I am trying to move around objects by manipulating their transformation matrices with Python. If the objects are in a parent/child hierarchy you have to step down this hierarchy using the object's matrix_parent_inverse
element. My code works fine with one exception: In case an object is a child of an armature's bone the child has a matrix_parent_inverse
I do not understand.
Say, we have a cube as child of a cone as child of a cylinder, i. e. the hierarchy cube -> cone -> cylinder. bpy.data.objects["Cube"].matrix_parent_inverse
gives me the inverse matrix of the cone at the time of parenting. Fine.
Now we have the same situation (at least in my opinion) when the cube is the child of a bone. The hierarchy is in this case cube -> bone -> armature. bpy.data.objects["Cube"].matrix_parent_inverse
should give the same result as in the first situation but it does not. So my question is: What is the meaning of matrix_parent_inverse
in this case or how can I get the correct one?
Sample code showing the different results (Blender 2.71):
import bpy
#------------------------------------------------------
# Make a parent hierarchy
# cube -> cone -> cylinder
# "->" means "is child of"
#------------------------------------------------------
# Delete the scene:
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
# Create a cylinder at location (2, 3, 4):
bpy.ops.mesh.primitive_cylinder_add(location=(2, 3, 4))
# Create a cone and make it the cylinder's child at the same position:
bpy.ops.mesh.primitive_cone_add(location=(2, 3, 4))
bpy.context.scene.objects.active = bpy.data.objects["Cylinder"]
bpy.ops.object.parent_set(type='OBJECT')
# Create a cube at (0, 0, 0) and make it the cone's child:
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0))
bpy.context.scene.objects.active = bpy.data.objects["Cone"]
bpy.ops.object.parent_set(type='OBJECT')
# Print the cube's parent inverse matrix:
print(bpy.data.objects["Cube"].matrix_parent_inverse)
#------------------------------------------------------
# Make a parent hierarchy
# cube -> bone -> armature
# "->" means "is child of"
#------------------------------------------------------
# Delete the scene:
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
# Create an armature at (2, 3, 4), a bone is created automatically as child:
bpy.ops.object.armature_add(location=(2, 3, 4))
# Create a cube at (0, 0, 0) and make it the bone's child:
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0))
bpy.context.scene.objects.active = bpy.data.objects["Armature"]
bpy.ops.object.mode_set(mode='POSE')
bpy.ops.object.parent_set(type='BONE')
# Print the cube's parent inverse matrix:
print(bpy.data.objects["Cube"].matrix_parent_inverse)
# => output:
#<Matrix 4x4 (1.0000, 0.0000, 0.0000, -2.0000)
# (0.0000, 1.0000, 0.0000, -3.0000)
# (0.0000, 0.0000, 1.0000, -4.0000)
# (0.0000, 0.0000, 0.0000, 1.0000)>
#
#<Matrix 4x4 (1.0000, 0.0000, 0.0000, -2.0000)
# (0.0000, 0.0000, 1.0000, -5.0000)
# (0.0000, -1.0000, 0.0000, 3.0000)
# (0.0000, 0.0000, 0.0000, 1.0000)>
#
# Both matrices should be the same but aren't.
C.object.data.bones[0].matrix
$\endgroup$