[Math] Understanding the value of inner product of two quaternions in Slerp().

geometryquaternions

I'm reading pbrt and trying to better understanding the return value of Dot(). The Dot() function takes two quaternions and returns their inner product. Also note, internally, when it comes to the inner product, a quaternion is treated as a 4D vector. I know when two vectors, or in this case the two quaternions, are parallel, then their inner product is equal to 1.0.

Things get little confusing for me when I read the implementation of Slerp()

Quaternion Slerp(float t, const Quaternion &q1,
                 const Quaternion &q2) {
    float cosTheta = Dot(q1, q2);
    if (cosTheta > .9995){
        return Normalize((1.f - t) * q1 + t * q2);
    } else {
      // ...
    }
}

I don't quite understand the if(cosTheta > .9995) part. If two quaternions are parallel, then their inner product is 1.0, correct? The only reason I can think of for having a greater-than operator is because Slerp() is meant to work with quaternions and unit quaternions. Is that right?

My ultimate goal is to replace if(cosTheta > .9995) with something more accurate, such as:

if( approxEqual(cosTheta, 1.0) or cosTheta > 1.0 ){ ... }

approxEqual computes whether the two arguments are ap­prox­i­mately equal based on their relative difference.

Would my new if statement be mathematically correct?

In the book Slerp() is described as:

$$
slerp(q1,q2,t) = \frac{ q1 \sin((1-t) \theta) + q2 \sin(t\theta) }{ \sin \theta }
$$

…given the quaternions to interpolate between, $q1$ and $q2$, denote by \theta the angle between them. Then, given a parameter value t ∈[0,1], we'd like to find the intermediate quaternion $q'$ that makes angle $\theta' = \theta t$ between it and $q1$, along the path from $q1$ to $q2$. –page 95

The implementation of the Slerp() function checks to see if the two quaternions are nearly parallel, in which case it uses regular linear interpolation of quaternion components in order to avoid numerical instability. Otherwise, …

Best Answer

The numerical instability the code is meant to avoid is not one that occurs only if $\cos\theta$ is calculated to be greater than $1$ due to rounding; it occurs already if $\cos\theta$ is close to $1$, since the exact formula uses division by $\sin\theta=\sqrt{1-\cos^2\theta}$. So the answer is, no, you shouldn't replace that line; it's there for a good reason. You can experiment with increasing the bound to see whether it's been optimally chosen, but you shouldn't replace it by $1$.

Related Question