2

I am trying to rotate my model around the global axis. This is what I have:

I created a method that would process the user input. If the user presses A or D, the model will rotate 90 degrees to the left or to the right around the Z axis. If the user presses W or S, it will rotate 90 degrees forward or backward around the X axis. Finally, it the user presses Q or E, it will rotate around the Y axis to the left or to the right. But if I rotate on the x axis and then try to rotate on the y axis, it will rotate depending on the local axis of the model, not around the global axis.

Can someone help me fix this?

The following is my code to process the inputs for my model:

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;
    }
}

The following is my model:

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));
genpfault
  • 51,148
  • 11
  • 85
  • 139
Jennifer
  • 115
  • 9

1 Answers1

2

The rotations in your code are cumulative, so if you rotate a airplane for instance, along the yaw (y-axis), then pitch up (x-axis), it'll pitch nose-up in the model's local space, no matter where it yaw'd first, instead of in the global space.

To have a global transform, you'd need to actually change the order of your transforms to always match what you're doing in order. Probably the easiest way to do that would be to keep modelHeart around between frames, so it persists, and you just modify it between frames.

Of course, that's just if I'm interpreting the problem right.

Another way, if you aren't particularly set on it being in a global space, is to rotate the middle rotation's normal axis in the opposite direction to the rotation before it, using the same normal but the negative angle.

Maybe something like this?

// 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
Anne Quinn
  • 12,609
  • 8
  • 54
  • 101
  • It works partially, it works when I rotate on the x and Y axis, but if I try to rotate on the z axis, it rotates as if I was in the y axis – Jennifer Aug 14 '21 at 03:25
  • I was able to fix it, I simply had to add zNorm = glm::rotate(zNorm, glm::radians(-heartAngleX), xNorm); Thank you very much for your help – Jennifer Aug 14 '21 at 03:27