• 13
• 16
• 27
• 9
• 9

# Weird skeletal animation collapsing error

This topic is 1777 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I just don't get it. I was pretty elated when I figured out how to export an animated mesh to Blender DAE and get it working in-game, but it's not quite working perfectly. There's a weird bug where the character's arm collapses into a ball between two frames of animation, then corrects itself. I'm 99% sure it's the quaternion interpolation that's causing this, because the translation is just fine, it looks like the rotation is getting messed up. Also, this only happens twice over the 50+ frame animation. Here's the code that blends the skeleton's current animation pose. is this likely to be causing the problem? I can produce a GIF if required

void Skeleton::LerpFrame(float frame, float t, bool siblings, bool children)

{

Vector3 trans = pAnimation->GetTranslate(frame);

Vector3 scale = pAnimation->GetScale(frame);

Quaternion rotate = pAnimation->GetRotate(frame);

FrameRotate = Quaternion::Slerp(FrameRotate, rotate, t);

FrameTranslate = Vector3::Lerp(FrameTranslate, trans, t);

FrameScale = Vector3::Lerp(FrameScale, scale, t);

Matrix parentTransform = Matrix::Identity();

if (pParent)

{

parentTransform = pParent->GlobalTransform;

}

Matrix localTransform = Matrix::CreateFromQuaternion(FrameRotate) * Matrix::CreateTranslation(FrameTranslate);

GlobalTransform = localTransform * parentTransform;

if (pSibling && siblings)

pSibling->LerpFrame(frame, t, true, children);

if (pChild && children)

pChild->LerpFrame(frame, t, true, true);

}


Important notes: The math library I'm using is DirectX::SimpleMath. Also, there's no skinning shader - at the moment my characters are made out of static meshes attached to a skeleton, so that can't be the problem.

##### Share on other sites

is this likely to be causing the problem?

In my opinion, no.

Identify which frames this problem is occuring on. You can do this by simply providing debug controls for the playback position frame-by-frame with arrow keys or something. After that, use debugging technolololololologies to take a closer look. Then you may be able to find the culprit! (:

Question I have:

How is 't' defined? It denotes a position within two frames' interval, between 0.0 and 1.0, right?

Edited by Reflexus

##### Share on other sites

For the quat interpolation make sure you are doing it correctly.  Slerp isn't enough.  You need to do nlerp for most cases anyway.

You need to make sure you are lerping along the shortest path.  Slerp may be interpolating along the longer path to the destination in some cases.  You have to check the distance and negate some axis or something.

I myself use glm and simply use glm::short_mix so I'm not sure how to implement it off the top of my head, I just know it does something along those lines.

##### Share on other sites

I know t is in [0, 1], because it is calculated as

t = (requested_frame - min_frame) / (max_frame - min_frame)


where min_frame is the previous keyframe before the requested, and max_frame is the immediately next.

Anyway, when I was checking this, I found the problem: For calculating the position at any given frame, the animation track does this:

Vector3 GetFrameTranslateKey(float frame)
{
Vector3 before = ...
Vector3 after = ...
float t = ...
return before + (after - before) * t;
}


So that's fine, but then I carelessly copy-pasted that into the quaternion version

Quaternion GetFrameRotateKey(float frame)
{
Quaternion before = ...
Quaternion after = ...
float t = ...
return before + (after - before) * t;
}


so I changed the last line to

return Quaternion::Slerp(before, after, t);


and it works flawlessly. Thanks for helping guys!

##### Share on other sites

Good revisions to your overall animation system! :D