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.

  • $\begingroup$ Your rest and par_rest are identical, that doesn't seem correct. $\endgroup$
    – CodeManX
    Oct 16, 2013 at 23:00
  • $\begingroup$ 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. $\endgroup$
    – ideasman42
    Oct 17, 2013 at 2:07
  • $\begingroup$ It expects final pose matrix -- the matrices to be sent to the video card $\endgroup$
    – luminos
    Oct 17, 2013 at 2:54
  • $\begingroup$ @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. $\endgroup$
    – Adhi
    Oct 17, 2013 at 3:30
  • $\begingroup$ @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. $\endgroup$
    – luminos
    Oct 18, 2013 at 2:21

1 Answer 1


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).


You must log in to answer this question.

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