Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


FBX exporter - Calculating bind pose matrix and animation bone transforms


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
1 reply to this topic

#1 Ali Mohebali   Members   -  Reputation: 104

Like
0Likes
Like

Posted 25 November 2013 - 12:03 PM

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;

  pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);

  // Multiply lReferenceGlobalInitPosition by Geometric Transformation

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

    lReferenceGlobalInitPosition *= lReferenceGeometry;

  // Get the link initial global position

  pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);

  // 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;

 

cml::matrix_translation(

translationMatrix,

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

 

cml::matrix_rotation_quaternion(

rotationMatrix,

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

 

cml::matrix_scale(

scaleMatrix,

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;

time.SetMilliSeconds(currentTime);

 

FbxAMatrix transform;

 

if (isRootBone)

{

    transform = linkNode->EvaluateGlobalTransform(time);

}

else

{

    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_rotation.normalize();

 

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

 

Attached Thumbnails

  • Capture.PNG


Sponsor:

#2 DUDVim   Members   -  Reputation: 340

Like
0Likes
Like

Posted 01 December 2013 - 06:09 PM

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 :).






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