gpt4 book ai didi

c++ - opengl 中鼠标输入背后的数学和偏航/俯仰值

转载 作者:行者123 更新时间:2023-11-30 04:59:11 25 4
gpt4 key购买 nike

您好,我正在尝试一些 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轴的正方向指向我们正在观看的窗口的顶部,yaw的增加意味着相机的方向 vector 应该向左旋转对吧?但在节目中,镜头转向并显示了场景的右侧部分。我不明白发生了什么。

如果我知道这里发生了什么,我想我就能理解为什么获取 yoffset 的计算顺序与获取 xoffset 值的计算顺序不同。

如有任何帮助,我们将不胜感激。如果我误解了任何数学概念或其他内容,请告诉我。提前致谢!

最佳答案

Since the positive direction of the y axis points to the top of the window we're watching, the increase in yaw means that the direction vector of the camera should rotate to the left direction right?

没有。 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,我们可以将其视为正向 vector 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 和 yaw 的完整公式,您会发现它等于:

front = R_y(-yaw) * R_z(pitch) * (1,0,0)^T

这只是一个复合旋转,首先将 (1,0,0) 围绕 z 轴旋转一个角度 pitch 以正缠绕顺序,然后将结果围绕 y 轴旋转一个角度 偏航负序。

我还认为您在此处引用的源代码的作者要么 a) 匆忙,要么 b) 对此处的数学运算方式有点困惑。我这么说有两个原因:

  1. 默认方向为 (0,0,-1),但欧拉角设置为 pitch=0, yaw=0 导致 (1,0,0) 观察方向,默认为 yaw=-90。人们可以用一种更清晰、更直观的方式来表述它,以便零角度产生默认的前视方向。

  2. 这里完全不需要lookAt 的使用。它将在内部进行的正交归一化只是对处理能力的浪费(按照今天的标准,这不是一个很大的浪费,但仍然如此)。使用 (0,1,0) 作为向上 vector 会在极点附近变得非常不稳定,并将 pitch 限制为 [-89,89] 只是一种防止这种情况发生的技巧。在这个导航模型中让相机向上或向下看实际上没有错(因为你只沿着一个二维平面移动,前向仍然由 yaw 单独定义,即使在看直线上升或下降)。这种情况引起的万向节锁定也​​无关紧要,因为后面根本没有第三次旋转。

    直接从两个旋转角度和相机位置直接创建 View 矩阵确实容易得多,并且完全避免了接近或完全 90 度的任何问题。

关于c++ - opengl 中鼠标输入背后的数学和偏航/俯仰值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51341126/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com