Animation Space Conversion

I’m writing an importer for a game format and everything is fully functional except for the animations, which are still not affecting the skeleton as intended.

Here’s an example skeleton in rest pose:

Note that the conversion from node to blender bone format is done with the following code, so the bones are reliable and their original matrices can easily retrieved from the bones:

bone.head = mathutils.Vector((0,0,0))       
bone.tail = mathutils.Vector((1,0,0))

Now the animations, I can correctly visualize them as a tree of animated empty objects, but I need to transfer these transformations onto an armature.

My assumptions are:

  • empty transformations are relative to the parent empty (ie. there is no rest pose; the original, unkeyframed transformation is simply overwritten)
  • bone transformations are relative to the bone’s own rest pose
  • the coordinate axes used by blender bones and my animated empties are different

Which means that to get from the empty object transformations to a bone transformations, I think I have to do two things:

  • remove the rest pose from the transformations
  • change the coordinate system (the blender bones point in Y-direction, while the empties point in X-direction)

My keyframes are stored in 4x4 matrices, key_mat.

To remove the rest pose from the transformations, I do:

key_mat = key_mat * node_rest_mat.inverted()

(I’ve also tried the “commute”, ie. key_mat = rest_mat.inverted() * key_mat)

To change the coordinate system, I do the following and it seems to work on the tree of empties:

matrix_swap = mathutils.Euler((math.radians(90), 0, math.radians(90))).to_matrix().to_4x4().inverted()
key_mat = matrix_swap.inverted() * key_mat * matrix_swap

I have also tried axis_conversion(…) from bpy_extras.io_utils but could not get the same result.

The result has the Y axis pointing forward as intended, and is globally rotated as well. Local animations are preserved:

So if I do the steps as described above and put everything together, I’m getting a distorted skeletal animation but not the desired result:

I just can’t seem to produce code that puts those two together into something that creates equivalent animations on the skeleton.
Any ideas on how to correctly transfer the keyframes from these empties onto the bones?

Problem solved, see for solution.