|
Hi.
I am facing a really strange problem when playing an animated model. The model is composed of several clusters and several meshes (KFbxMesh). My code is based on the ViewScene example, except that I am sending the influence matrices and weights to a vertex shader and using them to compute the final vertex position. The problem is I am getting different results depending on how (when, actually) I compute these matrices.
This is how I update the clusters:
//UpdateAll(mScene->GetRootNode()); // #1
for (unsigned int i=0; i < meshes.size(); ++i) {
//UpdateMesh(meshes[i].node); // #2 }
for (unsigned int i=0; i < meshes.size(); ++i) {
UpdateMesh(meshes[i].node); // #3
drawMesh(meshes[i]); }
The animation only plays right when I use #3, but I would expect #1 and #2 to work as well. Is there a reason for this to happen? I already debugged ComputeClusterDeformation and the order that the nodes are evaluated and its final matrices are exactly the same when using any of the alternatives, but somehow only #3 gives the correct result. The only thing I can think of is that the information is being corrupted when being sent to the shader, but even this doesn’t make sense to me.
It is worth mentioning that if I remove all the meshes but one in 3ds Max, the remaining mesh is animated correctly. But if I load the original model and manually ignore the meshes that were removed, the result is also not correct (but coherent with the “wrongness” of the original model).
These are the functions that I use for traversing the nodes:
void ModelFBX::UpdateMesh(KFbxNode* pNode) {
KFbxXMatrix lGlobalOffPosition = GetGlobalPosition(pNode) * GetGeometry(pNode);
KFbxSkin* lSkinDeformer = (KFbxSkin *) pNode->GetMesh()->GetDeformer(0, KFbxDeformer::eSKIN);
int lClusterCount = lSkinDeformer->GetClusterCount();
for (int i=0; i < lClusterCount; ++i) {
ComputeClusterDeformation(lGlobalOffPosition, pNode, lSkinDeformer->GetCluster(i));
}
}
void ModelFBX::UpdateAll(KFbxNode* pNode) {
if (pNode->GetNodeAttribute() && pNode->GetNodeAttribute()->GetAttributeType() == KFbxNodeAttribute::eMESH) {
UpdateMesh(pNode);
}
int lChildCount = pNode->GetChildCount();
for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
UpdateAll(pNode->GetChild(lChildIndex));
}
}
I hope that someone can point out the stupid mistake I am making.
EDIT: Some more info:
For each mesh, I precalculate a matrix (actually, a texture) of size nClusters X nVertices containing the weights of each cluster for each vertex, then the appropriate matrix is sent to the shader when the mesh is to be rendered. This is what makes it possible (hopefully!) to compute the displacement of each vertex only once (in the vertex shader).
EDIT2: SOLVED
The problem was that the final matrix of each cluster depends on matrices that are specific to the mesh. Fixed this to re-update only what is needed and now it works (not the way I intended, but pretty close to it).
|