opengl中鼠标输入背后的数学和偏航/俯仰值
Math behind the mouse input in opengl and the yaw/pitch values
嗨,我正在尝试一些c++opengl代码,并制作了一台相机。我想给场景一个鼠标输入来四处查看,所以我添加了这个代码,就像这里的教程一样。https://learnopengl.com/Getting-started/Camera
然而,关于偏航和俯仰值,我不理解一些数学概念。这是鼠标移动的回调函数。
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
if (firstMouse) //preventing large jumps
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos;
lastX = xpos;
lastY = ypos;
float sensitivity = 0.1f;
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
//cameraFront is the direction vector of the camera. Where the camera is looking at
cameraFront = glm::normalize(front);
}
以下是全局变量及其初始值,用于mouse_callback函数以防万一。
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
//lookAt function requires position, target's position, up vector respectively.
有两件事我不明白。据我所知,偏航和俯仰分别是从y轴和x轴计算得出的。用我们的右手,把拇指朝着轴的+方向,其他手指弯曲的方向就是角度的正方向。
现在假设我在不改变yoffset的情况下将鼠标向右移动。然后,根据mouse_callback函数,由于xoffset为正,因此偏航值会增加。由于y轴的正方向指向我们正在观看的窗口的顶部,因此偏航的增加意味着相机的方向矢量应该向左旋转?但在节目中,镜头转向并显示了场景的右侧部分。我不明白发生了什么。
如果我知道这里发生了什么,我想我可以理解为什么获得yoffset的计算顺序与获得xoffset值不同。
如有任何帮助,我们将不胜感激。如果我弄错了任何数学概念或其他什么,请告诉我。提前感谢!
由于y轴的正方向指向我们正在观看的窗口的顶部,偏航的增加意味着相机的方向矢量应该向左旋转?
否。y
轴的方向与此处的任何内容都无关。当pitch
为0时,给出的公式等于:
front.x = cos(glm::radians(yaw))
front.y = 0
front.z = sin(glm::radians(yaw));
因此,如果偏航为0,则会得到(1,0,0)
(右(。如果你把它增加到90度,你会得到(0,0,1)
,它在右手坐标系中直接指向后面,所以你就向右转了。
你似乎以某种方式将其与正旋转方向联系起来,当绕y旋转时,正旋转方向总是从z到x。但这些公式并没有实现绕y轴的正旋转角度yaw
,但它们实际上旋转了-yaw
:由于系统设置为在角度0处产生+x,我们可以将其视为正向矢量v= (1,0,0)
绕轴y的旋转,因此经典旋转矩阵将产生:
( cos(yaw) 0 sin(yaw) ) ( cos(yaw) )
v' = ( 0 1 0 ) * v = ( 0 )
( -sin(yaw) 0 cos(yaw) ) (-sin(yaw) )
然而,当你以负旋转方向旋转时,你最终得到的是转置矩阵,只是翻转sin
:的减号
( cos(yaw) 0 -sin(yaw) ) ( cos(yaw) )
v' = ( 0 1 0 ) * v = ( 0 )
( sin(yaw) 0 cos(yaw) ) ( sin(yaw) )
所以它只是
front = R_y ( -yaw) * (1,0,0)^T
如果你看看pitch
和偏航的完整公式,你会注意到它将等于:
front = R_y(-yaw) * R_z(pitch) * (1,0,0)^T
这只是一个复数旋转,首先以正缠绕顺序绕z轴旋转(1,0,0(角度pitch
,然后以负缠绕顺序绕y轴旋转角度yaw
。
我还认为,你在这里引用的源代码的作者要么a(很匆忙,要么b(只是对这里的数学运算有点困惑。我这么说有两个原因:
默认方向为(0,0,-1(,但欧拉角设置为
pitch=0
,yaw=0
产生(1,0,0(观察方向,默认为yaw=-90
。人们本可以用一种更干净、更直观的方式来表述它,这样零角度就可以产生默认的前瞻性方向。这里完全不需要使用
lookAt
。它将在内部进行正交归一化只是浪费处理能力(以今天的标准来看,这不是一个很大的问题,但尽管如此(。使用(0,1,0)
作为上矢量在极点附近会变得非常不稳定,将pitch
限制为[-89,89]
只是防止这种情况发生的一种方法。实际上,在这个导航模型中,让相机直视上下并没有错(因为你只沿着2D平面移动,所以即使直视上下,前进方向仍然由yaw
单独定义(。这种情况引起的万向节锁定也不相关,因为接下来根本没有第三次旋转。实际上,直接从两个旋转角度和相机位置创建视图矩阵要容易得多,并且完全避免在接近或完全90度时出现任何问题。
- opengl中鼠标输入背后的数学和偏航/俯仰值
- SDL C++鼠标输入处理切换效果
- GetAsyncKeyState 未检测到鼠标输入
- 鼠标输入和键输入有什么区别(在前台获取窗口)
- 跟踪鼠标输入事件
- 如何使用Win32 API阻止来自透明窗口的鼠标输入?
- QT4.8嵌入.使用QCursor :: SetPos()调整鼠标输入会导致一个抽搐的光标
- C++ WinAPI - 草率的鼠标输入
- 打开GL/Glut绘制的线未从鼠标输入显示
- Windows C - 需要想法 - 在同一应用/窗口中将鼠标输入和原始输入组合在一起
- C++编译器,形状,如何在鼠标输入上更改颜色
- 鼠标输入:MOUSEEVENTF_MOVE移动不根据dx,dy
- SDL - 鼠标输入
- 发送输入发送鼠标输入和键盘输入
- 使用 Windows 的原始鼠标输入
- 如何将键盘和鼠标输入发送到不是Windows7上活动窗口的游戏
- 原始鼠标输入的解释
- c++键盘/鼠标输入
- 如何在GTK中获得键盘和鼠标输入
- c++ Directx鼠标输入焦点丢失后行为怪异