# Recreate to_track_quat with two vectors using python

i've been asked to recreate the to_track_quat function of mathutils to create a quaternion that looks from point a to point b, but so far i've been un successful.

I'm using in blender two objects, being their positions:

object.location = mathutils.Vector((0,0,3))

target.location = mathutils.Vector((2,4,4))

angle = look_at(object, target)

Here is my first function:

def look_at(u, v):
u.normalize()
v.normalize()
dot = u.dot(v)
cross = u.cross(v)
q = mathutils.Quaternion()
q.x = cross.x
q.y = cross.y
q.z = cross.z
q.w = math.sqrt(u.length_squared*v.length_squared) + dot
q.normalize()
print(q)
return q


Returns (w=0.9129, x=-0.3651, y=0.1826, z=0.0000)

The result is something like this:

I believe i'm missing an operation, but i'm not certainly sure what. Can someone guide me a bit on how to do it properly?

Another attempt that has been suggested:

def look_at(u, v):
w = (v - u)/math.sqrt((v.x - u.x)**2 + (v.y - u.y)**2 + (v.z - u.z)**2)
up = mathutils.Vector((0,-1,0))

q = mathutils.Quaternion()
cross1 = w.cross(up)
dot1 = w.dot(up)
q.x = cross1.x
q.y = cross1.y
q.z = cross1.z
q.w = math.sqrt(w.length_squared*up.length_squared) + dot1
q.normalize()
return q

• In maths, a vector is not a point, even though we use the same data structure to store both. Normalising points (u and v) makes no sense. – dr. Sybren Dec 8 '16 at 0:47
• I'm kind of aware since when i did put it in it made no difference, but i comment it in an out just in case to get some hope when i try new stuff. – Seyren Windsor Dec 8 '16 at 2:25
• You have to compute w = (v - u)/|v - u|, and then compute the angle between the forward vector of the object and w to compute the correct rotation. – dr. Sybren Dec 8 '16 at 2:44
• With that do you mean to subtract the two vectors and divide it by the module of the subtraction of the vectors? – Seyren Windsor Dec 8 '16 at 4:00
• That's the mathematical notation of the normalised vector from u to v. – dr. Sybren Dec 8 '16 at 4:01

Based on this tutorial I wrote this function

def look_at(camera_position, target_position):
"""Returns model-view matrix from camera position to target.

# Arguments
camera_position: Numpy-array of length 3. Camera position.
target_position: Numpy-array of length 3. Target position.
"""
camera_direction = camera_position - target_position
camera_direction = camera_direction / np.linalg.norm(camera_direction)
camera_right = np.cross(np.array([0.0, 0.0, 1.0]), camera_direction)
camera_right = camera_right / np.linalg.norm(camera_right)
camera_up = np.cross(camera_direction, camera_right)
camera_up = camera_up / np.linalg.norm(camera_up)
rotation_transform = np.zeros((4, 4))
rotation_transform[0, :3] = camera_right
rotation_transform[1, :3] = camera_up
rotation_transform[2, :3] = camera_direction
rotation_transform[-1, -1] = 1
translation_transform = np.eye(4)
translation_transform[:3, -1] = - camera_position
look_at_transform = np.matmul(rotation_transform, translation_transform)
return look_at_transform