GLM: Initializing Quaternion with Eular XYZ

Dear all,

this question will be most of you elementary, but I can not find a way: if all I have are Eular Angle Coordinates [x, y, z] for rotation, how exactly to initialize guaternion() with these three values, please?

I am reading the GLM API documentation over and over, but I can not find a way. All I see, is quaternion initalization with angle an axis.

Thank you very much.

Unfortunately this feature is not available yet or at least not directly.

My guess is that you might be able to get the same results using three angleAxis calls and multiply the three quaternions together.

Hi Groovounet,

thank you for your reply. In other words, if I have the following Eular angles: [20, 30, 40], can I perform quatrnion initialization followingly?

glm::gtx::quaternion myXQuat = angleAxis[20, 1, 0, 0];
glm::gtx::quaternion myYQuat = angleAxis[30, 0, 1, 0];
glm::gtx::quaternion myZQuat = angleAxis[40, 0, 0, 1];

glm::gtx::quaternion myFinalQuat = myXQuat * myYQuat * myZQuat;

is the above correct, please?

Is the multiplication used, a Dot Product, please?


Hmm… am I doing something wrong, that I can not multiply Quaternions with overloaded * operator? Is there a way for quaternion multiplication?

I include the following: #include “gtx/quaternion.hpp”


Is the following correct, please? I wish to perform quaternion interpolation:

//myInterpolatedRotQuat = glm::mix(glm::quat(1.0f, pvAnimation->at(nFrameNo).vecRotation.x, pvAnimation->at(nFrameNo).vecRotation.y, pvAnimation->at(nFrameNo).vecRotation.z), glm::quat(1.0f, pvAnimation->at(nFrameNo + 1).vecRotation.x, pvAnimation->at(nFrameNo + 1).vecRotation.y, pvAnimation->at(nFrameNo + 1).vecRotation.z), fInterpolationTime);
glm::quat myXAxisQuat = glm::gtx::quaternion::angleAxis (pvAnimation->at(nFrameNo).vecRotation.x, 1.0f, 0.0f, 0.0f);
glm::quat myYAxisQuat = glm::gtx::quaternion::angleAxis (pvAnimation->at(nFrameNo).vecRotation.y, 0.0f, 1.0f, 0.0f);
glm::quat myZAxisQuat = glm::gtx::quaternion::angleAxis (pvAnimation->at(nFrameNo).vecRotation.z, 0.0f, 0.0f, 1.0f);
glm::quat myAxisQuat = glm::gtc::quaternion::cross( myZAxisQuat, myYAxisQuat);
myAxisQuat = glm::gtc::quaternion::cross( myAxisQuat, myXAxisQuat);

glm::quat myNextXAxisQuat = glm::gtx::quaternion::angleAxis (pvAnimation->at(nFrameNo + 1).vecRotation.x, 1.0f, 0.0f, 0.0f);
glm::quat myNextYAxisQuat = glm::gtx::quaternion::angleAxis (pvAnimation->at(nFrameNo + 1).vecRotation.y, 0.0f, 1.0f, 0.0f);
glm::quat myNextZAxisQuat = glm::gtx::quaternion::angleAxis (pvAnimation->at(nFrameNo + 1).vecRotation.z, 0.0f, 0.0f, 1.0f);
glm::quat myNextAxisQuat = glm::gtc::quaternion::cross( myNextZAxisQuat, myNextYAxisQuat);
myNextAxisQuat = glm::gtc::quaternion::cross( myNextAxisQuat, myNextXAxisQuat);

myInterpolatedRotQuat = glm::mix(myAxisQuat, myNextAxisQuat, fInterpolationTime);

I use ZYX orientation multiplication order. The problem I have is, that

vecInterpolatedRot = glm::gtx::quaternion::eularAngles( myInterpolatedRotQuat) ;

does not contain interpolated Rotation values. In fact, the values do not change at all.

Thank you.

Please stop using Euler angles for animation data. Seriously, don’t do this.

Animation data should ideally be stored as matrices. But since rotation matrices are 9 values (and they interpolate terribly), a more compact way is to store something equivalent but smaller. Namely, quaternions, which are 4 values. You can even compact these down to 3 values since the quaternion will be of unit length (and assuming the fourth value is the positive root. Negate the original quaternion if it is negative).

So you take up the same room as Euler angles, but without the pain that Euler angles involve.

am I doing something wrong, that I can not multiply Quaternions with overloaded * operator

Are you using a recent version of GLM? I submitted a patch for this that was accepted and applied months ago.

BTW, there’s no need to randomly bold parts of your posts. :wink:

Hi Alfonse,

Ok, I will accept your advices. I have written my own exporter from 3D authoring application, which I use. I wished to avoid rewritting everything, therefore I decided converting euler angles to quaternions during game play.

What if I need to say, add/subtract/divide/multiply existing orientations stored stored as quaternions? An example: I would need to add 20 degrees to current orientation. Will not I have difficulties performing these simple math operations with quaternions?

The version of GLM I use is more than 5 months old. I will download and try more recend version.

I will avoid using bold parts in my posts. I wished to emphasis key things, which should not be overlooked.

What if I need to say, add or subtract say 90 grades angles to angles stored as quaternions.

I don’t understand exactly what you mean by that. But it sounds like you’re talking about applying an orientation change to an existing orientation (ie: the quaternion). Which is just quaternion multiplication. You build a quaternion based on the orientation change you want to make. And you apply it on the left or right side as appropriate to the current quaternion. Thus giving rise to a new one.

Hi again, Alfonse,

Yes, you understood my question correctly. Thank you for your answer. I see, I found someone very experience, and I will take my chances, and try to get as much information as possible from you :slight_smile:

Could you kindly take a look at the following, please:

glm::quat myAxisNextQuat(pvAnimation->at(nFrameNo + 1).vecRotation);
vec3EularAngles = glm::gtx::quaternion::eularAngles( myAxisNextQuat);

This was just a test to see, what kind of information is returned back to me, as an Quaterniont -> EulerAngle conversion.

However, I see, that the values I obtained are not degrees. If they are, I must be doing something wrong.

In the code above I:

[ul][li]Initialize myAxisNextQuat with values: x:-54.0f y:73.0f z:-277.0f[]myAxisNextQuat then contains: x:-0.3 y:0.6 z:-0.3 w:-0.6[]After calling eularAngles(), I get the following back to vec3EularAngles vector: x:1.6 y:-1.5 z-0.6[/ul][/li]
Why are the values so small? I would expect degrees. What can be wrong, please?

I tripplechecked the values entered, and they look correct.

Why are the values so small?

Because they’re in radians. It’s (in all likelihood) not intended behavior. And if it is intended behavior, it should be documented.

File a bug on it.

And while you’re filing bugs, point out that “eular” is spell wrong.

Hi Alfonse,

I have created the new ticket for bug: Ticket #112

Can I have one more question related to the subject, please:

The quaternion constructor below accepts a glm::vec3 vector as one of the possible parameters.

explicit tquat(tvec3<T> const & eulerAngles);

How is it with the order of angles passed to intiliatize the quaternion? If I know that I will use particular quaternion only for interpolation, should I pass glm::vec3 with eular x, y, z values in a specific order? Alternatively, can I aways pass vec3 with values in order: heading, pitch, bank?