15
\$\begingroup\$

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

I have a set of Euler 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 Euler 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)
\$\endgroup\$
0

4 Answers 4

15
\$\begingroup\$

I'm not familiar with GLM, but in the absence of a function to directly convert from Euler 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 ) )
\$\endgroup\$
11
  • \$\begingroup\$ good answer because it's less ambiguous about order of application. \$\endgroup\$ Jun 10, 2011 at 10:33
  • \$\begingroup\$ @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. \$\endgroup\$ Jun 10, 2011 at 13:54
  • \$\begingroup\$ 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. \$\endgroup\$ Jun 10, 2011 at 13:58
  • \$\begingroup\$ @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. \$\endgroup\$ Jun 10, 2011 at 14:33
  • 3
    \$\begingroup\$ @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. \$\endgroup\$ Jun 11, 2011 at 20:33
21
\$\begingroup\$
glm::quat myquaternion = glm::quat(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.

\$\endgroup\$
13
  • \$\begingroup\$ 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. \$\endgroup\$ Jun 10, 2011 at 10:00
  • \$\begingroup\$ The function definition is the exact same as yours; I posted it in my answer if it mattered. \$\endgroup\$ Jun 10, 2011 at 10:24
  • \$\begingroup\$ 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. \$\endgroup\$ Jun 10, 2011 at 10:28
  • \$\begingroup\$ 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. \$\endgroup\$ Jun 10, 2011 at 10:31
  • 3
    \$\begingroup\$ -1 for not mentioning the rotation order, which is very important for the question \$\endgroup\$ Jun 10, 2011 at 20:03
9
\$\begingroup\$

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.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ +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. \$\endgroup\$ Jun 10, 2011 at 13:51
  • \$\begingroup\$ This is the best answer here. \$\endgroup\$
    – plasmacel
    Jul 19, 2019 at 19:15
1
\$\begingroup\$
vec3 myEuler (fAngle[0],fAngle[1],fAngle[2]);
glm::quat myQuat (myEuler);

fAngle must be in radians!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Was this a joke? Or did you you just not read the other answers (especially Daniel's)? \$\endgroup\$ Dec 17, 2011 at 12:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .