I have my custom axis XYZ vectors (Yellow color in the screenshot below). They are normalized. I need to rotate an object according to these vectors. Is it possible to do this with the python API?

custom axis

  • 1
    $\begingroup$ If these are direction vectors, you can find the rotation_difference between them via the Vector function of the same name: blender.org/api/blender_python_api_current/… $\endgroup$ – TLousky Dec 20 '16 at 10:56
  • $\begingroup$ I tried it but had no luck. If you could make an example? $\endgroup$ – mifth Dec 20 '16 at 12:42

If you want to change the basis you need to set up a transformation matrix. For standard Cartesian coordinates the x (1, 0, 0) , y (0, 1, 0) and z (0, 0, 1) axis vectors make up the columns of the 3 x 3 Indentity matrix.

To make up your basis matrix use the three orthogonal vectors that make up your axis vectors to build a transform matrix.

m = [vx, vy, vz]

which for all extents and purposes is a 3 x 3 rotation matrix.

To rotate your monkey simply multiply its matrix_world by this matrix.

To have translation in your change of coordinates would need a 4 x 4 matrix.

Is all this starting to sound familiar?, it should do as it's pretty much making the cube in image below a child of the empty, and using the empties local space as our new coordinate space.

enter image description here

Using the empty as an example to show the 3 orthogonal vectors that make up its local space.

>>> for v in C.object.matrix_world.to_3x3():
...     print(v)
<Vector (0.8496, -0.4064, -0.3362)>
<Vector (0.1958, 0.8349, -0.5144)>
<Vector (0.4897, 0.3712, 0.7889)>
# orthogonal ?
>>> degrees(Vector((0.8496, -0.4064, -0.3362)).angle(Vector((0.1958, 0.8349, -0.5144))))
90.00059673093595 # close enough

enter image description here

You can use the rotation_difference method of the mathutils.Vector object to calculate the 3 axis angle difference between two vectors.

This function is used as follows:

# Calculate the angle between two vectors. Returns a Quaternion object.
vector1.rotation_difference( vector2 )

Here's some sample code that uses this function:

import bpy
from mathutils import Vector
from math import degrees

v0 = Vector(( 0,0,0 ))
v1 = Vector((-0.792312741279602, 0.6056182980537415, -0.0739390179514885))

rot = v1.rotation_difference( v0 ).to_euler()
print( [ degrees( a ) for a in rot ] )

Output is (angle rotation in each axis):

[ -77.31130736634618, -146.788879528308, -40.89379056097038 ]

Now if you want to rotate an object according to this rotation difference, all you need to do is to assign the value of rot to the object's rotation_euler property:

obj.rotation_euler = rot

Note: the image can be a bit misleading since the cube and corresponding empty's location is not the value of V1 at all. V1 represents the rotation / direction values only, with respect to the zero vector (V0).

  • $\begingroup$ What would happen if you exchange v0 and v1 above? $\endgroup$ – batFINGER Dec 20 '16 at 15:56
  • $\begingroup$ @batFINGER that would give you the inverse transformation form v1 to v0 $\endgroup$ – Ajay Feb 12 at 0:17

Your Answer

