Original Post
Hi everyone,
I'm having trouble trying to interpolate between key frames. Each bone has a position (in bone space) and a rotation as a quaternion. Without any interpolation, and simply rendering each frame, it looks completely correct, but as soon as I try to interpolate between frames it goes kinda crazy. Here's a video illustrating the problem:
[media]
I think it might have something to do with my SLERP code, but I can't find anything wrong with it...here's the code:
Another thing that's weird is that if I take out the if ( coshalftheta > (1.0f - std::numeric_limits::epsilon()) ) block, the model doesn't get drawn at all.
If it's of any use, here's my code for building the key frames from the bones:
I've spent far too long on this, and it's just annoying the heck out of me that I can't find the problem Hopefully someone here can spot my mistake though.
Thanks in advance!
I'm having trouble trying to interpolate between key frames. Each bone has a position (in bone space) and a rotation as a quaternion. Without any interpolation, and simply rendering each frame, it looks completely correct, but as soon as I try to interpolate between frames it goes kinda crazy. Here's a video illustrating the problem:
[media]
[/media]
I think it might have something to do with my SLERP code, but I can't find anything wrong with it...here's the code:
Quaternion Slerp ( const Quaternion& a, const Quaternion& b, float t )
{
if ( t >= 1.0f ) return b;
if ( t <= 0.0f ) return a;
float coshalftheta = DotProduct (a, b);
Quaternion c (b);
// Angle is greater than 180. We can negate the angle/quat to get the
// shorter rotation to reach the same destination.
if ( coshalftheta < 0.0f )
{
coshalftheta = -coshalftheta;
c = -c;
}
if ( coshalftheta > (1.0f - std::numeric_limits<float>::epsilon()) )
{
// Angle is tiny - save some computation by lerping instead.
Quaternion r (Lerp (a, c, t));
r.Normalize();
return r;
}
float halftheta = std::acos (coshalftheta);
return (a * std::sin ((1.0f - t) * halftheta) + c * std::sin (t * halftheta)) / std::sin (halftheta);
}
Another thing that's weird is that if I take out the if ( coshalftheta > (1.0f - std::numeric_limits
If it's of any use, here's my code for building the key frames from the bones:
void Ghoul2AnimationSet::BuildFrame ( BonePalette &newBones, const BonePalette &bones ) const
{
newBones[rootBone] = bones[rootBone];
BuildFrameRecurse (rootBone, newBones, bones);
}
void Ghoul2AnimationSet::BuildFrameRecurse ( int parentBone, BonePalette& newBones, const BonePalette& bones ) const
{
if ( joints[parentBone].children.empty() ) return;
for ( std::vector<int>::const_iterator it = joints[parentBone].children.begin();
it != joints[parentBone].children.end();
++it )
{
newBones[*it].position = newBones[parentBone].position + newBones[parentBone].orientation.RotatePoint (bones[*it].position);
newBones[*it].orientation = newBones[parentBone].orientation * bones[*it].orientation;
newBones[*it].orientation.Normalize();
BuildFrameRecurse (*it, newBones, bones);
}
}
BonePalette Ghoul2AnimationSet::BuildSkeleton ( int currentFrame, int nextFrame, float lerp ) const
{
const BonePalette& a = frames[currentFrame];
const BonePalette& b = frames[nextFrame];
unsigned int numBones = joints.size();
BonePalette p (numBones),
q (numBones);
for ( unsigned int i = 0; i < numBones; i++ )
{
p.position = Lerp (a.position, b.position, lerp);
p.orientation = Slerp (a.orientation, b.orientation, lerp);
p.orientation.Normalize();
}
BuildFrame (q, p);
return q;
}I've spent far too long on this, and it's just annoying the heck out of me that I can't find the problem Hopefully someone here can spot my mistake though.
Thanks in advance!