Manually building bindpose matrices in FBX SDK

Manually building bindpose matrices in FBX SDK

Anonymous
Not applicable
4,224 Views
1 Reply
Message 1 of 2

Manually building bindpose matrices in FBX SDK

Anonymous
Not applicable

Hi everyone, I've been running into a strange issue where my bindpose matrices are getting incorrect values compared to what I'm expecting from Maya. I'm using a different approach compared to the more common GetTransformLinkMatrix on the current cluster to receive its bindpose matrix. This strategy worked in FBX SDK 2015 and its based on the EvaluateLocalTransform function which I use to store each joint's local transformation at the specified time. The specified time is FBXSDK_TIME_INFINITE, which should give me the bindpose the mesh was bound to without any animation curves evaluation. I want to do this to create the inversed bind pose matrix for the current joint so I can use this for my skeletal animation calculations. 

 

I start by initializng the root joint in order to be able to iterate through the joint hierarchy using the parent index I've received from a depth-first search algorithm I used when reading the contents from the FBX file. By doing so, I should be able to manually create a joint's bindpose by multiplying the current joint's local transform with the parent joint's local transform. The motivation for this was to detach as much of the logic as possible from FBX so that the same approach can (hopefully) be used for other formats.

 

Now suddenly, when upgrading to FBX SDK 2017.0.1, this no longer works. It might also be worth to mention that I'm using animation layers and that I've experienced issues in which they modify the bindpose matrices depending on if I mute them or not before exporting. Are there any options with animation layers I should take extra notice on when working with layers? Is there a unique bindpose under every layer? I haven't bound more than one mesh to the same skeleton, so I've unchecked in my skin bind settings to not allow more than one bind pose. On the base animation layer, I only have the mesh in bindpose and no keyframes applied. I've only used this strategy without animation layers, but they shouldn't affect the transform values since I've specified FBXSDK_TIME_INFINITE. So to my question, is this actually a valid way of manually building your bindpose matrices or is there a better way? By using TransformLinkMatrix, I receive the same invalid values so I get the feeling that something else is messing up my bindpose. Any help would be appreciated, I feel rather lost at the moment since this used to work for me back in 2015. 

 

I'm going to attach my bind settings, the structs I'm using to gather data and the algorithm I use with comments for each step. I'm also going to include a log file where I display the raw values from the matrices, column major from the FbxAMatrix type. 

 

Mesh is a wrapper to the skin node

 

struct Mesh { 

 

  string name

  FbxMesh* meshNode;
  FbxSkin* skinNode;

 

}

 

Joint is a wrapper to the matrices

 

struct Joint {

 

  string Name;
  int ParentIndex;

 

  FbxAMatrix GlobalBindposeInverse;
  FbxAMatrix LocalTransform;
  FbxAMatrix GlobalTransform;

  FbxNode* Node;

 

}

 

// Get the root joint node which is the first cluster in the skin.
FbxCluster* currentCluster = pMesh.skinNode->GetCluster(0);

currentCluster->GetName();

 

// Initialize the root joint first. By doing so, we make sure no children is evaluated before its parent
pMesh.skeleton.hierarchy[0].LocalTransform = currentCluster->GetLink()->EvaluateLocalTransform(FBXSDK_TIME_INFINITE);
pMesh.skeleton.hierarchy[0].GlobalTransform = pMesh.skeleton.hierarchy[0].LocalTransform;
pMesh.skeleton.hierarchy[0].GlobalBindposeInverse = pMesh.skeleton.hierarchy[0].GlobalTransform.Inverse();

 

// Loop through all the joints in the hierarchy
for (int i = 1; i < NUM_BONES; i++) {

 

    // Receive the current joint cluster
    currentCluster = pMesh.skinNode->GetCluster(i);

 

   // Create a reference to the currenct joint in the hierarchy to be processed
   Joint &b = pMesh.skeleton.hierarchy[i];

 

   // Get the current joint LOCAL transformation
   b.LocalTransform = currentCluster->GetLink()->EvaluateLocalTransform(FBXSDK_TIME_INFINITE);

   // Calculate the current joint GLOBAL transformation by taking the global transformation of the parent

   multiplied by this joint LOCAL transformation
   b.GlobalTransform = pMesh.skeleton.hierarchy[b.ParentIndex].GlobalTransform * b.LocalTransform;

 

   // The inverse bind pose is calculated by taking the inverse of the joint GLOBAL transformation matrix
   b.GlobalBindposeInverse = b.GlobalTransform.Inverse();

 

}

0 Likes
Accepted solutions (1)
4,225 Views
1 Reply
Reply (1)
Message 2 of 2

Anonymous
Not applicable
Accepted solution

Problem solved, there was a faulty in my joint tool settings. I had to check "Orient joint to World" to receive the correct values. Now both methods work, the manual method and the TransformLinkMatrix approach. I hope this can help anyone out there experiencing the same problem.

0 Likes