Gediminas
Gediminas

Reputation: 1860

How to extract yaw pitch roll from glm::quat and glm::mat4

Is it possible to extract the yaw, pitch and roll information from the glm::mat4? (That is a world transformation matrix with the translation, rotation and scale already applied)

Here is some code that I'm experimenting with:

    float yawDeg = 0;
    float pitchDeg = 20;
    float rollDeg = 80;

    glm::mat4 transform = glm::eulerAngleYXZ(glm::radians(yawDeg), glm::radians(pitchDeg), glm::radians(rollDeg));

    glm::quat rotation(transform); // Is this a correct way?
 // glm::quat rotation(glm::quat_cast(transform)); // Gives the same results.

    printf("pitch: %f\n", glm::degrees(glm::pitch(rotation))); // Output:   3.616443
    printf("yaw:   %f\n", glm::degrees(glm::yaw(rotation)));   // Output: -19.683496
    printf("roll:  %f\n", glm::degrees(glm::roll(rotation)));  // Output:  79.372414

But I'm getting some strange results, here are some values:

yawDeg=92, pitchDeg=0, rollDeg=0 results yaw: 88.0, pitch: 180.0, roll: 180.0

yawDeg=0, pitchDeg=92, rollDeg=0 results yaw: 0.0, pitch: 92.0, roll: 0.0 - Looks ok.

yawDeg=0, pitchDeg=0, rollDeg=92 results yaw: 0.0, pitch: 0.0, roll: 92.0 - Looks ok.

yawDeg=0, pitchDeg=10, rollDeg=92 results yaw: -9.993845, pitch: -0.352578, roll: 92.030830

I think maybe my glm::mat4 to glm::quat conversion is incorrect?

Upvotes: 0

Views: 4442

Answers (3)

Jeroen Koffeman
Jeroen Koffeman

Reputation: 51

Did you try using glm::eulerAngleYXZ? (YXZ instead of XYZ). That way the rotation construction is returned in the same order as your input eulerAngles.

Upvotes: 0

true
true

Reputation: 11

There is one thing I'd like to add. Yaw degree from GLM is actually between −90°~90°. It's because GLM get the yaw angle from arcsine, and −90°~90° is the range of usual principal value you can get from that.

Here you can see a snippet of the code from the github of GLM, https://github.com/g-truc/glm/blob/master/glm/gtc/quaternion.inl#L41

Upvotes: 1

Gediminas
Gediminas

Reputation: 1860

The reason why I was getting those unexpected values was because in certain angles GLM is internally applying it's own angles. I.e for:

Input yawDeg=60, pitchDeg=0, rollDeg=0 we'll get yaw: 60.0, pitch: 0.0, roll: 0.0 - as expected.

And for:

Input yawDeg=92, pitchDeg=0, rollDeg=0 we'll get yaw: 88.0, pitch: 180.0, roll: 180.0 - modified!

If you would look visually at the 3D object with those transformations applied - all rotations should look ok even if GLM have modified the values internally.

Another thing I've noticed is that Euler angles returned by GLM are always in the range of -180, 180 degrees for all axis.

Regarding the glm::mat4 to glm::quat conversion. I was doing everyting ~ok. The important thing to note here is that if you're using scaling in your transformation matrix, you need to normalize your quaternion!

glm::quat rotation = glm::normalize(glm::quat_cast(matrix));

Another thing I found was that GLM has a function called glm::extractEulerAngleXYZ. So if you just want to extract Euler angles from your transformation matrix, you don't really need to do any conversion to the quaternion.

I'm still not fully satisfied, because I did not find any way to convert GLM's Euler angle values back to the original values that were provided by the user.

Upvotes: 0

Related Questions