|
Tell us what you think of the site.
|
Autodesk Media & Entertainment User Community
|
Autodesk® 3ds Max®
|
|
Autodesk® Maya®
|
|
Autodesk® Softimage®
|
|
Autodesk® MotionBuilder®
|
|
Autodesk® Mudbox™
|
|
Autodesk® ImageModeler™
|
|
Autodesk® Sketchbook® Pro
|
|
Autodesk® Smoke on Mac®
|
| Still can't get skeleton's bind pose
|
|
|
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:
KFbxSkin* lSkinDeformer = reinterpret_cast<KFbxSkin*>(pMesh->GetDeformer(0, KFbxDeformer::eSKIN));
int lClusterCount = lSkinDeformer->GetClusterCount();
for( int i= 0 ; i < lClusterCount; i ++ ) {
KFbxCluster* lFbxCluster = lSkinDeformer->GetCluster(i);
KFbxNode* lLinkNode = lFbxCluster->GetLink();
if(lLinkNode)
{
KFbxXMatrix lFbxLinkMatrix;
lFbxCluster->GetTransformLinkMatrix( lFbxLinkMatrix );
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:

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 *j, KFbxNode *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:

... 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
|
|
|
|
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(KFbxNode* pNode) {
KFbxVector4 lT, lR, lS;
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
|
|
|
|
Howdy,
Well, adding that extra code gives me the exact same result:

... 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();
KFbxSkin* lSkinDeformer = reinterpret_cast<KFbxSkin*>(pMesh->GetDeformer(0, KFbxDeformer::eSKIN));
int lClusterCount = lSkinDeformer->GetClusterCount();
for( int i= 0 ; i < lClusterCount; i ++ )
{
KFbxCluster* pCluster = lSkinDeformer->GetCluster(i);
KFbxNode* lLinkNode = pCluster->GetLink();
if(lLinkNode)
{
KFbxXMatrix lClusterGlobalInitPosition;
pCluster->GetTransformLinkMatrix( lClusterGlobalInitPosition );
// 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
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
|
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. ]
|
|
|
|
Howdy,
So, where would this “default bind pose” be stored, and how would I access it?
Adios,
Cactus Dan
|
|
|
|
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.
|
|
|
|
Howdy,
Well, the mesh isn’t deformed so that won’t work. :(
Adios,
Cactus Dan
|
|
|
|
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.
|
|
|
|
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
|
|
|
|
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
|
|
|
|
|
|