PDA

View Full Version : Clamping the dot product in a Slerp for Quaternion



openlearner
06-13-2013, 09:23 AM
I'm looking at two different source for the Slerp method of interpolation between two quaternions. They are pretty similar except for one notable difference: one clamps the dot product between 0 and 1, and the other between -1 and 1. Here is one of them:


glm::fquat Slerp(const glm::fquat &v0, const glm::fquat &v1, float alpha)
{
float dot = glm::dot(v0, v1);

const float DOT_THRESHOLD = 0.9995f;
if (dot > DOT_THRESHOLD)
return Lerp(v0, v1, alpha);

glm::clamp(dot, -1.0f, 1.0f); //<-- The line in question
float theta_0 = acosf(dot);
float theta = theta_0*alpha;

glm::fquat v2 = v1 - v0*dot;
v2 = glm::normalize(v2);

return v0*cos(theta) + v2*sin(theta);
}

Here is the other:


template <typename T>
inline QuaternionT<T> QuaternionT<T>::Slerp(T t, const QuaternionT<T>& v1) const
{
const T epsilon = 0.0005f;
T dot = Dot(v1);

if (dot > 1 - epsilon) {
QuaternionT<T> result = v1 + (*this - v1).Scaled(t);
result.Normalize();
return result;
}

if (dot < 0) //<-The lower clamp
dot = 0;

if (dot > 1)
dot = 1;

T theta0 = std::acos(dot);
T theta = theta0 * t;

QuaternionT<T> v2 = (v1 - Scaled(dot));
v2.Normalize();

QuaternionT<T> q = Scaled(std::cos(theta)) + v2.Scaled(std::sin(theta));
q.Normalize();
return q;
}

I think it is worth noting also the the Lerp algorithm in the second one doesn't seem right for all cases?

I just want some feedback on these differences and if they really matter at all.

GClements
06-13-2013, 10:52 AM
Clamping the dot product to -1..+1 should be a no-op if the quaternions are normalised, but it may provide robustness e.g. in the case of rounding error (passing a value outside that range to acos() will result in a domain error).
Clamping to zero seems wrong; it effectively clamps the angle to 180 degrees (by clamping the half angle to 90 degrees). In the absence of additional steps, a negative dot product will result in the interpolation taking the long way around (i.e. rotating through an angle greater than 180 degrees). Typically, if the dot product is negative, you would negate one of the two quaternions (and their product) so that the interpolation takes the shorter path.