15
$\begingroup$

Is there a command for getting world-space matrix of pose bones, same as obj.matrix_world for objects? I found pose_bone.matrix, but it gives weird result for me.

$\endgroup$
14
$\begingroup$

Yes:

As the documentation says, a pose bones matrix is in object space, this means - unless the object has no loc/scale/rot applied, you will have to apply the objects matrix.

matrix_final = obj.matrix_world @ pose_bone.matrix

This test script adds an empty at the pose-bone.

# Assume we are in pose mode with an active bone

import bpy
from bpy import context

pose_bone = context.active_pose_bone

# we can get the object from the pose bone
obj = pose_bone.id_data
matrix_final = obj.matrix_world @ pose_bone.matrix


# now we can view the matrix by applying it to an object
obj_empty = bpy.data.objects.new("Test", None)
context.collection.objects.link(obj_empty)
obj_empty.matrix_world = matrix_final
| improve this answer | |
$\endgroup$
4
$\begingroup$

mathutils now uses the PEP 465 binary operator for multiplying matrices.

matrix_final = obj.matrix_world * pose_bone.matrix

becomes

matrix_final = obj.matrix_world @ pose_bone.matrix

Since 2.8 object are now stored in Collections, so :

context.scene.objects.link(obj_empty)

becomes

bpy.data.collections['Collection'].objects.link(obj_empty)

Here is the complete script updated:

# Assume we are in pose mode with an active bone,
# and a collection named collecion exist

import bpy
from bpy import context

pose_bone = context.active_pose_bone

# we can get the object from the pose bone
obj = pose_bone.id_data
matrix_final = obj.matrix_world @ pose_bone.matrix


# now we can view the matrix by applying it to an object
obj_empty = bpy.data.objects.new("Test", None)
bpy.data.collections['Collection'].objects.link(obj_empty)
obj_empty.matrix_world = matrix_final
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks, this is useful ! But now I would like to ask, I have global_matrix, how to convert it to localtransform (localtion / rotation / scale)? $\endgroup$ – user66174 Mar 13 at 16:00
3
$\begingroup$

Again with tip to tail offset.

Slight addition to @ideasman42's answer to enable globally locating to tip or tail of bone based on an offset. 0 is as above at fat end of bone (head), 1 at skinny end (tail).

This is to emulate somewhat the option in copy transform constraints to locate with offset along bone.

The vector

(pb.head - pb.tail)

describes the object space vector from head to tail A translation matrix is created to translate point of interest locally along the bone.

# Assume we are in pose mode with an active bone

import bpy
from bpy import context
from mathutils import Matrix

# add empty half way along bone
offset = 0.5 # 0 for tail 1 for tip.

pb = context.active_pose_bone

T =  Matrix.Translation(
    offset * (pb.tail - pb.head)
    )

# we can get the object from the pose bone
obj = pb.id_data
matrix_final = obj.matrix_world @ (T @ pb.matrix)


# now we can view the matrix by applying it to an object
obj_empty = bpy.data.objects.new("Test", None)
context.collection.objects.link(obj_empty)
obj_empty.matrix_world = matrix_final
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.