1
\$\begingroup\$

I tried to obtain bone transform matrix for animation implemented with Directx11 and FBX sdk. I found this function in some web resources:

fbxCluster->GetLink()->EvaluateGlobalTransform();  // base pose

It seems that it is able to recursively calculate global transformation of each bone, thus I don't need to traverse the node tree. However the result obtained from it is weird.

The obtained globalBoneBaseMatrix is used in vertex shader:

void MeshImporter::LoadWeight(FbxNode* fbxNode, MeshEntry* mesh)
{
    FbxMesh* fbxMesh = fbxNode->GetMesh();
    int numSkin = fbxMesh->GetDeformerCount(FbxDeformer::eSkin);

    if (numSkin == 0)
    {
        return;
    }

    assert(numSkin == 1);

    // Assume only one deformer
    FbxSkin* fbxSkin = static_cast<FbxSkin*>(fbxMesh->GetDeformer(0, FbxDeformer::eSkin));
    int numCluster = fbxSkin->GetClusterCount();
    int numControlPoints = fbxMesh->GetControlPointsCount();
    vector<VertexWeight> tmpWeightList(numControlPoints);

    for (int i = 0; i < numCluster; i++)
    {
        FbxCluster* fbxCluster = fbxSkin->GetCluster(i);
        unsigned int boneIndex = model->skeleton->bones.size();

        assert(fbxCluster->GetLinkMode() == FbxCluster::eNormalize);

        // Read skeleton bones data (transformation matrix of each bone)
        string boneName(fbxCluster->GetLink()->GetName());

        if (!model->skeleton->FindBoneByName(boneName))
        {
            if (boneIndex >= MAXBONE)
            {
                PrintTab("Too many bones to load!!");
            }
            else
            {
                // Read weights of each vertex
                int numIndexInCluster = fbxCluster->GetControlPointIndicesCount();
                int* indicesInCluster = fbxCluster->GetControlPointIndices();
                double* weights = fbxCluster->GetControlPointWeights();

                for (int j = 0; j < numIndexInCluster; j++)
                {
                    tmpWeightList[indicesInCluster[j]].AddBoneData(boneIndex, weights[j]);
                }

                // Normalize weights
                /*for (int inVert = 0; inVert < tmpWeightList.size(); inVert++)
                {
                    tmpWeightList[inVert].Normalize();
                }*/

                // Read animation bone matrix
                XMFLOAT4X4 globalBoneBaseMatrix;
                FbxAMatrix fbxGlobalBoneBaseMatrix = fbxCluster->GetLink()->EvaluateGlobalTransform();

                if (i == 0)
                {
                    for (int r = 0; r < 4; r++)
                        for (int c = 0; c < 4; c++)
                        {
                            globalBoneBaseMatrix.m[r][c] = (float)fbxGlobalBoneBaseMatrix.mData[r][c];

                            PrintTab("Global mat: " +     to_string(fbxGlobalBoneBaseMatrix.mData[r][c]));
                        }
                }

                Bone bone;
                bone.name = boneName;
                bone.globalBoneBaseMatrix = globalBoneBaseMatrix;
                bone.boneIndex = boneIndex;
                bone.fbxNode = fbxNode;

                model->skeleton->bones.push_back(bone);
            }
        }
    }
}

My code reading animation data:

// Animation transform data
struct AnimationConstantBuffer
{
    XMFLOAT4X4 meshBoneMatrices[MAXBONE];
};

Vertex shader:

PixelShaderInput output;
float4 pos = float4(input.pos, 1.0f);

// Test animations
matrix boneTransform = 
    BoneMatrices[input.boneIndices.x] * input.weights.x +
    BoneMatrices[input.boneIndices.y] * input.weights.y +
    BoneMatrices[input.boneIndices.z] * input.weights.z +
    BoneMatrices[input.boneIndices.w] * input.weights.w;

pos = mul(pos, boneTransform);
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;
...

And for testing, I did not update the bone matrix in real time. I'm not sure whether the way I use it is correct, but the rendering result is obviously wrong. There might be other mistakes.

\$\endgroup\$

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.