标签:调用 rspec last 原理 滚轮 dia 结果 就会 矩阵
一、隐藏并捕捉光标
偏航角和俯仰角是通过鼠标移动获得的,水平的移动影响偏航角,竖直的移动影响俯仰角。
原理是,存储上一帧鼠标的位置,在当前帧中计算鼠标位置与上一帧的位置相差多少。如果水平/竖直差别越大,那么俯仰角或偏航角就改变越大,也就是摄像机需要移动更多的距离。
首先我们应该告诉GLFW,它应该隐藏光标,并捕捉它。
结果:无论我们怎样移动鼠标,光标都不会显示,但它也不会离开窗口。
glfwSetInputMode(window,GLFW_CURSOR,GLFW_CURSOR_DISABLED);
二:监听鼠标移动事件
为了计算俯仰角和偏航角,我们需要让GLFW监听鼠标移动事件(和键盘输入相似)。用一个回调函数来完成,函数原型如下:
void mouse_callback(GLFWwindow *window,double xpos,double ypos);
xpos,ypos代表当前鼠标的位置。当我们用GLFW注册了回调函数之后,鼠标一移动mouse_callback函数就会被调用:
1 glfwSetCursorCallback(window,mouse_callback);
三、在处理FPS风格摄像机的鼠标输入的时候,我们必须在最终获取方向向量之前做下面这几步:
1、计算鼠标距上一帧的偏移量
2、把偏移量添加到摄像机的俯仰角和偏航角中
3、对俯仰角和偏航角进行最大和最小值的限制
4、计算方向向量
第一步:计算鼠标距上一帧的偏移量,所以必须在程序中存储上一帧的鼠标位置,我们把它的初始值设置为屏幕的中心
1 float lastX = screenWidth/2.0f; 2 float lastY = screenHeight/2.0f;
第二步:在鼠标的回调函数中计算当前帧和上一帧鼠标位置的偏移量:
1 float xoffest = xpos-lastX; 2 float yoffset = lastY - ypos;//注意这里是相反的,因为y坐标是从底部往顶部依次增大的 3 lastX = xpos; 4 lastY = ypos; 5 6 float sensitivity = 0.05f; 7 xoffest *= sensitivity; 8 yoffest *= sensitivity;
注意我们把偏移量乘以了sensitivity(灵敏度)值。如果我们忽略这个值,鼠标移动就会太大了
俯仰角(Pitch)、偏航角(Yaw)
接下来我们把偏移量加到全局变量pitch和yaw上
1 yaw +=xoffset; 2 pitch +=yoffset;
第三步:给摄像机添加一些限制,这样摄像机就不会发生奇怪的移动了。对于俯仰角,要让用户不能看高于89度的地方(在90度是视角会发生逆转,所以我们把89度看成极限),同样也不允许-89度。
1 if(pitch>89.0f) 2 pitch = 89.0f; 3 if(pitch <-89.0f) 4 pitch = -89.0f;
注意到我们没有给偏航角设置限制,这是因为我们不希望限制用户的水平旋转。
第四步:通过俯仰角和偏航角来计算得到真正的方向向量:
1 glm::vec3 front; 2 front.x = cos(glm::radians(pith))*cos(glm::radians(yaw)); 3 front.y = sin(glm::radians(pitch)); 4 front.z = cos(glm::radians(pith))*cos(glm::radians(yaw)); 5 cameraFront = glm::normolize(front);
计算出来的方向向量就会包含根据鼠标移动计算出来所有的旋转了。
我们可以简单的使用一个bool
变量检验我们是否是第一次获取鼠标输入,如果是,那么我们先把鼠标的初始位置更新为xpos和ypos值,这样就能解决这个问题;接下来的鼠标移动就会使用刚进入的鼠标位置坐标来计算偏移量了:
1 if(firstMouse)//这个bool变量初始时是设定为true的 2 { 3 lastX = xpos; 4 lastY = ypos; 5 firstMouse = false; 6 }
最后的代码应该是这样的:
1 void mouse_callback(GLFWwindow* window, double xpos, double ypos) 2 { 3 if(firstMouse) 4 { 5 lastX = xpos; 6 lastY = ypos; 7 firstMouse = false; 8 } 9 10 float xoffset = xpos - lastX; 11 float yoffset = lastY - ypos; 12 lastX = xpos; 13 lastY = ypos; 14 15 float sensitivity = 0.05; 16 xoffset *= sensitivity; 17 yoffset *= sensitivity; 18 19 yaw += xoffset; 20 pitch += yoffset; 21 22 if(pitch > 89.0f) 23 pitch = 89.0f; 24 if(pitch < -89.0f) 25 pitch = -89.0f; 26 27 glm::vec3 front; 28 front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); 29 front.y = sin(glm::radians(pitch)); 30 front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); 31 cameraFront = glm::normalize(front); 32 }
三、缩放
实现一个缩放(Zoom)接口。在之前的教程中我们说视野(Field of View)或fov定义了我们可以看到场景中多大的范围。当视野变小时,场景投影出来的空间就会减小,产生放大(Zoom In)了的感觉。我们会使用鼠标的滚轮来放大。与鼠标移动、键盘输入一样,我们需要一个鼠标滚轮的回调函数:
1 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) 2 { 3 if(fov >= 1.0f && fov <= 45.0f) 4 fov -= yoffset; 5 if(fov <= 1.0f) 6 fov = 1.0f; 7 if(fov >= 45.0f) 8 fov = 45.0f; 9 }
当滚动鼠标滚轮的时候,yoffset值代表我们竖直滚动的大小。当scroll_callback函数被调用后,我们改变全局变量fov变量的内容。因为45.0f
是默认的视野值,我们将会把缩放级别(Zoom Level)限制在1.0f
到45.0f
。
我们现在在每一帧都必须把透视投影矩阵上传到GPU,但现在使用fov变量作为它的视野:
projection = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);
最后不要忘记注册鼠标滚轮的回调函数:
glfwSetScrollCallback(window, scroll_callback);
标签:调用 rspec last 原理 滚轮 dia 结果 就会 矩阵
原文地址:https://www.cnblogs.com/keguniang/p/9949855.html