# Applying incremental rotation with quaternions: flickering or hesitating

I'm having a couple of problems while rotating an object every frame with GLM.

First problem
I'm trying to rotate the object with a small increase using quaternion multiplication.

glm::quat deltaQuat = glm::qua(0.001f, glm::vec3(0.0f, 1.0f, 0.0f));
object.SetWorldRotation(object.GetWorldRotation() * deltaQuat);


The result of this code is that the rotation switches back and forward with its inverse each frame, plus the small delta.

Full framerate video here, and the logs I get:

Object world rotation: quat(1.000000, {0.000000, 0.000000, 0.000000})
Object world rotation: quat(0.001000, {0.000000, 1.000000, 0.000000})
Object world rotation: quat(-0.999999, {0.000000, 0.002000, 0.000000})
Object world rotation: quat(-0.003000, {0.000000, -0.999997, 0.000000})
Object world rotation: quat(0.999994, {0.000000, -0.004000, 0.000000})
Object world rotation: quat(0.005000, {0.000000, 0.999990, 0.000000})
Object world rotation: quat(-0.999985, {0.000000, 0.006000, 0.000000})
Object world rotation: quat(-0.007000, {0.000000, -0.999979, 0.000000})
Object world rotation: quat(0.999972, {0.000000, -0.008000, 0.000000})
Object world rotation: quat(0.009000, {0.000000, 0.999964, 0.000000})
Object world rotation: quat(-0.999955, {0.000000, 0.010000, 0.000000})
Object world rotation: quat(-0.011000, {0.000000, -0.999945, 0.000000})
Object world rotation: quat(0.999934, {0.000000, -0.012000, 0.000000})
Object world rotation: quat(0.013000, {0.000000, 0.999922, 0.000000})
Object world rotation: quat(-0.999909, {0.000000, 0.014000, 0.000000})
Object world rotation: quat(-0.015000, {0.000000, -0.999895, 0.000000})
Object world rotation: quat(0.999880, {0.000000, -0.015999, 0.000000})
Object world rotation: quat(0.016999, {0.000000, 0.999864, 0.000000})
Object world rotation: quat(-0.999847, {0.000000, 0.017999, 0.000000})
Object world rotation: quat(-0.018999, {0.000000, -0.999829, 0.000000})
Object world rotation: quat(0.999810, {0.000000, -0.019999, 0.000000})


Second problem
Similarly to the first one, I'm trying to rotate the object with a small increase, this time using euler angles.

object.SetWorldEulerRotation(object.GetWorldEulerRotation() + glm::vec3(0.0f, 0.1f, 0.0f));

// where:

void SetWorldEulerRotation(glm::vec3 const& eulerRotation)
{
SetWorldRotation(glm::quat(eulerRotation));
}

// and

glm::vec3 GetWorldEulerRotation() const
{
return glm::eulerAngles(m_rotation); // m_rotation is a world quaternion
}


The result of this code is that the object's rotation does not go beyond 180º in either direction. It jitters between a little over that rotation and a little under it.

Video here, and the logs I get:

Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})
Object world rotation: quat(0.707403, {0.000000, 0.706810, 0.000000})
Object world rotation: quat(0.703863, {-0.000000, 0.710336, -0.000000})


Is there something I'm misunderstanding about quaternions/Euler angles, rotations in general or the GLM library?

• Your Euler angle example is running afoul of the same issue I explain in the context of Unity here - Euler angles have to have wrap-around points somewhere, so there's no guarantee the triplet you get back from a quaternion is the same one you gave it - somewhere in the 3 DOF domain it has to add a 360 degree rotation or two 180 degree flips to keep the angles in the defined output range, which can mean suddenly "increase y angle" can have the opposite meaning you expect. Commented Apr 10, 2022 at 23:09
• For the first problem, I'm having a devil of a time finding documentation for how glm::qua(float s, glm::vec3 v) interprets its arguments. It looks from your code like you're expecting s to be an angle and v to be a unit vector representing a rotation axis. But from the logs, it looks like we're seeing s as the real (w) component of the quaternion and v as the imaginary triplet. Do you get anything more sensible if you try something like glm::qua(glm::cos(angle/2), glm::vec3(0, glm::sin(angle/2), 0))? Commented Apr 10, 2022 at 23:21
• @DMGregory You're right! I assumed the API worked differently. That constructor is for setting the x,y,z,w values of the quaternion. Switching to glm::quat deltaQuat = glm::quat(glm::vec3(0.0f, 0.001f, 0.0f)); solves the first problem. Commented Apr 11, 2022 at 0:50
• Want to post your solution as an Answer below? If you're waiting on a solution to the second problem, just store your own angle triplet rather than converting from quaternions to Euler angles to try to recover them. That way you have full visibility and control over where and how you wrap them. Commented Apr 11, 2022 at 1:45
• I shouldn't try to "solve" the second problem. As you explained, it's doing something that shouldn't be done when (only) using quaternion internally. Commented Apr 11, 2022 at 3:17

Using the euler angles constructor works: glm::quat deltaQuat = glm::quat(glm::vec3(0.0f, 0.001f, 0.0f));.