Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quaternions -> Euler Angles -> Rotation Matrix trouble (GLM)

I'm writing a program that loads a file containing a scene description and then displays it using OpenGL. I'm using GLM for all of my math operations. Rotations in the scene file are stored in quaternion format. My scene management systems takes rotations for objects in the form of euler angles, and these angles are later converted to a rotation matrix when drawing.

My loading process thus takes the quaternion rotations, converts them to euler angles for storage in my object class, then converts these euler angles to rotation matrices for drawing. I'm using the glm::eulerAngles and glm::eulerAngleYXZ functions (respectively) to perform these two operations.

However, I am getting incorrect results. For example, if I understand correctly the quaternion {0.500 -0.500 0.500 0.500} (that's W X Y Z) should describe the rotation taking an arrow from the +Z axis to the +Y axis. When I run the program, however, I get the arrow pointing along the +X axis.

I would assume that there is some flaw in my understanding of the quaternions, but I am able to get my expected results by skipping the intermediary euler angle form. By converting the quaternion directly to a rotation matrix using glm::toMat4, I get a rotation that points my +Z arrow towards +Y.

I'm having trouble reconciling these two different outputs, considering that both methods seem both simple and correct. To simplify my question, why is it that these two seemingly equivalent methods produce different results:

glm::quat q(.5, -.5, .5, .5);
glm::vec3 euler = glm::eulerAngles(q) * 3.14159f / 180.f; // eulerAngleYXZ takes radians but eulerAngles returns degrees
glm::mat4 transform1 = glm::eulerAngleYXZ(euler.y, euler.x, euler.z);
// transform1 rotates a +Z arrow so that it points at +X

glm::quat q(.5, -.5, .5, .5);
glm::mat4 transform2 = glm::toMat4(q);
// transform2 rotates a +Z arrow so that it points at +Y
like image 840
iondune Avatar asked Aug 21 '12 03:08

iondune


People also ask

Does GLM use quaternions?

The glm::mat4_cast function converts a quaternion into a 4x4 rotation matrix. This stands in place of the series of 3 rotations used in the last tutorial.

How do you convert a rotation matrix to Euler angles?

Given a rotation matrix R, we can compute the Euler angles, ψ, θ, and φ by equating each element in R with the corresponding element in the matrix product Rz(φ)Ry(θ)Rx(ψ). This results in nine equations that can be used to find the Euler angles. Starting with R31, we find R31 = − sin θ.

Are quaternions better than Euler angles?

Quaternions are absolutely more accurate. There is a problem called Gimbal lock which was found in Euler angles. It happens when two axis align together. On the other hand quaternions are more flexible and solved this problem as it is more axis oriented.

Why might you choose quaternions over Euler angles?

Quaternions provide smooth interpolation of animated rotations and always produce the most efficient path between keyframes in comparison to Euler angles. Quaternions store the overall orientation of an object rather than a series of individual rotations.


1 Answers

You have probably figured this out by now... but

What eulerAngle sequence does the function:

glm::vec3 euler = glm::eulerAngles(q) * 3.14159f / 180.f;

return? If it does not return explicitly an 'YXZ' sequence, you will not be able to use the next function properly:

glm::mat4 transform1 = glm::eulerAngleYXZ(euler.y, euler.x, euler.z);

Your variable 'euler' must be the same sequence type as the function you specify to transform it into a rotation matrix.

After looking here it looks like the function 'glm::eulerAngles' returns 'XYZ' as pitch, yaw, and roll. Thus, assuming they are 'YXZ', or yaw, pitch, roll is incorrect.

As said before, with Euler angles and rotation matrices, order matters!

like image 162
dinkelk Avatar answered Sep 18 '22 05:09

dinkelk