Jump to content

  • Log In with Google      Sign In   
  • Create Account

Weird skeletal animation collapsing error


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 hupsilardee   Members   -  Reputation: 486

Like
0Likes
Like

Posted 03 April 2013 - 07:07 AM

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.



Sponsor:

#2 Rhetorician   Members   -  Reputation: 119

Like
0Likes
Like

Posted 01 May 2013 - 05:02 PM

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, 01 May 2013 - 05:07 PM.


#3 ill   Members   -  Reputation: 320

Like
0Likes
Like

Posted 01 May 2013 - 10:06 PM

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.



#4 hupsilardee   Members   -  Reputation: 486

Like
1Likes
Like

Posted 06 May 2013 - 05:43 AM

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!



#5 Rhetorician   Members   -  Reputation: 119

Like
0Likes
Like

Posted 06 May 2013 - 11:12 AM

Good revisions to your overall animation system! :D






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS