Hi guys,
Thank for helping. I think I should provide more information. This is kind of long so please bear with me.
I am creating my animations in 3dx Max; for this situation I set two keyframes (those pictured), one at frame 0 and the other at frame 5 (the frame numbers are arbritray as you'll see.) I then export via FBX using the 'bake animation' option, if you're not familiar with that it simply resolves or 'flattens' everything and outputs the bone data for every frame, so I end up with keyframe (sample) data at frames 0, 1, 2, 3, 4, 5.
My FBX loader extracts the data for keys 0 and 5 (the two I specifically set) and I use those for my two poses (animation samples.)
Here is the totality of what I extract from the FBX file:
1) bone offsets (the 'bind pose' or 'T pose')
2) the keyframe poses (two in my case, at frame 0 and 5)
3) mesh and vertex weights (not relevant here)
I convert then store that data like this:
// for the offsets
struct SkeletonBone {
float4x4 offset;
};
// I only need a single SkeletonBone array since that never changes
struct Skeleton {
SkeletonBone* bones;
int num_bones; // three in this scenario
};
// for the keyframes (poses or samples depending on terminology)
// it's the basic SRT without the scale
struct Bone {
float3 lclT; // local translation
float4 lclR; // local rotation as quaternion
};
// each array of the above Bone struct is an animation sample (I call them poses)
struct Pose {
Bone* bones;
int num_bones; // three in this scenario
};
// for this scenario I would have an array of two Poses
Pose poses[2];
If you like I can provide the routines I use to convert the raw data to the offset matrices and SRTs but it's nothing fancy.
I then have everything I need to generate the matrix palette every frame. For testing I run a 30-iteration loop, increment the interpolation value t from 0.0 to 1.0, and transform the ankle bone position by palette[2]. I can include that code as well but it's standard stuff.
I really don't think my math is wrong. I've created bone chains with 12 bones, did crazy xyz rotations on all 12 bones, transformed the last bones' positions with the matrix palette and they're perfect, exactly where the bones are in 3ds Max.
All I can think of is that I need more animation samples for an animation like this, it will definitely reduce the increasing error as t approaches 0.5 but i still feel like something is wrong.
Also, this is not IK releated at all, I was mistaken; IK doesn't even enter the picture since I'm baking the animations.
Here is my Nlerp function:
// I like it better like this
typedef DirectX::XMFLOAT4 float4;
void quaternionNlerp(float4* out, float4* q1, float4* q2, float t)
{
float dot = q1->x * q2->x + q1->y * q2->y + q1->z * q2->z + q1->w * q2->w;
// I read to check the dot but I see no difference either way
if (dot < 0.0f){
// negate one of the quaternions (q2)
out->x = q1->x + t * (-q2->x - q1->x);
out->y = q1->y + t * (-q2->y - q1->y);
out->z = q1->z + t * (-q2->z - q1->z);
out->w = q1->w + t * (-q2->w - q1->w);
}
else{
out->x = q1->x + t * (q2->x - q1->x);
out->y = q1->y + t * (q2->y - q1->y);
out->z = q1->z + t * (q2->z - q1->z);
out->w = q1->w + t * (q2->w - q1->w);
}
// do the normaliztion with DirectX math
DirectX::XMVECTOR xmv1 = DirectX::XMLoadFloat4(out);
DirectX::XMVECTOR xmv2 = DirectX::XMVector4Normalize(xmv1);
DirectX::XMStoreFloat4(out, xmv2);
}
Maybe I can give you the actual data and you can run it through your animation system ? It's only three bones and two poses, not too much.
That's about all I can think of. Thanks again.