Im trying to optimize my skeletal animation system by using tracks (curve) instead of keyframe. Each curve take care of a specific component then (for now) I linearly interpolate the values. Work fine for my bone positions, however Im having a hard time getting rid of the "jagyness" of the quaternion component interpolation...
Basically I have 1 curve for each component (XY and Z) for each bones quaternion and I use the following code to interpolate the XY and Z curves independently:
// Simple lerp... (f is always a value between 0.0f and 1.0f)
return ( curve->data_array[ currentframe ].value * ( 1.0f - f ) ) +
( curve->data_array[ nextframe ].value * f );
When I interpolate the quaternion XYZ then I use the following code to rebuild the W component of the quaternion before normalizing it and affecting it to my bone before drawing:
Quaternion QuaternionW( const Quaternion q )
{
Quaternion t = { q.x, q.y, q.z };
float l = 1.0f - ( q.x * q.x ) - ( q.y * q.y ) - ( q.z * q.z );
t.w = ( l < 0.0f ) ? 0.0f : -sqrtf( l );
return t;
}
The drawing look fine at the exception that the bones become all jerky from time to time, would it be due to the floating point precision? Or the recalculation of the W component? Or there is absolutely no way I can linearly interpolate each component of a quaternion this way?
ps: On a side note, in my curve interpolation function if I replace the code above with:
return curve->data_array[ currentframe ].value;
instead or linearly interpolating, everything is fine... So the data is obviously correct... Im puzzled...
[ EDIT ]
After more research I found that the problem comes from the frame data... I got i.e. the following:
Frame0: quat.x = 0.950497
Frame1: quat.x = -0.952190
Frame2: quat.x = 0.953192
This is what causes the inversion and jaggyness... I tried to detect this case and inverse the sign of the data but it still doesn't fix the problem fully as some frame now simply look weird (visually when drawing).
Any ideas how to properly fix the curves?