c++ - OpenGL 使用 glm::rotate 绕全局轴旋转

标签 c++ opengl glfw glm-math

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

我创建了一个处理用户输入的方法。如果用户按 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 轴),它将在模型的局部空间中向上倾斜,无论它首先偏航到哪里,而不是在全局空间。

要进行全局转换,您需要实际更改转换的顺序,以始终与您正在执行的操作按顺序匹配。也许最简单的方法是在帧之间保留 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

关于c++ - OpenGL 使用 glm::rotate 绕全局轴旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68779716/

相关文章:

opengl - 了解OpenGL矩阵

c++ - SOIL 图像库和释放内存

c++ - 为什么元组不会收到未使用的变量警告?

c++ - 为什么定义析构函数会删除隐式定义的移动赋值运算符?

c++ - char 的实现定义是否影响 std::string?

c++ - 按键时更改 GLFWwindow 的背景

c++ - 从回调函数访问实例

c++ - 标记为 bitset 和 uint64_t 的并集

opengl - OpenGL 的自定义混合方程(着色器)

glfw - Oculus Rift 是否可以与 Quadro M1000M 配合用于非游戏用途?