I don’t want to turn this to a blog about quaternions, but if you are familiar with animation you’ve probably had your fair share of quaternions. Spherical linear interpolation AKA slerp is then used to interpolate between two orientations ( quaternions ). Your generic slerp function would look something like this…
Quaternion Slerp( const Quaternion& lhs, const Quaternion& rhs, float t )
{
float cosAlpha = lhs.Dot( rhs );
Quaternion r = rhs;
if( cosAlpha < 0.0f )
{ // if cos(alpha) is positive, then the path from q1 to q2 is shorter.
r = -1.0f*r;
}
cosAlpha = lhs.Dot( r );
float alpha = acos( cosAlpha );
if( fabs( alpha ) < epsilon )
{ //< these quaternions are too close to slerp between.
return lhs;
}
float a = sin( ( 1.0f - t ) * alpha ) / sin( alpha );
float b = sin( t*alpha ) / sin( alpha );
Quaternion q = a*lhs + b*r;
q.Normalize(); //< we want a unit quaternion
return q;
}
Lots of slow trig functions for hundreds of slerps can really bog you down.
Well, this article by Jonathan Blow has a nice hack that approximates slerp. It uses generic lerp between two quaternions and then normalizes the quaternion to project it back onto the unit sphere.
Our new code looks something like…
Quaternion Slerp( const Quaternion& lhs, const Quaternion& rhs, float t )
{
Quaternion hackQuat;
hackQuat.x = lhs.x + t*(rhs.x – lhs.x);
hackQuat.y = lhs.y + t*(rhs.y – lhs.y);
hackQuat.z = lhs.z + t*(rhs.z – lhs.z);
hackQuat.w = lhs.w + t*(rhs.w – lhs.w);
hackQuat.Normalize();
return hackQuat;
}
Unfortunately, where slerp moves through at constant speed, linear interpolation moves quickly at the endpoints and slowly in the middle; worst case being where the original angle b/t quaternions is 90degrees. They fix this by "splining" t to compensate for the speed issues.
I decided to put both methods to the test in my homemade animation loader/updater/viewer! Each bone only has a maximum of 16 keyframes creating pretty decent angles between orientations. Can you tell which is which?!
Of course, a better method would be to just implement incremental slerp which is both computationally fast and takes care of any speed issues.





0 Responses to “hacked slerp”