# Calculating final Bone/PoseBone matrices

I'm writing an exporter and am trying to export the animations but I'm not certain of what space the matrices are in or what they're relative to (if anything) and the docs don't really give much info at all about any class variable.

I believe the Bind Pose matrix should come from PoseBone.bone.matrix_local. Since it's being called a 'local' matrix I would assume that it's relative to its parent but then the docs say it's in armature-space. What does this matrix really represent?

I'm trying to export the final pose matrix for each bone for a given frame but I tend to either have very incorrect matrices or they seem to not be inheriting a rotation somewhere.

rig_ui.py calculates a pose matrix like this:

rest = posebone.bone.matrix_local.inverted()
par_rest = posebone.bone.matrix_local.inverted()
par_inv = posebone.parent.matrix.inverted()
final = rest * par_rest * par_inv * posebone.matrix


This results in the armature pose seeming to lose an ancestor's rotation somewhere. What I don't understand is why none of the other scripts actually use ancestor's matrices if bone.matrix_local actually is relative to its parent. Won't it need to have accumulated every ancestor? Am I misunderstanding what space either bone.matrix_local or posebone.matrix is in?

Some scripts/exporters are also using the inverse of the pose bone's parent's matrix or the inverse of the bone's parent's matrix_local (before applying that to that bone's matrix_local which is not inverted). My understanding was that only the bind pose matrices need to be inverted and ALL of them must be inverted.

• Your rest and par_rest are identical, that doesn't seem correct. – CodeManX Oct 16 '13 at 23:00
• Its hard to give a definitive answer to this question, mainly because it always depends on the space which the format expects the bones in. – ideasman42 Oct 17 '13 at 2:07
• It expects final pose matrix -- the matrices to be sent to the video card – luminos Oct 17 '13 at 2:54
• @luminos: You mean each bone's global matrix? Then PoseBone.matrix might be adequate. It is final; the matrix is usable to snap other object to the pose bone's position. – Adhi Oct 17 '13 at 3:30
• @Adhi: Yes it looks like it is the one I want. I was a bit confused by what some other scripts were doing but I suppose they were trying to undo some transformations. – luminos Oct 18 '13 at 2:21

A straight-forward approach using convert_space() and a matrix to convert bone space:

import bpy

arma_ob = bpy.context.object
mesh_ob = bpy.data.objects['Suzanne']

pose_bone = bpy.context.active_pose_bone

bone_space = Matrix(((1,0,0,0),(0,0,1,0),(0,-1,0,0),(0,0,0,1)))
mat = arma_ob.convert_space(pose_bone, pose_bone.matrix, 'POSE', 'WORLD') * bone_space

mesh_ob.matrix_world = mat


Add a monkey and select a pose bone, then run the above script. Then Suzanne should look in pose bone direction. Note that bone direction is +Y, so it's (0,1,0) for a bone pointing upwards (Z).