OpenGL:当我移动它时,相机会侧向倾斜

时间:2017-08-25 16:31:00

标签: c++ opengl glm-math

我试图在OpenGL中自己实现一个摄像头(我使用glfw和gml)。 至于现在,我没有任何课程。我稍后会创建它。所以这是我尝试编码相机的动作;它可以通过简单的鼠标移动工作,但否则,相机会侧向倾斜。我还是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矢量不会向上/向下倾斜,但它并没有解决问题。我还试图添加一个(全局)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);

但它并没有解决问题。有什么建议吗?

1 个答案:

答案 0 :(得分:3)

看起来你的右侧是全局X轴,Y轴在屏幕深处,Z轴向上。而你当地的相机轴系统是类似的。
所需的行为是将摄像机旋转到当前位置,左右鼠标移动围绕全局 Z旋转,上行鼠标移动围绕局部 X.仔细考虑这些旋转,直到你理解它们为止,以及为什么一个人在全球范围内,而另一个人围绕当地方向。想象一下安全摄像机及其运动,以显示轴系统和旋转。

目标是获取用于通过lookAt函数定义视图转换的参数。

首先围绕局部X旋转。我们通过反转当前的视图矩阵将此局部矢量转换为全局轴系统,您调用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);