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:
- This is not the rest matrix.
- 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?