Rotation around the cursor with low-level python (no bpy.ops)

In order to optimize my script, I would need some help to perform a rotation around the cursor
(see Rotate object around cursor with Python)

With low-level python, that means, without bpy.ops.* operations.

I have to admit that I didn't find a good overview on how to make rotation with python without bpy.ops. Do I have to perform matrix operations for a simple rotation around an axis Z located at the cursor position?

• I think you are better of using the bpy.ops. The functions in the module call on compiled C commands. This is a lot faster than doing it with python. Also optimizing a script by not using the built-ins blender provides is rather silly. This is just my opinion though Mar 7, 2014 at 13:18
• The low level python api will call c-functions as well. See this post and this post for reasons to not use operators. Mar 7, 2014 at 15:25

Rotate a vector

import bpy
from math import pi
from mathutils import Vector, Euler, Matrix, Quaternion

v = Vector((1.0, 1.0, 1.0))
#point which will be rotated around the cursor

cursor_loc = bpy.context.scene.cursor_location

rot_mat = Matrix.Rotation(pi / 2.0, 3, 'Z')
v_new = rot_mat * (v - cursor_loc) + cursor_loc


There are further options available (see api docs):

You can construct a matrix, this is most efficient if you want to apply the same transformation on many points.

mat = (Matrix.Translation(cursor_loc) *
Matrix.Rotation(pi / 2.0, 4, 'Z') *
Matrix.Translation(-cursor_loc))
v_new = mat * v


You can use quaternions:

# using (axis, angle) constructor
q = Quaternion((0.0, 0.0, 1.0), pi / 2.0)
v_new = q * (v - cursor_loc) + cursor_loc


or eulers:

eu = Euler((0.0, 0.0, pi / 2.0), 'XYZ')
v_new = v - cursor_loc
v_new.rotate(eu)  # works for quat's and matrix types too
v_new += cursor_loc


Rotate an object

mat = (Matrix.Translation(cursor_loc) *
Matrix.Rotation(pi / 2.0, 4, 'Z') *
Matrix.Translation(-cursor_loc))

obj.matrix_world = mat * obj.matrix_world


Euler and Quaternion both offer a method to convert them to a matrix:

q  = Quaternion()
eu = Euler()

mat =  q.to_matrix().to_4x4()
mat = eu.to_matrix().to_4x4()

• You can also do from math import radians and specify the rotation in degrees like radians(90) (equal to pi/2) Mar 7, 2014 at 18:47
• Thanks pink vertex for the answer. I have difficulties to adapt your proposal for a single point (the vector v) to a whole object obj; could you adapt your script to make it run for an object obj that is a plan or a cube? Thanks. Mar 7, 2014 at 23:26
• Added a section. Mar 8, 2014 at 1:46
• great, it helped me a lot! I used the matrix_basis and not matrix_world but your answer provided me the information I needed to move ahead. Thanks! Mar 8, 2014 at 23:51

Rotate object(s) around cursor with cursor rotation

I did a function. you can run it on selected objects in a loop.

for ob in context.selected.objects
rot_around_curs(context, ob)


I convert cursor rotation to a matrix, then modify obj matrix to get a rotation around the cursor with the cursor rotation value

    def rot_around_curs(self, context, obj):
curs = context.scene.cursor
mat = curs.matrix
loc = curs.location
R = mat.to_quaternion().to_matrix().to_4x4() #cursor rotation
T = Matrix.Translation(loc) #cursor location
M = T @ R @ T.inverted() #we just involve the rotation
obj.matrix_world = M @ obj.matrix_world #update obj matrix


the advantage of converting matrix in quaternion is to not use for instance curs.rotation_euler depending in what rotation mode you are

• Hi, thanks for the post. This site is not a regular forum, answers should be substantial and thoroughly explain the solution and required workflow. One liners and short tips rarely make for a good answer. If you can edit your post and provide some more details about the code. Perhaps add a few images illustrating the workflow and final results. See How do I write a good answer? Nov 3, 2021 at 11:36