The system I'm making reads from pose bones for guidance, but doesn't use blender's built-in rigging system. I can get the head and tail coordinates, but I also need to know if the bone has been rotated around its axis.

EditBone has a property "roll" that sounds like what I need, but PoseBone lacks this property. I need to take into account the possibility that the bone has been rotated in pose mode. Is there a way to derive this value from the properties that PoseBone does provide?


1 Answer 1


Bone Matrices.

A bone is defined along its local Y axis. The roll is a rotation around the y axis.

Let's say for example sake, we add a default single bone armature, and give bone a roll of 45 degrees.

Edit Mode

>>> C.active_bone

>>> C.active_bone.roll = radians(45)
>>> degrees(C.active_bone.roll)

If we look at its matrix

>>> [degrees(a) for a in C.active_bone.matrix.to_euler()]
[90.00000250447816, -0.0, 45.00000125223908]

The 90 about X explains why it is standing up, and the roll we set is about Z.

If the matrix is set to Identity (zero position) the bone would point in the Y direction. A bone vector is (0, bone.length, 0) where default length is 1.

Pose mode.

Ok off to pose mode. The edit bone settings are the zero settings, aka rest pose. We set the pose bones matrix_basis when we alter loc, rot, scale in posebone properties panel. With no pose set each pose bone will have a size 4 identity matrix.

>>> C.active_pose_bone.matrix_basis
Matrix(((1.0, 0.0, 0.0, 0.0),
        (0.0, 1.0, 0.0, 0.0),
        (0.0, 0.0, 1.0, 0.0),
        (0.0, 0.0, 0.0, 1.0)))

and a familiar set of results from the PoseBone.matrix. Note the matrix here is a 4x4 so as well as rotation has translation and scale.

>>> [degrees(a) for a in C.active_pose_bone.matrix.to_euler()]
[90.00000250447816, -0.0, 45.00000125223908]

Ok lets rotate (roll) the pose bone with RYY45 ie rotate bone by 45 degrees about its local Y axis.

>>> [degrees(a) for a in C.active_pose_bone.matrix_basis.to_euler()]
[0.0, 45.00000466733367, 0.0]


>>> [degrees(a) for a in C.active_pose_bone.matrix.to_euler()]
[90.00000250447816, -0.0, 89.999995674289]

Notice how we get 90 now for the rotation Z roll, which takes into account 45 for the edit bone roll, plus 45 for the pose bone roll,

Alternatively Using Bone.AxisRollFromMatrix

Arbitrarily placed bone with 41 degree bone roll

>>> degrees(C.active_bone.roll) # in edit mode

switch to pose mode

>>> pb = C.active_pose_bone
>>> pb

>>> b = pb.bone
>>> b

pose bone locally rolled 30 degrees

>> [degrees(a) for a in pb.matrix_basis.to_euler()]
[-9.504621014570856e-07, 30.00000424992064, 1.5754678639128658e-06]

edit bone roll from pose bone

>>> axis, angle = b.AxisRollFromMatrix(b.matrix, axis=pb.y_axis)
>>> degrees(angle)

Combined roll

>>> axis, angle = b.AxisRollFromMatrix(pb.matrix.to_3x3(), axis=pb.y_axis)
>>> degrees(angle)
  • $\begingroup$ Thanks. I think I follow you up until the end. If roll is rotation around the bone's Y-axis, why is it suddenly Z at the end? More importantly, how do we work backwards to derive the roll from the final result? $\endgroup$ Feb 3, 2020 at 13:21
  • $\begingroup$ What's unclear to me from question is do you want roll that is applied in pose mode. (local rot Y), 2nd last result, roll that is assigned to edit bone, or the combination of both? $\endgroup$
    – batFINGER
    Feb 3, 2020 at 14:04
  • $\begingroup$ The combination of both. Basically my script builds the mesh along the bone, and I need to know which direction to build in. $\endgroup$ Feb 3, 2020 at 14:37
  • $\begingroup$ Excellent, I think I understand the Bone.AxisRollFromMatrix answer. I'll try it out. $\endgroup$ Feb 3, 2020 at 14:51

You must log in to answer this question.

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