TurkeyMan
2013-10-13
I have been trying to wrangle an obscure animation problem for a couple of weeks now, and I've become rather frustrated. Rather than go through everything I've tried, I'll just state my goal directly, and ask if anyone can think how to do it properly :)
Assimp seems to presume you want to animate in node-local space, it provides this mOffsetMatrix to transform the animation matrices into the node's space, and when I do it the assimp way, it does work.
What I actually want to do is skin in world space, not node-space.
The reason for this is I can calculate the animation state only once for the whole mesh, instead of having to produce a set of distinct bone batches which are each multiplied by mOffsetMatrix per node.
My approach:
Transform all vertices into world space, ie, multiply all vertices by their node matrix. This is my mesh data.
Transform all animations into world space. I imagine this should be something like animatedBoneMatrix*inverseBindPoseMatrix. I should then be able to apply these to the mesh directly.
This works, in simple animations... except it just doesn't work for more complex animations, and I can't work out where I've gone wrong. It seems almost like one of my source matrices (bone matrix, animation matrix or node matrix) are just not quite right, or in an unexpected space.
When I try to track it down, ie, understand the source of the error, I uncover strange problems that just confuse me more.
For instance, mOffsetMatrix is said to be inverse(boneInBindPose) * nodeMatrix (I can see from FBXConverter.cpp:1270), so when I try and fabricate an offsetMatrix myself using inverse(bindMatrix) * nodeMatrix, which should be identical to mOffsetMatrix, I find that the matrix produced is different...
Why is it different? How do I actually calculate mOffsetMatrix?
But more importantly, I just want to know how to transform the animation into world space, so I can apply it to flat, world-space vertices.
I've tried to understand the problem from a whole heap of angles, but nothing seems to add up.
I've tried to transform mOffsetMatrix back into world space by: mOffsetMatrix * inverse(nodeMatrix), but that doesn't seem to work.
I got desperate and tried to manufacture mOffsetMatrix every way I could think, fiddling with multiply orders out of desperation. but none of these are correct:
MFMatrix test[8];
test[0].Multiply4x4(n, b);
test[1].Multiply4x4(n, invB);
test[2].Multiply4x4(invN, b);
test[3].Multiply4x4(invN, invB);
test[4].Multiply4x4(b, n);
test[5].Multiply4x4(b, invN);
test[6].Multiply4x4(invB, n); // this is the one I expect should be mOffsetMatrix
test[7].Multiply4x4(invB, invN);
Where 'n' is the node matrix and 'b' is the bind-pose matrix.
Please update the documentation surrounding mOffsetMatrix, there is very little detail to work from, I have no idea what it is, and I can't seem to produce it from raw parts no matter what I do...
Thanks.
- Manu