【问题标题】:OpenGL rotate around global axis using glm::rotateOpenGL 使用 glm::rotate 围绕全局轴旋转
【发布时间】:2021-10-17 03:22:39
【问题描述】:

我正在尝试围绕全局轴旋转我的模型。这就是我所拥有的:

我创建了一个处理用户输入的方法。如果用户按下 A 或 D,模型将围绕 Z 轴向左或向右旋转 90 度。如果用户按下 W 或 S,它将围绕 X 轴向前或向后旋转 90 度。最后,如果用户按下 Q 或 E,它将围绕 Y 轴向左或向右旋转。但是如果我先在 x 轴上旋转,然后尝试在 y 轴上旋转,它会根据模型的局部轴旋转,而不是围绕全局轴旋转。

有人可以帮我解决这个问题吗?

以下是我处理模型输入的代码:

if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) {
    // reposition camera
    heartModel1 = true;
    heartModelX -= 30.0f;
    heartWallX -= 30.0f;
    heartModelZ += 30.0f;
    heartWallZ += 30.0f;
}
if (heartModel1) {
    // Rotate model
    // D -> Rotate Right
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
        heartAngleZ -= 90.0f;
    }
    // A -> Rotate left
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
        heartAngleZ += 90.0f;
    }
    // S -> Rotate back
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
        heartAngleX += 90.0f;
    }
    // W -> Rotate forward
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
        heartAngleX -= 90.0f;
    }
    // Q -> Rotate left on Y axis 
    if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {
        heartAngleY += 90.0f;
    }
}

以下是我的模型:

glm::mat4 modelHeart = glm::mat4(1.0f);
        modelHeart = glm::translate(modelHeart, glm::vec3(heartModelX + 30, heartModelY, heartModelZ - 30));
        modelHeart = glm::rotate(modelHeart, glm::radians(heartAngleX), glm::vec3(1.0f, 0.0, 0.0)); // Rotate on X axis
        modelHeart = glm::rotate(modelHeart, glm::radians(heartAngleY), glm::vec3(0.0, 1.0f, 0.0)); // Rotate on Y axis
        modelHeart = glm::rotate(modelHeart, glm::radians(heartAngleZ), glm::vec3(0.0, 0.0, 1.0f)); // Rotate on Z axis
        modelHeart = glm::scale(modelHeart, glm::vec3(heartModelScale, heartModelScale, heartModelScale));

【问题讨论】:

    标签: c++ opengl glfw glm-math


    【解决方案1】:

    您的代码中的旋转是累积的,因此如果您旋转一架飞机,例如,沿偏航(y 轴)然后向上俯仰(x 轴),它会在模型​​的局部空间中向上俯仰,无论它首先偏航到哪里,而不是在全局空间中。

    要进行全局转换,您需要实际更改转换的顺序,以始终与您正在执行的操作保持一致。可能最简单的方法是在帧之间保留modelHeart,这样它就会持续存在,您只需在帧之间修改它。

    当然,这只是在我正确解释问题的情况下。

    另一种方法,如果您没有特别设置它在全局空间中,则使用相同的法线但负角以与之前的旋转相反的方向旋转中间旋转的法线轴。

    也许是这样的?

    // back of the envelope psuedo-code
    #include <glm/gtx/rotate_vector.hpp>
    
    glm::vec3 xNorm(1.0, 0.0f, 0.0);
    glm::vec3 yNorm(0.0, 1.0f, 0.0);
    glm::vec3 zNorm(0.0, 0.0f, 1.0);
    modelHeart = glm::rotate(modelHeart, glm::radians(heartAngleX), xNorm); // Rotate on X axis
    yNorm = glm::rotate(yNorm, glm::radians(-heartAngleX), xNorm);
    modelHeart = glm::rotate(modelHeart, glm::radians(heartAngleY), yNorm); // Rotate on Y axis
    zNorm = glm::rotate(zNorm, glm::radians(-heartAngleY), yNorm);
    modelHeart = glm::rotate(modelHeart, glm::radians(heartAngleZ), zNorm); // Rotate on Z axis
    

    【讨论】:

    • 它可以部分工作,当我在 x 和 Y 轴上旋转时它可以工作,但是如果我尝试在 z 轴上旋转,它会像我在 y 轴上一样旋转
    • 我能够修复它,我只需添加 zNorm = glm::rotate(zNorm, glm::radians(-heartAngleX), xNorm);非常感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多