c++ - 基于四元数的相机不需要的滚动

标签 c++ opengl quaternions glm-math

我创建了一个基于四元数的相机,但是当我转动相机时,会出现不需要的滚动。我不想失去使用例如欧拉角的运动自由度,因为有时需要添加滚动。如果我使用欧拉角,那么据我所知,我可以获得万向节锁。

代码:

struct FreeCamera : public BaseCamera {
    float pitch = 0, yaw = 0, roll = 0;

    void updateView();

private:
    glm::quat qCamera;
};

struct FreeCameraController: public BaseCameraController {
    float sensitivityPitch = 0.0025f, sensitivityYaw = 0.0025f, sensitivityRoll = 0.0025f;

    void mouseMove(const float x, const float y, const float z = 0);

    inline void setMousePos(const float x, const float y, const float z = 0) {
        lastMousePos = glm::vec3(x, y, z);
    }

private:
    glm::vec3 lastMousePos = glm::vec3(0.0f);
};

void FreeCamera::updateView() {
    // temporary frame quaternion from pitch, yaw, roll
    glm::quat qPYR = glm::quat(glm::vec3(pitch, yaw, roll));
    // reset values
    pitch = yaw = roll = 0;

    // update qCamera
    qCamera = qPYR * qCamera;
    qCamera = glm::normalize(qCamera);
    glm::mat4 rotate = glm::mat4_cast(qCamera);

    glm::mat4 translate = glm::mat4(1.0f);
    translate = glm::translate(translate, -pos);

    view = rotate * translate;
}

void FreeCameraController::mouseMove(const float x, const float y, const float z) {
    glm::vec3 dCoord = glm::vec3(x, y, z) - lastMousePos;

    ((FreeCamera*)camera)->yaw = dCoord.x * sensitivityYaw;
    ((FreeCamera*)camera)->pitch = dCoord.y * sensitivityPitch;
    ((FreeCamera*)camera)->roll = dCoord.z * sensitivityRoll;

    lastMousePos = glm::vec3(x, y, z);
}

是否可以重置不需要的滚动,“稳定”相机?

最佳答案

当你想要阻止滚动(如果它是一辆汽车,可能也会偏航,因为你会让汽车飞起来),你必须通过连接旋转来阻止其中一个轴。您想要实现的是实际的万向节锁定(在专门飞行时使用包含所有旋转的单个四元数来摆脱它)。因此,假设您可以检测车辆是否在地面上:

glm::mat4 rotationMatrix;
// When you want to get rid of any axis rotation, you must lock it
if(onGround)
{
    glm::quat yawQ = glm::quat(glm::vec3(0.0f, yaw, 0.0f));
    yawQ = glm::normalize(yawQ);
    glm::mat4 yawMat = glm::mat4_cast(yawQ);

    glm::quat pitch = glm::quat(glm::vec3(pitch, 0.0f, 0.0f));
    pitch = glm::normalize(pitch);
    glm::mat4 pitchMat = glm::mat4_cast(pitch);

    rotationMatrix = pitchMat * yawMat;
}
else
{
  //Your computation
  rotationMatrix = glm::mat4_cast(yourQuaternion);
}

viewMatrix = rotationMatrix * translationMatrix;

注意,不一定要使用四元数才能达到地面控制效果

关于c++ - 基于四元数的相机不需要的滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57210185/

相关文章:

c++ - QGLWidget - 3-D 空心物体的横截面

game-physics - 正交基四元数

c++ - 将 CGAL 与四元数结合起来合乎逻辑吗

c++ - 有没有办法将四元数转换为角度?

c++ - 从构造函数调用虚函数

c++ - Singleton 被构造两次

c++ - 外部 C 和结构方法

c++ - 对类里面的 C++ 引用感到困惑

opengl - OpenGL GL_COLOR_BUFFER_BIT 属性位是否表示深度和模板缓冲区相关状态?

c++ - 尝试为屏幕的每个像素着色时出现线条?