1
$\begingroup$

I'm trying to build upon this answer to rotate an object around an arbitrary point.

I get that if I do:

rot_mat = Matrix.Rotation(-pi / 4, 4, 'Z')
orig_loc, orig_rot, orig_scale = obj.matrix_world.decompose()

orig_loc_mat = Matrix.Translation(orig_loc)
orig_rot_mat = orig_rot.to_matrix().to_4x4()
orig_scale_mat = Matrix.Scale(orig_scale[0],4,(1,0,0)) * Matrix.Scale(orig_scale[1],4,(0,1,0)) * Matrix.Scale(orig_scale[2],4,(0,0,1))

obj.matrix_world = rot_mat @ orig_rot_mat @ orig_scale_mat 

instead of

obj.matrix_world = orig_loc_mat @ rot_mat @ orig_rot_mat @ orig_scale_mat 

I will have my object rotated correctly and centered on 0.0.

So I guess I need to perform some transform on orig_loc_mat so that the location is also moved.

What's the transform I need to do?

$\endgroup$
2
  • $\begingroup$ @batFINGER - sorry about that - I'm in the process of leaning both Python and Blender, so often I have trouble with the naming of things, and as a consequence with hitting good google results. The duplicate you point to didn't pop up in two days of googling for "rotate around point blender python" and following every possible link. Should I delete question and answer? BTW - thanks for the amazing answers $\endgroup$
    – simone
    Commented Aug 11, 2021 at 8:09
  • $\begingroup$ NP, will close as dupe. Have same issue with numpy. $\endgroup$
    – batFINGER
    Commented Aug 11, 2021 at 8:13

1 Answer 1

2
$\begingroup$

If you rotate around the center (i.e.: location) of the object, the process is:

  1. translate the object to location (0, 0, 0)
  2. rotate the object
  3. translate it back to the original location

which is what this does:

 obj.matrix_world = orig_loc_mat @ rot_mat @ orig_rot_mat @ orig_scale_mat 

In order to rotate around an arbitrary point the process is:

  1. translate the object to location (0, 0, 0)
  2. rotate the object
  3. rotate the location
  4. translate it back to the new location

where rotating the location is the same as rotating any object, so what you do is:

# get the rotation matrix (deg is negated - bpy goes clockwise, mathutils counter-clockwise
rot_matrix = mathutils.Matrix.Rotation(math.radians(-deg), 4, axis.upper())

# decompose the world matrix
orig_loc, orig_rot, orig_scale = obj.matrix_world.decompose()
orig_rot_matrix =   orig_rot.to_matrix().to_4x4()
orig_scale_matrix = mathutils.Matrix.Scale(orig_scale[0],4,(1,0,0)) @ mathutils.Matrix.Scale(orig_scale[1],4,(0,1,0)) @ mathutils.Matrix.Scale(orig_scale[2],4,(0,0,1))

# this does the job
#                       1. translate to center
#         2. rotate     |
#         |             |                  3. translate back
#         |             |                  |
new_loc = rot_matrix @ (orig_loc - center) + center)

# make a matrix out of the new location 
new_loc_matrix = mathutils.Matrix.Translation(new_loc)

# all together now
obj.matrix_world = new_loc_matrix @ rot_matrix @ orig_rot_matrix @ orig_scale_matrix 

I pieced this together from answers on rotating without bpy.opy and on rotation around a cursor, so I was clearly standing on the shoulders of giants. Summing things up here in hope it's useful for someone else.

$\endgroup$

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