Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I hope you know GL Mathematics (GLM) because I've got a problem, I can not break:

I have a set of Eular Angles and I need to perform smooth interpolation between them. The best way is converting them to Quaternions and applying SLERP alrogirthm.

The issue I have is how to initialize glm::quaternion with Euler Angles, please?

I read GLM Documentation over and over, but I can not find appropriate Quaternion constructor signature, that would take three Eular Angles. The closest one I found is angleAxis() function, taking angle value and an axis for that angle. Note, please, what I am looking for si a way, how to parse RotX, RotY, RotZ.


For your information, this is the above metnioned angleAxis() function signature:

detail::tquat< valType > angleAxis (valType const &angle, valType const &x, valType const &y, valType const &z)
share|improve this question
add comment

4 Answers

up vote 6 down vote accepted

I'm not familiar with GLM, but in the absence of a function to directly convert from eular angles into quaternions, you can use the "rotation around an axis" functions (such as "angleAxis") to it yourself.

Here's how (pseudocode):

Quaternion QuatAroundX = Quaternion( Vector3(1.0,0.0,0.0), EulerAngle.x );
Quaternion QuatAroundY = Quaternion( Vector3(0.0,1.0,0.0), EulerAngle.y );
Quaternion QuatAroundZ = Quaternion( Vector3(0.0,0.0,1.0), EulerAngle.z );
Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ;

(Or you may need to switch those quaternion multiplies around, depending on the order in which your euler angle rotations are intended to be applied)

Alternately, from looking through GLM's documentation, it appears that you may be able to convert euler angles -> matrix3 -> quaternion like this:

toQuat( orient3( EulerAngles ) )
share|improve this answer
    
good answer because it's less ambiguous about order of application. –  Richard Fabian Jun 10 '11 at 10:33
    
@Trevor: +1, Hi Trevor, thanks for your good answer. This looks like the most practical solution here. I can easily switch between the rotation multiplication order. Possibly, the number of combinations is the reason, why Euler Angle to Quaterion conversion is not avaialble in GLM. –  Bunkai.Satori Jun 10 '11 at 13:54
    
Although all the answers are good and valuable, in my opinion, this is the most practical one. I would like to mark it as the Accepted Answer. –  Bunkai.Satori Jun 10 '11 at 13:58
    
@Trevor: In Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ;, what kind of multiplication have you meant? I am surprised, that GLM, does not overload operator * for Quaternion multiplication, so possibly, I will have to peform multiplication manually. –  Bunkai.Satori Jun 10 '11 at 14:33
2  
@Bunkai the concept of quaternion multiplication is similar to matrix multiplication, it is neither dot nor cross product. If you want to understand the usage of quaternions, then get used to matrices and understand axis-angles, their basic concept is pretty similar to quaternions, the math is a bit more advanced, but once you understood axis-angles, then quaternions are not far away anymore. –  Maik Semder Jun 11 '11 at 20:33
show 6 more comments
vec3 myEuler (fAngle[0],fAngle[1],fAngle[2]);
glm::quat myQuat (myEuler);

fAngle must be in radians!

share|improve this answer
1  
Was this a joke? Or did you you just not read the other answers (especially Daniel's)? –  Christian Rau Dec 17 '11 at 12:25
add comment
glm::quat myquaternion(glm::vec3(angle.x, angle.y, angle.z));

Where angle is a glm::vec3 containing pitch, yaw, roll respectively.

PS. If in doubt, just go to the headers and look. The definition can be found in glm/gtc/quaternion.hpp:

explicit tquat(tvec3<T> const & eulerAngles) {
        tvec3<T> c = glm::cos(eulerAngle * value_type(0.5));
    tvec3<T> s = glm::sin(eulerAngle * value_type(0.5));

    this->w = c.x * c.y * c.z + s.x * s.y * s.z;
    this->x = s.x * c.y * c.z - c.x * s.y * s.z;
    this->y = c.x * s.y * c.z + s.x * c.y * s.z;
    this->z = c.x * c.y * s.z - s.x * s.y * c.z;    
}

Where quat is a float typedef for tquat.

share|improve this answer
    
That's quite ambiguous, what order would these apply in? Eulers are ordered rotations and the quaternion constructor here doesn't seem to care about that. –  Richard Fabian Jun 10 '11 at 10:00
    
The function definition is the exact same as yours; I posted it in my answer if it mattered. –  Daniel Jun 10 '11 at 10:24
    
not the order of the arguments, the order of application of rotation. My answer contains the XYZ ordering, taken from the wikipedia article, however, we use ZYX ordering of application at my old company, and YZX at my current one. the x angle is still the first value in the vector / argument list in all cases, but the actual resultant transform is not the same. –  Richard Fabian Jun 10 '11 at 10:28
    
I fixed my answer for the rotationQuat, so you can see how you could easily change the order. By default it accepts XYZ, but you can easily change that. –  Daniel Jun 10 '11 at 10:31
1  
-1 for not mentioning the rotation order, which is very important for the question –  Maik Semder Jun 10 '11 at 20:03
show 8 more comments

Solution is in wikipedia: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

using that:

sx = sin(x/2); sy = sin(y/2); sz = sin(z/2);
cx = cos(x/2); cy = cos(y/2); cz = cos(z/2);

q( cx*cy*cz + sx*sy*sz,
   sx*cy*cz - cx*sy*sz,
   cx*sy*cz + sx*cy*sz,
   cx*cy*sz - sx*sy*cz ) // for XYZ application order

q( cx*cy*cz - sx*sy*sz,
   sx*cy*cz + cx*sy*sz,
   cx*sy*cz - sx*cy*sz,
   cx*cy*sz + sx*sy*cz ) // for ZYX application order

Constructors for a quaternion, given an Euler (where application of rotation is XYZ or ZYX). However, it's only two of six possible combinations of Euler angles. You really need to find out what order the Euler angles are constructed when converting to transform matrix. Only then can the solution be defined.

In the old company I worked at, we had Z as forwards (like most graphics cards) so the application order was ZYX, and at my current company the Y axis is forwards and Z is up, so our application order is YZX. This order is the order you multiply your quaternions together in to generate your final transform, and the order matters for rotations are the multiplications are not commutative.

share|improve this answer
    
+1, hi and thanks for great answer. As I use OpenGL, the Z value goes out of the screen. In my application I perform ZYX multiplication order. Originally, I thought, that GLM has this functionality available, but I see, they have not implemented it yet, so one alternative is creating the conversion manually , as you recommend. –  Bunkai.Satori Jun 10 '11 at 13:51
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.