OpenGL 使用 glm::rotate 围绕全局轴旋转

OpenGL rotate around global axis using glm::rotate

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

我创建了一个处理用户输入的方法。如果用户按下 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));

代码中的旋转是累积的,因此如果您旋转飞机,例如,沿偏航(y 轴),然后向上倾斜(x 轴),它会在模型​​的局部 space,无论它首先偏航在哪里,而不是在全局 space.

要进行全局转换,您需要实际更改转换的顺序,以始终与您按顺序进行的操作相匹配。可能最简单的方法是在帧之间保持 modelHeart,所以它会持续存在,你只需在帧之间修改它。

当然,前提是我对问题的理解是正确的。

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

也许是这样的?

// 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