I'm trying to import a skeletal animation using FBX SDK. I followed this article, managing to load all the needed data, but when I try to display the animation the mesh falls apart. My knowledge of skeletal animation is fairly limited which may be the issue.

Here is the animation code

for (int i = 0; i < m_numTriangles; i++)
    for (int j = 0; j < 3; j++)
        currVertex = m_verticies[m_triangles[i].vertices[j]];
        posVec1.Set(0, 0, 0);
        normVec1 = currVertex.normal;
        for (int k = 0; k < currVertex.blendingInfo.size(); ++k)
            jointIndex = currVertex.blendingInfo[k].index;
            jointWeight = currVertex.blendingInfo[k].weight;

            if (jointWeight != 0)
                transMat1 = m_skeleton.joints[jointIndex].animation[frameIndex1 - 1].transform;
                temp = transMat1.MultT(currVertex);
                posVec1 += temp*jointWeight;
        glNormal3f(normVec1.mData[0], normVec1.mData[1], normVec1.mData[2]);
        glVertex3f(posVec1.mData[0], posVec1.mData[1], posVec1.mData[2]);

I iterate over all the triangles, get the vertices, iterate over all the joints that affect said vertex, get the transformation matrix for the current frame and apply.

I believe the problem is with how I'm applying the matrix, but I don't know what I'm doing wrong. I think either I'm skipping a step or I'm misunderstanding what the transform matrix represents.

The article retrieves the global bind pose inverse as follows

currCluster->GetTransformMatrix(transformMatrix);   // The transformation of the mesh at binding time
currCluster->GetTransformLinkMatrix(transformLinkMatrix);   // The transformation of the cluster(joint) at binding time from joint space to world space
globalBindposeInverseMatrix = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform;

This is done for each joint. Do I need to multiply this with the transform matrix before applying to vertex? Like this

transMat1 = m_skeleton.joints[jointIndex].animation[frameIndex1 - 1].transform * m_skeleton.joints[jointIndex].globalBindposeInverse;

Or do I need to also multiply each joints globalBindposeInverse with its parents first?

This is how the article calculates the transform for each frame of animation

for (FbxLongLong i = m_startFrame; i <= m_endFrame; ++i)
    FbxTime currTime;
    currTime.SetFrame(i, FbxTime::eFrames24);
    currAnim.number = i;
    FbxAMatrix currentTransformOffset = inNode->EvaluateGlobalTransform(currTime);
    currentTransformOffset *= geometryTransform;
    currAnim.transform = currCluster->GetLink()->EvaluateGlobalTransform(currTime);
    currAnim.transform *= currentTransformOffset.Inverse();

I'm sorry if this is a trivial question, but I've been stuck on this for 4 days now.

  • 1
    \$\begingroup\$ I wonder if you're not taking the joint hierarchy into account. Hard for me to tell, but you may be combining all the joint's local transform by the mesh's global world space transform instead of walking the hierarchy order. For instance: by combining(concatenating) the root joint by world space, then combining the children of the root by the root (not by world space), then the children of the children of the root by children of the root... etc. This creates absolute world space transforms for each joint. \$\endgroup\$ – Steve H Jun 28 '15 at 14:29
  • \$\begingroup\$ Thanks for the reply @steve. Sorry for the delay, I was doing some research. I'm not sure I understand what you mean by "combining all the joint's local transform by the mesh's global world space transform instead of walking the hierarchy order", but I do go over each bone in order and calculate its matrix separately from its parent. I found two posts that explain what I think I'm missing. I don't move the vertices between joint and world space for transformations. After reading the articles I still cant understand which matrix represents which transform. \$\endgroup\$ – inzombiak Jun 29 '15 at 14:40
  • \$\begingroup\$ These are the posts 1 2 \$\endgroup\$ – inzombiak Jun 29 '15 at 14:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.