Jump to content
  • Advertisement
Sign in to follow this  
Ali Mohebali

FBX exporter - Calculating bind pose matrix and animation bone transforms

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I have been trying to write an FBX converter for our game engine recently and I have managed to get the meshes exported and coverted properly. But I seem to have a really hard time exporting bone pose and bone animations to our game engine format. The documentation for FBX SDK doesn't seem to help at all and I have been trying to look at the samples, although I don't get the concepts properly, I have managed to make some progress but still the end result does not seem t work. So I would like to explain what I do and hopefully someone can shed some light and provide some direction.


Like any typical game engine here is how my skinning and bone animation system works, to calculate the transform of any bone at any point of time in the animation, I use the following formula:


boneCurrentLocalTransform = boneInterpolatedLocalTransformAtTimeX * inverseBindPoseTransform;


To extract the bone structure, I use FbxScene GetPostCount and GetPose methods and search to find the pose that contains current mesh node. Using the matched pose I build my skeleton hierarchy. At this point I need to assign an inverseBindPoseTransform to each bone in the hierarchy. So what I do is to go through all the clusters in the mesh skin and calculate the inverseBindPose function using the following code I extracted from FBX samples:


FbxAMatrix GetGeometry(FbxNode* pNode)


  constFbxVector4 lT = pNode->GetGeometricTranslation(FbxNode::eSourcePivot);

  constFbxVector4 lR = pNode->GetGeometricRotation(FbxNode::eSourcePivot);

  constFbxVector4 lS = pNode->GetGeometricScaling(FbxNode::eSourcePivot);

  returnFbxAMatrix(lT, lR, lS);




void ComputeClusterDeformation(FbxMesh* pMesh,

FbxCluster* pCluster,

FbxAMatrix& lClusterRelativeInitPosition)


  FbxAMatrix lReferenceGlobalInitPosition;

  FbxAMatrix lClusterGlobalInitPosition;

  FbxAMatrix lReferenceGeometry;


  // Multiply lReferenceGlobalInitPosition by Geometric Transformation

  lReferenceGeometry = GetGeometry(pMesh->GetNode());

    lReferenceGlobalInitPosition *= lReferenceGeometry;

  // Get the link initial global position


  // Compute the initial position of the link relative to the reference.

  lClusterRelativeInitPosition = lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;



So the inverse bindPose for a cluster would be

FbxAMatrix inversebindPoseMatrix;

ComputeClusterDeformation(m_mesh, cluster, inversebindPoseMatrix);


And then I convert to my own engine matrix format

FbxVector4 translation = inversebindPoseMatrix.GetT();

FbxQuaternion rotation = inversebindPoseMatrix.GetQ();

FbxVector4 scaling = inversebindPoseMatrix.GetS();


Matrix4 translationMatrix;

Matrix4 rotationMatrix;

Matrix4 scaleMatrix;




Vector3(static_cast<float>(translation[0]), static_cast<float>(translation[1]), static_cast<float>(translation[2])));




Quaternion(static_cast<float>(rotation[0]), static_cast<float>(rotation[1]), static_cast<float>(rotation[2]), static_cast<float>(rotation[3])));




Vector3(static_cast<float>(scaling[0]), static_cast<float>(scaling[1]),static_cast<float>(scaling[2])));


Matrix4 inverseBindPoseTransform = translationMatrix * rotationMatrix * scaleMatrix;


To extract the animation for each bone at a specific time i use the following code


FbxTime time;



FbxAMatrix transform;


if (isRootBone)


    transform = linkNode->EvaluateGlobalTransform(time);




    transform = linkNode->EvaluateLocalTransform(time);



SkeletonAnimationKey keyValue;

// time in seconds

keyValue.m_time = currentTime * 0.001f;


FbxVector4 translation = transform.GetT();

FbxQuaternion rotation = transform.GetQ();

FbxVector4 scaling = transform.GetS();


keyValue.m_position[0] = static_cast<float>(translation[0]);

keyValue.m_position[1] = static_cast<float>(translation[1]);

keyValue.m_position[2] = static_cast<float>(translation[2]);

keyValue.m_rotation[0] = static_cast<float>(rotation[0]);


keyValue.m_rotation[1] = static_cast<float>(rotation[1]);

keyValue.m_rotation[2] = static_cast<float>(rotation[2]);

keyValue.m_rotation[3] = static_cast<float>(rotation[3]);



keyValue.m_scale[0] = static_cast<float>(scaling[0]);

keyValue.m_scale[1] = static_cast<float>(scaling[1]);

keyValue.m_scale[2] = static_cast<float>(scaling[2]);


Basically this is how the keys are generated for each bone node in the hierarchy. I interpolate between the keys at specific time to generate boneInterpolatedLocalTransformAtTimeX.


Alas after all these effort my mesh is still getting rendered messed up and it seems to be skinning issue. I am wondering if I am not calculating the bone animation transformations or bind poses properly.


One other thing to mention is that I exported vertices from the mesh directly without any manipulation. Basically what ever I get from GetControlPoints method of the mesh, I exported directly without multiplying againts any transformation.


I have also attached the fbx I am using to test + screen shot of  the resulting skinned mesh during animation. Thanks in advance.


FBX file: https://drive.google.com/file/d/0B5Eh4ET-2pNQdU96cGFKNlhkeFU/edit?usp=sharing


Share this post

Link to post
Share on other sites

I'm also working on a FBX converter and i tried your fbx dragon and got something that looked about the same :).


Right now i'm looking into if it could be a problem with the skeleton rather then the skinning as it looks right when i try a rigid mesh. All the parts looks good but they are in the wrong places. Might be worth taking a extra look that you skeleton looks right :).

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!