# GLM: Quaternion SLERP Interpolation

I wish to interpolate two quaternion values. As I still can not get working results, can I kindly ask you to verify my function calls? The code below supports GLM (OpenGL Mathemathics) library, so this questions might be for those, who know it.

Firstly, I perform Quaternion intialization from Euler Angles:

glm::quat myAxisQuat(pvAnimation->at(nFrameNo).vecRotation);
glm::quat myAxisNextQuat(pvAnimation->at(nFrameNo + 1).vecRotation);


Secondly, I interpolate between the two input quaternions. The variable fInterpolation contains value in the range 0.0f - 1.0f.

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


Thirdly, I convert my interpolated quaternion back to Euler Angles:

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


At the end, the values in vecInterpolatedRot do not represent the interpolated EulerAngles. It is difficult to understand the Quaternion values after conversion from Euler Angles, so I would like to ask you for your help, please.

I double and tripple checked input variables, I tried various approaches, and the only issue, at this moment might be with the third Aplha parameter in glm::mix()

## Update:

To provide you with more information, the returned values in vecInterpolatedRot are extremely low. At the end of the interpolation, I would expect valid Euler angles.

This is random sequence of interpolated values, as the object moves according to predefined animation path.

rotX:-1.7451 rotY:1.7993 rotZ-0.854642
rotX:-1.06451 rotY:1.18485 rotZ-0.694015
rotX:-0.254822 rotY:0.437004 rotZ-0.942035
rotX:0.578816 rotY:-0.335103 rotZ-0.716057
rotX:1.53934 rotY:-1.07602 rotZ-1.0182
rotX:2.5582 rotY:-1.87737 rotZ-0.759468
rotX:-2.58259 rotY:-2.47432 rotZ-1.06071
rotX:-1.35049 rotY:3.11548 rotZ-0.81839
rotX:0.0106472 rotY:2.78129 rotZ-1.04353
rotX:1.46636 rotY:2.33968 rotZ-0.879188
rotX:0.0289322 rotY:2.31166 rotZ-0.91746
rotX:-1.47901 rotY:2.37235 rotZ-0.938591
rotX:-2.59482 rotY:2.89469 rotZ-1.15554
rotX:2.47283 rotY:-2.76131 rotZ-0.992493
rotX:1.73065 rotY:-1.53285 rotZ-1.27898
rotX:0.85806 rotY:-0.176976 rotZ-1.03487
rotX:0.452009 rotY:-1.14604 rotZ-0.927788
rotX:0.0604701 rotY:-2.12479 rotZ-1.05684
rotX:0.107648 rotY:-2.07785 rotZ-1.05071
rotX:0.154894 rotY:-2.03083 rotZ-1.04569
rotX:0.809623 rotY:2.14456 rotZ-1.31262
rotX:1.15268 rotY:0.332553 rotZ-0.983604
rotX:2.16299 rotY:-0.545458 rotZ-1.11758
rotX:2.95376 rotY:-1.2008 rotZ-0.846527
rotX:-2.94892 rotY:-0.892473 rotZ-1.17334
rotX:-1.89716 rotY:-1.30162 rotZ-1.53247
rotX:0.804938 rotY:1.93659 rotZ-1.37281
rotX:0.653453 rotY:1.73722 rotZ-1.14364
rotX:2.24713 rotY:0.658935 rotZ-1.03684
rotX:2.97528 rotY:0.508203 rotZ-0.559124
rotX:-2.49988 rotY:0.640482 rotZ0.0117903
rotX:-1.57379 rotY:1.16303 rotZ0.288639
rotX:-1.4928 rotY:1.17794 rotZ0.902059
rotX:-0.667796 rotY:1.94995 rotZ1.49074
rotX:2.12971 rotY:-1.85782 rotZ0.904871
rotX:2.36951 rotY:-2.03682 rotZ0.189242
rotX:1.5574 rotY:-2.92156 rotZ-0.450418
rotX:1.6256 rotY:2.29519 rotZ-1.46659
rotX:2.85414 rotY:2.11303 rotZ-0.42888
rotX:-2.48503 rotY:2.96942 rotZ0.189887
rotX:-1.55656 rotY:3.00852 rotZ0.675669

• Did you figure out which rotation order is used when your euler-angles are exported? XYZ, YXZ, ZYX etc. – Maik Semder Jun 10 '11 at 17:05
• @Maik Semder: +1, hi Maik. Thank you for your comment. Yeah, I am aware of the importance of the angles order. What is the logic behind quaternions? Are angles wich I pass into Quaternions returned back in the same order? Say, I create initialize quaternion with values (x, y, z). I perform interpolation and conversion back to euler angle. Should I obtain values back in the same order (x, y, z). I checked, according to your advice, and I see, that eularAngles() returns the following order: return detail::tvec3<valType>(pitch(x), yaw(x), roll(x)); – Bunkai.Satori Jun 10 '11 at 18:21
• @Bunkai.Satori that is not the rotation order. It is important if you first rotate 10 degress around x-axis and the 20-degrees around y-axis or the other way around, 20 degrees around y-axis and then 10 degrees around x-axis. The results will be different – Maik Semder Jun 10 '11 at 18:33
• Euler angles are really the worst choice for this problem. Is there any chance you can export it directly in quaternions, matrices or axis-angles? This will be much easier at the end – Maik Semder Jun 10 '11 at 18:34
• @Maik: I believe, I understand your point. Previously, I performed linear intrpolation, which worked well. I had issues with Gimbal Locks, therefore, I switched to Quaterions. My application handles the order correctly. However, another issue is, in which order are values returned by glm::eularAngles(). If the values are assigned to appropriate variables. So, if my engine obtains X, Y, Z in respective variables. Do I get your point? – Bunkai.Satori Jun 10 '11 at 18:38

The posted values seem to be radians, but GLM uses degrees.

Edit: Also make sure you use the same rotation order. If you dont understand why that matters see the different results for different orders here at Wolfram Alpha. Play a bit with the "Euler rotation sequence" box and watch the different outputs.

Here and here are some more links that explain the rotation-order-problem

• @Maik Semder: +1, That is very good point. As I see, my questions might be elementary to you, but this is my first practical contact with this subject. I have to learn all the trick and things I have to be careful about. I will check, and keep this tread updated. – Bunkai.Satori Jun 10 '11 at 18:25
• @Main Semder: Thank you Maik, for your patience. I would like to udnerstand quaternions once forever and to make progress in my project. – Bunkai.Satori Jun 10 '11 at 19:00
• @Bunkai, understanding quaternions is definitely something that you should do. However, that is not the problem here. As long as you use Euler-Angles it is more important for your project to understand the importance of the rotations order. I will stop saying that now, because I feel I said it a thousand times ;) but it is the most important point here and the cause of your trouble. – Maik Semder Jun 10 '11 at 19:06
• @Bunkai, I just saw the answers from your previous questions say it too, unfortunetely you accepted the only partially wrong answer from Daniel that did not mention the rotation order, so the wrong answer. Trevor and Richard mentioned it and actually deserve the check mark more ;) – Maik Semder Jun 10 '11 at 20:02
• @Maik: Thanks for you note. Well, originally, I accepted Trevor's advice, which seemed to me as the most complete. But then, Daniel found a constructor, that should to exactly what I needed. Therefore, I think, Daniel provided the easiest and terefore most effective solution. Yeah, he could have mentioned the need to be careful about order of eular angles passed. He might have assumed as well, that I know this. Sometimes, it is hard to decide for the best answer. I have to agree, that Trevor's one was most more complete, and therefore, I reevaluated my decision. – Bunkai.Satori Jun 10 '11 at 20:19

I never used GLM until now (it seems interesting through) but are you sure about your "glm::mix" call ?

In the documentation I can find two mix functions :

• glm::core::function::common::mix

genTypeT glm::core::function::common::mix (
genTypeT const & x,
genTypeT const & y,
genTypeU const & a
)


If genTypeU is a floating scalar or vector: Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1].

• glm::gtc::quaternion::mix

detail::tquat<T> glm::gtc::quaternion::mix (
detail::tquat< T > const & x,
detail::tquat< T > const & y,
typename detail::tquat< T >::value_type const & a
)


Returns a SLERP interpolated quaternion of x and y according a.

I think glm::mix is an alias to the first one (I'm still searching informations to confirm it through, as I can't find it in the documentation) and as you need the second one, you could try to call it directly.

• it is the correct one, they use glm::quat C = glm::mix(A, B, 0.5f); in their test-suite in GLM/test/gtx/gtx_quaternion.cpp and A and B are quaternions – Maik Semder Jun 10 '11 at 17:19
• So this probably not the good solution, but it had to be verified. – Valkea Jun 10 '11 at 17:30
• +1, hi, and thank you for your comment. Well, I tried your suggestion, but unfortunately no improvement. It looks like the object is still static from orientation viewpoint. As if the interpolation does not result any significant values, to change object's orientation. Should quaternions contain values always in the -1 - +1 range, please? As I look at values in my quaterions after passing Euler Angle values to them, their values were in -1 - +1 range. – Bunkai.Satori Jun 10 '11 at 17:50
• @Maik Semder: +1, hi and thank you for yoru comment. I will check the test suite. I have not seen it yet. There is one thing that confuses me: glm::quat myAxisQuat(glm::vec3(-54.0f, 73.0f, -277.0f)); initializes myAxisQuat to values x:-0.3, y:0.6, z:-0.3, w:0.2. When I convert myAxisQuat back go Eular Angles glm::vec3 vec3EularAngles = glm::gtx::quaternion::eularAngles( myAxisQuat);, I obtain very small angles: x:1.6 y-1.5 z-0.6. I would expect valid angles here. Am I missinterpreting anything? This is my firs experience with quaternions. – Bunkai.Satori Jun 10 '11 at 18:05
• @Bunkai see my answer, also check the rotation order – Maik Semder Jun 10 '11 at 18:10