Reputation: 115
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));
Upvotes: 2
Views: 1369
Reputation: 13030
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
Upvotes: 2