Interpolate Between Two Quaternions The Long Way

We can do a slerp interpolation between two quaternions like this:

quat slerp(quat q1, quat q2, float t) {
    float angle = acos(dotProduct(q1, q2));
    float denom = sin(angle);
    //check if denom is zero
    return (q1*sin((1-t)*angle)+q2*sin(t*angle))/denom;

This will interpolate between the two quaternions the shortest way. However there's also a long way to interpolate between quaternions. As seen in the image below (source Maya).

enter image description here

How do we interpolate the long way?



The nature of unit quaternions and the way they map to 3D rotations means they can describe each 3D rotation value in two ways - as q(r, v') and as q(-r, -v') (imagine them as axis-angle rotations - inverting both the axis and the angle leads to the same 3D rotation).

Quaternions are actually points on a 4D unit spherical surface, and these two values represent anti-podal points on that sphere.

For a slerp (or nlerp) of two quaternions to follow the shortest path, the corresponding 4D points have to lie on the same hemisphere of the 4D sphere (this is also the reason why a weighted average of more than 2 quaternions doesn't have a unique solution). This maps to a non-negative dot product, and is usually something tested for in the interpolation code.

Simply negating one of the source quaternions will give you a point "on the opposite side of the 4D sphere", and lead to interpolation "the long way around" (and explains why negating the interpolation parameter leads to the same result).