OpenGL:当我移动相机时,相机会向侧面倾斜
OpenGL: Camera tilts sideways when I move it
我正在尝试自己在 OpenGL 中实现一个相机(我使用 glfw 和 gml)。
至于现在,我没有任何class。我稍后会创建它。所以这是我对相机运动编码的尝试;它可以通过简单的鼠标移动正常工作,但否则,相机会向侧面倾斜。我还是 OpenGL 的新手,所以我没有太多东西可以展示,但这里说明了我的问题:http://imgur.com/a/p9xXQ
我有几个(目前是全局的)变量:
float lastX = 0.0f, lastY = 0.0f, yaw = 0.0f, pitch = 0.0f;
glm::vec3 cameraPos(0.0f, 0.0f, 3.0f);
glm::vec3 cameraUp(0.0f, 1.0f, 0.0f); // As a reminder, x points to the right, y points upwards and z points towards you
glm::vec3 cameraFront(0.0f, 0.0f, -1.0f);
有了这些,我可以这样创建一个视图矩阵:
glm::mat4 view;
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
我希望能够垂直(偏航)和横向(俯仰)移动我的相机,即在我的屏幕上向上、向下、向右、向左移动。为此,适当旋转 cameraFront 向量和 cameraUp 向量,然后用更新后的向量更新视图矩阵就足够了。
我的光标位置回调看起来像这样:
glm::vec3 rotateAroundAxis(glm::vec3 toRotate, float angle, glm::vec3 axisDirection, glm::vec3 axisPoint) { // angle in radians
toRotate -= axisPoint;
glm::mat4 rotationMatrix(1.0f);
rotationMatrix = glm::rotate(rotationMatrix, angle, axisDirection);
glm::vec4 result = rotationMatrix*glm::vec4(toRotate, 1.0f);
toRotate = glm::vec3(result.x, result.y, result.z);
toRotate += axisPoint;
return toRotate;
}
void mouseCallback(GLFWwindow* window, double xpos, double ypos) {
const float maxPitch = float(M_PI) - float(M_PI) / 180.0f;
glm::vec3 cameraRight = -glm::cross(cameraUp, cameraFront);
float xOffset = xpos - lastX;
float yOffset = ypos - lastY;
lastX = xpos;
lastY = ypos;
float sensitivity = 0.0005f;
xOffset *= sensitivity;
yOffset *= sensitivity;
yaw += xOffset; // useless here
pitch += yOffset;
if (pitch > maxPitch) {
yOffset = 0.0f;
}
if (pitch < -maxPitch) {
yOffset = 0.0f;
}
cameraFront = rotateAroundAxis(cameraFront, -xOffset, cameraUp, cameraPos);
cameraFront = rotateAroundAxis(cameraFront, -yOffset, cameraRight, cameraPos);
cameraUp = rotateAroundAxis(cameraUp, -yOffset, cameraRight, cameraPos);
}
正如我所说,它适用于简单的上下、左右相机移动,但当我开始以圆圈或像疯子一样移动鼠标时,相机开始纵向旋转(滚动)。
我试图强制 cameraRight.y = cameraPos.y 使 cameraRight 向量不会因数值错误而倾斜 upwards/downwards 但它并没有解决问题。我还尝试添加一个(全局)cameraRight 向量来跟踪它而不是每次都计算它,所以函数的结尾如下所示:
cameraFront = rotateAroundAxis(cameraFront, -xOffset, cameraUp, cameraPos);
cameraRight = rotateAroundAxis(cameraRight, -xOffset, cameraUp, cameraPos);
cameraFront = rotateAroundAxis(cameraFront, -yOffset, cameraRight, cameraPos);
cameraUp = rotateAroundAxis(cameraUp, -yOffset, cameraRight, cameraPos);
但是并没有解决问题。有什么建议吗?
您的全局 X 轴似乎在右侧,Y 轴在屏幕深处,Z 轴在上。和你本地的相机轴系统是相似的。
期望的行为是在当前位置上旋转相机,左右鼠标移动是围绕 global Z 旋转,上下鼠标移动是围绕 local X. 围绕这些旋转思考一下,直到你很好地理解它们,以及为什么一个围绕全局方向而另一个围绕局部方向。想象一个安全摄像头及其运动,以可视化轴系统和旋转。
目标是通过lookAt
函数获取用于定义视图转换的参数。
首先围绕局部X旋转。我们通过反转当前View-matrix将这个局部向量转换为全局轴系,你调用view
glm::vec3 currGlobalX = glm::normalize((glm::inverse(view) * glm::vec4(1.0, 0.0, 0.0, 0.0)).xyz);
我们不仅需要旋转cameraUp
向量,还需要旋转全局坐标中定义的current target
,你说的cameraPos + cameraFront
:
cameraUp = rotateAroundAxis(cameraUp, -yOffset, currGlobalX, glm::vec3(0.0f, 0.0f, 0.0f)); //vector, not needed to translate
cameraUp = glm::normalize(cameraUp);
currenTarget = rotateAroundAxis(currenTarget, -yOffset, currGlobalX, cameraPos); //point, need translation
现在绕全局 Z 轴旋转
cameraUp = rotateAroundAxis(cameraUp, -xOffset, glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); //vector, not needed to translate
cameraUp = glm::normalize(cameraUp);
currenTarget = rotateAroundAxis(currenTarget, -xOffset, glm::vec3(0.0f, 0.0f, 1.0f), cameraPos); //point, need translation
最后,更新view
:
view = glm::lookAt(cameraPos, currenTarget, cameraUp);
我正在尝试自己在 OpenGL 中实现一个相机(我使用 glfw 和 gml)。 至于现在,我没有任何class。我稍后会创建它。所以这是我对相机运动编码的尝试;它可以通过简单的鼠标移动正常工作,但否则,相机会向侧面倾斜。我还是 OpenGL 的新手,所以我没有太多东西可以展示,但这里说明了我的问题:http://imgur.com/a/p9xXQ
我有几个(目前是全局的)变量:
float lastX = 0.0f, lastY = 0.0f, yaw = 0.0f, pitch = 0.0f;
glm::vec3 cameraPos(0.0f, 0.0f, 3.0f);
glm::vec3 cameraUp(0.0f, 1.0f, 0.0f); // As a reminder, x points to the right, y points upwards and z points towards you
glm::vec3 cameraFront(0.0f, 0.0f, -1.0f);
有了这些,我可以这样创建一个视图矩阵:
glm::mat4 view;
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
我希望能够垂直(偏航)和横向(俯仰)移动我的相机,即在我的屏幕上向上、向下、向右、向左移动。为此,适当旋转 cameraFront 向量和 cameraUp 向量,然后用更新后的向量更新视图矩阵就足够了。
我的光标位置回调看起来像这样:
glm::vec3 rotateAroundAxis(glm::vec3 toRotate, float angle, glm::vec3 axisDirection, glm::vec3 axisPoint) { // angle in radians
toRotate -= axisPoint;
glm::mat4 rotationMatrix(1.0f);
rotationMatrix = glm::rotate(rotationMatrix, angle, axisDirection);
glm::vec4 result = rotationMatrix*glm::vec4(toRotate, 1.0f);
toRotate = glm::vec3(result.x, result.y, result.z);
toRotate += axisPoint;
return toRotate;
}
void mouseCallback(GLFWwindow* window, double xpos, double ypos) {
const float maxPitch = float(M_PI) - float(M_PI) / 180.0f;
glm::vec3 cameraRight = -glm::cross(cameraUp, cameraFront);
float xOffset = xpos - lastX;
float yOffset = ypos - lastY;
lastX = xpos;
lastY = ypos;
float sensitivity = 0.0005f;
xOffset *= sensitivity;
yOffset *= sensitivity;
yaw += xOffset; // useless here
pitch += yOffset;
if (pitch > maxPitch) {
yOffset = 0.0f;
}
if (pitch < -maxPitch) {
yOffset = 0.0f;
}
cameraFront = rotateAroundAxis(cameraFront, -xOffset, cameraUp, cameraPos);
cameraFront = rotateAroundAxis(cameraFront, -yOffset, cameraRight, cameraPos);
cameraUp = rotateAroundAxis(cameraUp, -yOffset, cameraRight, cameraPos);
}
正如我所说,它适用于简单的上下、左右相机移动,但当我开始以圆圈或像疯子一样移动鼠标时,相机开始纵向旋转(滚动)。
我试图强制 cameraRight.y = cameraPos.y 使 cameraRight 向量不会因数值错误而倾斜 upwards/downwards 但它并没有解决问题。我还尝试添加一个(全局)cameraRight 向量来跟踪它而不是每次都计算它,所以函数的结尾如下所示:
cameraFront = rotateAroundAxis(cameraFront, -xOffset, cameraUp, cameraPos);
cameraRight = rotateAroundAxis(cameraRight, -xOffset, cameraUp, cameraPos);
cameraFront = rotateAroundAxis(cameraFront, -yOffset, cameraRight, cameraPos);
cameraUp = rotateAroundAxis(cameraUp, -yOffset, cameraRight, cameraPos);
但是并没有解决问题。有什么建议吗?
您的全局 X 轴似乎在右侧,Y 轴在屏幕深处,Z 轴在上。和你本地的相机轴系统是相似的。
期望的行为是在当前位置上旋转相机,左右鼠标移动是围绕 global Z 旋转,上下鼠标移动是围绕 local X. 围绕这些旋转思考一下,直到你很好地理解它们,以及为什么一个围绕全局方向而另一个围绕局部方向。想象一个安全摄像头及其运动,以可视化轴系统和旋转。
目标是通过lookAt
函数获取用于定义视图转换的参数。
首先围绕局部X旋转。我们通过反转当前View-matrix将这个局部向量转换为全局轴系,你调用view
glm::vec3 currGlobalX = glm::normalize((glm::inverse(view) * glm::vec4(1.0, 0.0, 0.0, 0.0)).xyz);
我们不仅需要旋转cameraUp
向量,还需要旋转全局坐标中定义的current target
,你说的cameraPos + cameraFront
:
cameraUp = rotateAroundAxis(cameraUp, -yOffset, currGlobalX, glm::vec3(0.0f, 0.0f, 0.0f)); //vector, not needed to translate
cameraUp = glm::normalize(cameraUp);
currenTarget = rotateAroundAxis(currenTarget, -yOffset, currGlobalX, cameraPos); //point, need translation
现在绕全局 Z 轴旋转
cameraUp = rotateAroundAxis(cameraUp, -xOffset, glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); //vector, not needed to translate
cameraUp = glm::normalize(cameraUp);
currenTarget = rotateAroundAxis(currenTarget, -xOffset, glm::vec3(0.0f, 0.0f, 1.0f), cameraPos); //point, need translation
最后,更新view
:
view = glm::lookAt(cameraPos, currenTarget, cameraUp);