Inside Sabertooth
Learn how Sabertooth uses 3ds Max to create 3D interactive projects, including HBO Go’s Game of Thrones interactive experience
  • 1/3
You are here: Forum Home / Autodesk® FBX® / FBX SDK / Still can't get skeleton's bind pose
  RSS 2.0 ATOM  
2 pages: 1.2 last

Still can't get skeleton's bind pose
Rate this thread
 
49501
 
Permlink of this thread  
avatar
  • Location: Midvale, UT
  • Total Posts: 144
  • Joined: 25 March 2010 10:49 AM

Howdy,

I’ve been searching the forum for information on getting the joint skeleton’s bind pose, and came across this post:
http://area.autodesk.com/forum/187980

... but that code doesn’t work.

Here is my implementation of that code:

KFbxSkinlSkinDeformer reinterpret_cast<KFbxSkin*>(pMesh->GetDeformer(0KFbxDeformer::eSKIN));

int lClusterCount lSkinDeformer->GetClusterCount();
for( 
int ilClusterCount++ )
{
 KFbxCluster
lFbxCluster lSkinDeformer->GetCluster(i);
 
KFbxNodelLinkNode lFbxCluster->GetLink();
 if(
lLinkNode)
 
{
 KFbxXMatrix lFbxLinkMatrix
;
 
lFbxCluster->GetTransformLinkMatrixlFbxLinkMatrix );
 
 for(
vector<JointNode*>::iterator it=jointList.begin(); it != jointList.end(); it++)
 
{
 JointNode 
*jn = (*it);
 if(
lLinkNode == jn->node)
 
{
 BaseObject 
*joint jn->joint;
 
Matrix jntM KFbxXMatrixToMatrix(lFbxLinkMatrix);
 
joint->SetMg(jntM); // set joint's global matrix
 
 
break;
 
}
 }
 }
}

... and this is the result:
FBXBindPose.jpg

The only difference between my code and the code in the link is the vector list of skeleton nodes and my joint objects:

struct JointNode
{
 BaseObject 
*joint;
 
KFbxNode *node;
 
 
JointNode(BaseObject *jKFbxNode *n)
 
{
 joint 
j;
 
node n;
 
}
}
;

... which is simply a vector list of a structure storing a pointer to the KFbxNode skeleton node and the BaseObject joint.

The file I’m testing is the humanoid.fbx file that is provided with the FBX SDK, and there are no poses stored in that file.
The result of pScene->GetPoseCount(); is 0.

There are some other weird things about that file, too. For example if I only import the skeleton and the mesh (without trying to find a bind pose for the skeleton), and get the nodes’ global matrices with pNode->GetGlobalFromDefaultTake();, there seems to be a mismatched scaling issue:
FBXDefaultScaling.jpg

... the mesh is scaled (2.544, 2.544, 2.544) and the skeleton’s root joint is scaled (0.165, 0.165, 0.165).

Is there a better way to get the bind pose from the clusters (when there’s no bind pose stored) that works?

Adios,
Cactus Dan



Replies: 0
avatar

Hello, Cactus Dan, from you code I can see you missed geometry transform. Please try the following codes from ViewScene sample:

// Get the link initial global position and the link current global position.
 
pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
 
// Multiply lClusterGlobalInitPosition by Geometric Transformation
 
lClusterGeometry GetGeometry(pCluster->GetLink());
 
lClusterGlobalInitPosition *= lClusterGeometry;
// Get the geometry deformation local to a node. It is never inherited by the
// children.
KFbxXMatrix GetGeometry(KFbxNodepNode{
    KFbxVector4 lT
lRlS;
    
KFbxXMatrix lGeometry;

    
lT pNode->GetGeometricTranslation(KFbxNode::eSOURCE_SET);
    
lR pNode->GetGeometricRotation(KFbxNode::eSOURCE_SET);
    
lS pNode->GetGeometricScaling(KFbxNode::eSOURCE_SET);

    
lGeometry.SetT(lT);
    
lGeometry.SetR(lR);
    
lGeometry.SetS(lS);

    return 
lGeometry;
}

This is also mentioned by Dario in the link you referenced:
“Ah, I get it now—yes, we do use the TransformLinkMatrix, and we also use the TransformMatrix from the KFbxCluster objects: if we don’t combine these with the geometric transformation, we don’t get the correct deformations… “

Refer to the mismatch, the joints and model could have one transform without binding, and have another transform at binding moment, the former one could be mismatched, but if you get their transform at binding moment, then they must match.



Jiayang Xu
Maya Data Platform
Autodesk

Replies: 0
avatar

Howdy,

Well, adding that extra code gives me the exact same result:
FBXBindPose2.jpg

... notice that if I rotate a copy of the mesh -90º, the joints in red seem to match up to a rotated bind pose, but the rest of them are way off.

Here is the how I added the lines of code:

void CDImportFBXCommand::ExtractBindPoseFromSkinDeformer(KFbxNode *pNode)
{
 KFbxMesh 
*pMesh = (KFbxMesh*)pNode->GetNodeAttribute();

 
KFbxSkinlSkinDeformer reinterpret_cast<KFbxSkin*>(pMesh->GetDeformer(0KFbxDeformer::eSKIN));
 
 
int lClusterCount lSkinDeformer->GetClusterCount();
 for( 
int ilClusterCount++ )
 
{
 KFbxCluster
pCluster lSkinDeformer->GetCluster(i);
 
KFbxNodelLinkNode pCluster->GetLink();
 if(
lLinkNode)
 
{
 KFbxXMatrix lClusterGlobalInitPosition
;
 
pCluster->GetTransformLinkMatrixlClusterGlobalInitPosition );
 
 
// Multiply lClusterGlobalInitPosition by Geometric Transformation
 
KFbxXMatrix lClusterGeometry GetGeometry(lLinkNode);
 
lClusterGlobalInitPosition *= lClusterGeometry;
 
 for(
vector<JointNode*>::iterator it=jointList.begin(); it != jointList.end(); it++)
 
{
 JointNode 
*jn = (*it);
 if(
lLinkNode == jn->node)
 
{
 BaseObject 
*joint jn->joint;
 
Matrix jntM KFbxXMatrixToMatrix(lClusterGlobalInitPosition);
 
joint->SetMg(jntM); // set joint's global matrix
 
 
break;
 
}
 }
 }
 }
}

... the GetGeometry() function I already had in the common.cpp file.

I can load an animation take for the joint skeleton:
http://www.cactus3d.com/FBXImportTest2.mov

... which works great, but without a bind pose for the skeleton, I can’t skin the mesh to the joints. :(

Is there something I’m still missing?

Adios,
Cactus Dan



Replies: 0
avatar

Howdy,

Well, these lines of code aren’t changing anything:

lClusterGeometry GetGeometry(pCluster->GetLink());
lClusterGlobalInitPosition *= lClusterGeometry;

... because when I print out the matrix result of GetGeometry(), it’s always:
1,0,0,0
0,1,0,0
0,0,1,0
0,0,0,1

... for every node. :(

Isn’t that the identity matrix? And isn’t it true that if you multiply any matrix by the identity matrix, the result is the same as the original matrix?

Adios,
Cactus Dan



Replies: 1
/userdata/avatar/vx3501hqr_small.jpg

Hi, Cactus, the geometric transform just happened to be an identity matrix in your case, that does not mean it is always an identity matrix.
To make the code work in general, for sure you need to take account of the geometric transform.

Author: Jiayang Xu

Replied: 23 November 2010 06:08 PM  
avatar
  • TravF
  • Posted: 17 November 2010 05:49 AM

Just for clarification, a FBX file can contain several bind poses, and not just a ‘bind pose’.  There are bindposes
stored in GetPose(), (I guess you could call them ‘extra bindposes’) and there is also the ‘default bindpose.’
The ‘default bindpose’ is not stored in GetPose(), so it shouldn’t matter if GetPoseCount() returns zero.

So, I think it would be best to refer to it as the ‘default bindpose’, just for sanity sake. :)

[ BTW, there is some techincal info in kfbxpose.h about the different between bind poses
and rest poses, which are both stored in GetPose().  Might be helpful. ]



Replies: 0
avatar

Howdy,

So, where would this “default bind pose” be stored, and how would I access it?

Adios,
Cactus Dan



Replies: 0
avatar
  • TravF
  • Posted: 17 November 2010 10:11 AM

Sorry, let me re-phrase it.  The ‘default bind pose’ for me is the global node transform at
time zero.  The data in KFbxSkin tells how to bind the mesh geometry to the skeleton.
I don’t think KFbxSkin can be used as a “bind pose” by itself.



Replies: 0
avatar

Howdy,

Well, the mesh isn’t deformed so that won’t work. :(

Adios,
Cactus Dan



Replies: 0
avatar
  • TravF
  • Posted: 17 November 2010 10:41 AM

I’m saying you can deform the mesh at time zero yourself.  The main functions you need are
DrawMesh() and ComputeShapeDeformation() from the ViewScene SDK example.

You can ignore all references to KFbxPose.



Replies: 0
avatar

Howdy,

Well, if there is a way to calculate the bind pose that fits the mesh, I’d prefer it that way, because I’ll be converting everything to my own joints and skinning. Which might also make it easier to load additional takes that are just the joint animations.

Is that even possible? I’ve seen some posts where others have asked this same thing and some example code is posted, but none of the code seems to work, and none of the threads have an update on whether or not it worked. :(

Adios,
Cactus Dan



Replies: 0
avatar
  • TravF
  • Posted: 17 November 2010 11:19 AM

I don’t think that’s possible.

The data in KFbxSkin binds/deforms the mesh geometry to the skeleton.  Not the other way around.
Maybe that was your problem?

As far as I know, this is a one-way bind.

If there is a way, I would like to see a screenshot! :)



Attachment Attachment
Replies: 0
2 pages: 1.2 last