10
$\begingroup$

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?

$\endgroup$
  • $\begingroup$ 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 $\endgroup$ – Vader Mar 7 '14 at 13:18
  • 2
    $\begingroup$ The low level python api will call c-functions as well. See this post and this post for reasons to not use operators. $\endgroup$ – pink vertex Mar 7 '14 at 15:25
14
$\begingroup$

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()
$\endgroup$
  • 1
    $\begingroup$ You can also do from math import radians and specify the rotation in degrees like radians(90) (equal to pi/2) $\endgroup$ – CoDEmanX Mar 7 '14 at 18:47
  • $\begingroup$ 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. $\endgroup$ – Salvatore Mar 7 '14 at 23:26
  • $\begingroup$ Added a section. $\endgroup$ – pink vertex Mar 8 '14 at 1:46
  • $\begingroup$ 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! $\endgroup$ – Salvatore Mar 8 '14 at 23:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.