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

19,752

Solution 1

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!

Solution 2

The order of multiplication is important when dealing with Euler angles. YXZ and XYZ produce very different rotations.

You could calculate separate matrices for each axis, and then multiply them together in the order your need.

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

glm::mat4 transformX = glm::eulerAngleX(euler.x);
glm::mat4 transformY = glm::eulerAngleY(euler.y);
glm::mat4 transformZ = glm::eulerAngleZ(euler.z);

glm::mat4 transform1 =
    transformX * transformY * transformZ; // or some other order

Solution 3

I think the result is radian already, no need to convert.

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

glm::mat4 transformX = glm::eulerAngleX(euler.x);
glm::mat4 transformY = glm::eulerAngleY(euler.y);
glm::mat4 transformZ = glm::eulerAngleZ(euler.z);

glm::mat4 transform1 =
    transformX * transformY * transformZ; // or some other order
Share:
19,752

Related videos on Youtube

iondune
Author by

iondune

I'm a software engineering and computer science graduate student and infrequent intern at a variety of companies.

Updated on June 04, 2022

Comments

  • iondune
    iondune almost 2 years

    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
    
    • wardw
      wardw almost 4 years
      Aside: at least as of 0.9.9 glm::eulerAngles(q) returns its result in radians. See glm/gtc/quaternion.hpp.
  • JCooper
    JCooper over 11 years
    It seems that this will suffer from the exact same problems. The Euler angles are only valid for the order they're computed for. Putting them into matrices doesn't undo that fact.
  • iondune
    iondune over 11 years
    @Markus I considered that my conversion of euler angles to matrix could be the problem, but there is a discrepancy before that stage. For example, the quaternions (0.5, -0.5, 0.5, 0.5) and (0.707106, 0, 0.707106, 0) both convert to euler angles (0, 90, 0), despite representing two distinct rotations (+Z to +Y and +Z to +X respectively) when converted directly to a matrix.
  • wardw
    wardw almost 4 years
    Yes, noticed this too, and at least as of 0.9.9 is stated as returning radians in glm/gtc/quaternion.hpp. I assume GLM changed this at some point since the original question in 2012. (Bet that was fun for some).