11
$\begingroup$

I'm currently writing an exporter script. So far, I can export meshes just fine, but I've got some problems with exporting the armature.

According to the python api, there are three different types of bones:

There's also this old (or rather: ancient) guide on how armatures work: http://www.blender.org/development/release-logs/blender-240/how-armatures-work , but I can't find a proper mapping between that document and the current api.

I know I can get the restpose of the armature by grabbing the bone.matrix_local, but this matrix is relative to the armature.

So... How do you grab the bones matrices so that the transform is relative to the parent instead of relative to the armature?

I tried exporting the bones relative to their parent by multiplying the inverse of the parents matrix_local by the bones matrix_local, but that does seem to result in incorrect translation values.

This is how I currently grab the parent-relative matrices:

        #I'm interested in the rest pose here, so I iterate over the bones
        for bone in armature.data.bones:                
            #make matrix of this bone relative
            boneMat = mathutils.Matrix.Identity(4)
            if bone.parent == None:
                boneMat = bone.matrix_local
            else:
                boneMat = bone.parent.matrix_local.inverted() * bone.matrix_local

            #decompose
            loc, quat, sca = boneMat.decompose()

By the way: I'm using blender 2.66.1 w/the included python

$\endgroup$
0

2 Answers 2

9
$\begingroup$

The code snippet you give seems to be correct if you want the transform from the head of the parent bone to the head of the child bone.

How is the translation incorrect? There are supposed to be two translations between these bones, one from the head of the parent to its tail, and (if the child is not connected to the parent) one from the tail of the parent to the head of the child.

In the 2.40 armatures guide, bone.matrix is bone_mat and bone.matrix_local is arm_mat. This is how they relate in python:

# parent head to tail, and parent tail to child head
bone_translation = Matrix.Translation(Vector((0, bone.parent.length, 0)) + bone.head)
# parent armature space matrix, translation, child bone rotation
bone.matrix_local == bone.parent.matrix_local * bone_translation * bone.matrix.to_4x4()
$\endgroup$
1
  • 1
    $\begingroup$ I'm planning on using the exported models in an openGL program. Somewhere between the export and displaying them on screen, something goes wrong. Now I can rule out the exporter as an error source. Thank you. Your explanation of the relation between matrix and matrix_local is really helpfull too. I wish this was explained better in the api docs. $\endgroup$
    – Exilyth
    Jul 9, 2013 at 19:23
5
$\begingroup$

To get real local-to-parent position and rotation of each bone I do this. Strange, but this works. Difference from OP is result quaternion must be inverted.

mat_local_to_parent = (
    bone.matrix_local if bone.parent is None else
    bone.parent.matrix_local.inverted() * bone.matrix_local
)
pos = mat_local_to_parent.to_translation()
quat = mat_local_to_parent.to_quaternion().inverted()
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .