Arcball camera inverting at 90 deg azimuth

风格不统一 提交于 2019-12-06 12:35:34

It's a common mistake to use lookAt for rotating the camera. You should not. The backward/right/up directions are the columns of your view matrix. If you already have them then you don't even need lookAt, which tries to redo some of your calculations. On the other hand, lookAt doesn't help you in finding those vectors in the first place.

Instead build the view matrix first as a composition of translations and rotations, and then extract those vectors from its columns:

void Visual::cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
    ...
    if (rightMousePressed)
    {
        GLfloat xoffset = (xpos - cursorPrevX) / 4.0;
        GLfloat yoffset = (cursorPrevY - ypos) / 4.0;

        camera.inclination = std::clamp(camera.inclination + yoffset, -90.f, 90.f);
        camera.azimuth = fmodf(camera.azimuth + xoffset, 360.f);

        view = glm::mat4();
        view = glm::translate(view, glm::vec3(0.f, 0.f, camera.radius)); // add camera.radius to control the distance-from-target
        view = glm::rotate(view, glm::radians(camera.inclination + 90.f), glm::vec3(1.f,0.f,0.f));
        view = glm::rotate(view, glm::radians(camera.azimuth), glm::vec3(0.f,0.f,1.f));
        view = glm::translate(view, camera.Target);

        camera.Right = glm::column(view, 0);
        camera.Up = glm::column(view, 1);
        camera.Front = -glm::column(view, 2); // minus because OpenGL camera looks towards negative Z.
        camera.Position = glm::column(view, 3);

        view = glm::inverse(view);
    }
    ...
}

Then remove the code that calculates view and the direction vectors from updateModelViewProjection and updateCameraVectors.

Disclaimer: this code is untested. You might need to fix a minus sign somewhere, order of operations, or the conventions might mismatch (Z is up or Y is up, etc...).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!