Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Skeletal Animation Matrix Mess

This thread is locked; no one can reply to it. rss feed Print
Skeletal Animation Matrix Mess
Erin Maus
Member #7,537
July 2006
avatar

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:

#SelectExpand
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. :(

---
ItsyRealm, a quirky 2D/3D RPG where you fight, skill, and explore in a medieval world with horrors unimaginable.
they / she

Go to: