Page 1 of 1

How do bones/armatures/curves work together numerically?

Posted: Thu Jun 03, 2010 6:19 am
by SteveBaker
Background: I've been working in 3D graphics for 30 years, I've implemented skeletal mesh animation from scratch half a dozen times - so I have a clue. But I need help decyphering the armature information that blender provides so I can feed it to my own skeletal mesh rendering application.

I've written a Python exporter that saves out Armatures, Bones & IPO Curves - along with all of the data that blender lets you grab for those objects. Now I'm trying to make sense of what I see...and I'm having ZERO luck with it! I have the simplest test model imaginable - two bones with two of which rotates 90 degrees around the Y axis and back again. You can grab it at along with the XML file that my Python exporter produced from it (which basically just writes out all of the blender structures without doing anything to them...yet):

I have the per-vertex blendweight and blendindex stuff all figured out and I've written a shader that I've carefully tested and I know works to transform the vertices correctly, given a set of bind-to-pose matrices, one per bone per time-step.

The problem is that I'm having a terrible time understanding what the numbers that my Python exporter extracts actually MEAN. On the BONE objects, I see 'armaturespace' and 'bonespace' with both head and tail positions for each, also a 4x4 armaturespace matrix and 3x3 bonespace matrix - also a bonespace roll angle and a curve data for the X,Y,Z,W components of a quaternion rotation and X,Y,Z location for each bone at each time step. I also understand how the bone hierarchy is organized.

However, turning that information into a bunch of bind-to-pose matrices that I can use in my shader to transform the skin vertices is turning into a nightmare! I simply can't fathom out what all of these numbers are telling me!

For example: My python dump says that the first bone goes vertically up from (0,0,0) to (0,0,1) and the second from (0,0,1) to (0,0,2) - which makes sense - that's what I see in blender. But the armaturespace and bonespace matrices for both bones mysteriously rotate through 90 degrees around the X axis?!?


I didn't apply any rotations to the bones in the armature when I created it - and I can't think of any need for a 90 degree rotation - so what does this mean?

What I really need is a simple step-by-step explanation of the order of transform operations to get from a skin vertex in bind-pose to the animated position: given the data exposed to Python in the bone description and the quaternion for a particular timestep...exactly what math do I need?

Thanks in advance...

Posted: Sat Jun 05, 2010 7:03 am
by an-toni
Is this old doc of any help? ... ures-work/

Otherwise perhaps some of the existing armature export codes can help too.


Posted: Sat Jun 05, 2010 3:47 pm
by SteveBaker
Thank you! That definitely looks useful - I'll dive into it tonight and see if I can get something to work.

Posted: Thu Jun 10, 2010 4:29 pm
by SteveBaker
I've worked through that document, and I thought I understood what it says - but the results don't work.

The second diagram seems to be telling me that I need to transform vertices by the "pose_mat" - which is basically:

pose_mat[N] = pose_mat[N-1].tail[N-1].head[N].mat[N].curve[N]

...but for the uber-simple two bone animation in, the first bone ends up with an identity matrix (which is good) - and the second bone gets:

pose_mat = I . tail [N-1] . I . I . curve[N]

(I is identity).

tail[N-1] is a one unit translation in +Z and for the first frame of the animation, the curve data is also identity.

So pose_mat ends up transforming the top cube +1 unit in Z...but it should be identity.

Hence, I'm either misunderstanding that document - or it's out of date for Blender 1.49.