# Converting from Tree of Empty to Armature back to Tree of Empties

I'm writing an importer for an irregular model format. This is based on a 3dsmax script. The format stores the skeleton as a list of bones listing each bone's parents and two matrices, one called "Local Matrix" (Lmatrix) and one called "Absolute Matrix" (Amatrix).

The 3dsmax importer constructs the skeleton by creating a dummy for each bone, parenting them and setting their "transform" property to the Lmatrix . I tried doing this in blender by decomposing the Lmatrix and creating a bone for each empty, setting the tail to the parent's bone head (or the origin), setting the head to the translation and applying the rotation in pose mode. This didn't work.

I found out that using empties by setting their matrix_local to the Lmatrix gave the correct results position wise.

def createArmature(formatArmature, data):
miniscene = {}
createRootNub(miniscene)
for ix, bone in enumerate(armature):
if "Bone.%03d"%ix not in miniscene:
createNub(ix, bone, formatArmature, miniscene)
miniscene["Bone.%03d"%255].name = '%s Armature'%processPath(data.path)
data.armature = miniscene
return

def createRootNub(miniscene):
o = bpy.data.objects.new("Bone.%03d"%255, None )
miniscene["Bone.%03d"%255]=o
o.show_wire = True
o.show_x_ray = True
return

def createNub(ix, bone, armature, miniscene):
o = bpy.data.objects.new("Bone.%03d"%ix, None )
miniscene["Bone.%03d"%ix]=o
parentName = "Bone.%03d"%bone["parentId"]
if parentName not in miniscene:
createNub(bone["parentId"],armature[bone["parentId"]],miniscene)
o.parent = miniscene[parentName]
for property in bone:
o[property]=bone[property]
o.matrix_local = bone["lmat"]
o.show_wire = True
o.show_x_ray = True
o.show_bounds = True


However unlike 3dsMax, blender (at least as far as I've been able to find) doesn't really do rigging to a tree of empties, only armatures. So I figured out that with the empties already in the correct position creating a skeleton that simply connected the nodes should result in the correct positions.

def emptyToSkeleton(empty, armature):
children = []
for child in empty.children:
ix = int(child.name.replace("Bone.",""))
blenderBone = armature.edit_bones.new("TBone.%03d"%ix)
blenderBone.head = Vector([empty.matrix_world[i][3] for i in range(3)])
blenderBone.tail = Vector([child.matrix_world[i][3] for i in range(3)])
for sonBone in emptyToSkeleton(child, armature):
sonBone.parent = blenderBone
children.append(blenderBone)
for property in empty.keys():
blenderBone[property]=empty[property]
return children


This worked fine visually, however I suspected that rotations would be missing or completely wrong. Which I confirmed when converting back the armature to a tree of empties with the following code and seeing that the matrix_local had changed in the process.

def posedSkeletonToEmpty(bone, root):
ix = int(bone.name.replace("TBone.",""))
empty = bpy.data.objects.new("EBone.%03d"%ix, None )