0
$\begingroup$

I have the following information from an object: Rotation in degrees (absolute world coordinates) and position in absolute world coordinates.

My goal: to set the position and orientation of a pose bone via python.

My problem: How to rotate the bone by the X, Y, Z axis around it's head along the world X, Y, Z axis?

Here is my current approach: I take my bone's rest matrix (armatureObject.pose.bones["Arm1"].matrix), convert this to euler angles in degrees.

Here is my first assumption that may actually be wrong:

  1. This is not the rest matrix.
  2. The X Y Z angles I get out of this: are these angles relative to the world, or relative to something else?

Now in this process I add my rotation (as I want this bone to be rotated by X = 20°, Y = 30° and Z = 40°) and finally I apply these again to the pose bone.

However, this does not yield a correct result.

What I have in values:

  • Pose Bone Rest Matrix 4x4 converted to Euler (XYZ): -56.332200° , 27.38295°, 48.9299°
  • My input Offset Rotation: : 20°, 30°, 40°

By manually using the cursor and rotating the bone via this pivot in 3D View, I was able to get the correct position for the bone and read the values I need to get through calculation: - Should be (Euler XYZ): 3.082°, -29.799°, 38.67°

Simple enough I believe rotating my matrix by 20, 30 and 40 rotation matrices should have solved it, but it doesn't. :(

armatureBones = armatureObject.pose.bones
boneWP = armatureObject.matrix_world * armatureBones["Arm1"].matrix

rX = mathutils.Matrix.Rotation(radians(20), 4, 'X')
rY = mathutils.Matrix.Rotation(radians(30), 4, 'Y')
rZ = mathutils.Matrix.Rotation(radians(40), 4, 'Z')
newRotMat = rZ * rY * rX * boneWP
newRotMatDirs = newRotMat.to_euler()

# readout to compare
print ("is angle:", degrees(newRotMatDirs[0]),degrees(newRotMatDirs[1]),degrees(newRotMatDirs[2]))
print ("should be", 3.082, -29.799, 38.67)

For this I get: 8.900, 1.558, 144.03145

Where am I going wrong?

$\endgroup$

1 Answer 1

0
$\begingroup$

See this answer

def rotate_around_center(mat_rot, center):
    return ( mathutils.Matrix.Translation( center) * 
             mat_rot * 
             mathutils.Matrix.Translation(-center))

eu = mathutils.Euler(map(radians, (20.0, 30.0, 40.0), 'XYZ').to_matrix().to_4x4()
newRotMat = rotate_around_center(eu, boneWP.location) * boneWP
$\endgroup$
1
  • $\begingroup$ This did the trick! There was a missing ) to close the "map" parameter, and boneWP.location didn't work for me, so I used boneWP.decompose()[0] $\endgroup$
    – Mondkalb
    Commented Jan 20, 2017 at 9:44

You must log in to answer this question.

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