|
Skeletal Animation Matrix Mess |
Erin Maus
Member #7,537
July 2006
|
Hi, I'm trying to generate the inverse bind pose matrices for a model using Assimp. Assimp only gives the IBP matrices for bones with vertices. I need them for all bones. I figured the IBP should be the inverse of the world transform of each bone: 1void exportBoneNode(
2 const aiScene* scene,
3 const aiNode* parent,
4 const aiNode* node,
5 const aiMatrix4x4& matrix,
6 FILE* output)
7{
8 std::fprintf(output, "\t[\"%s\"] = {\n", node->mName.C_Str());
9 if (parent)
10 {
11 std::fprintf(output, "\t\tparent = \"%s\",\n", node->mParent->mName.C_Str());
12 }
13
14 aiMatrix4x4 nodeWorldTransform = matrix * node->mTransformation;
15 aiMatrix4x4 nodeInverseBindPoseTransform = nodeWorldTransform;
16 nodeInverseBindPoseTransform.Inverse();
17
18 auto nodeInverseBindPoseMatrixElements = &nodeInverseBindPoseTransform.a1;
19 std::fprintf(output, "\t\tinverseBindPose = { ");
20 for (int j = 0; j < 16; ++j)
21 {
22 std::fprintf(output, "%f, ", nodeInverseBindPoseMatrixElements[j]);
23 }
24 std::fprintf(output, "},\n");
25 std::fprintf(output, "\t},\n");
26
27 for (int i = 0; i < node->mNumChildren; ++i)
28 {
29 exportBoneNode(scene, node, node->mChildren[i], nodeWorldTransform, output);
30 }
31}
32
33void exportSkeleton(const aiScene* scene, FILE* output)
34{
35 if (scene->mNumMeshes < 1)
36 {
37 std::fprintf(stderr, "no meshes\n");
38 return;
39 }
40
41 auto node = scene->mRootNode->FindNode("Armature");
42 if (!node)
43 {
44 std::fprintf(stderr, "no skeleton (must be node named 'Armature')\n");
45 return;
46 }
47
48 std::fprintf(output, "{\n");
49
50 aiMatrix4x4 identity;
51 exportBoneNode(scene, nullptr, node, identity, output);
52
53 std::fprintf(output, "}\n");
54}
But it's wrong. My inverse bind pose does not match the one Assimp has. It doesn't matter if I start with the skeleton or root bone; if I flip the matrix multiplication order when calculating nodeWorldTransform; negating the root transform; or anything else. The resulting matrix is wrong. For example, Assimp gives me: 1.000000, 0.000000, -0.000000, 0.194337, 0.000000, -1.000000, -0.000000, 0.358689, -0.000000, 0.000000, -1.000000, -0.000000, 0.000000, 0.000000, -0.000000, 1.000000 While my code gives me: 0.000000, -1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.358689, -1.000000, -0.000000, 0.000000, -0.194337, -0.000000, 0.000000, -0.000000, 1.000000 The Y translation is correct (0.35..., 8th component), but nothing else is. How do I calculate the inverse bind pose matrices from the skeleton in Assimp? edit: I wasn't multiplying by the scene root transform. Wow. I figured it would be identity but I was wrong. --- |
|