1

In the Blender Game Engine my Python script makes an empty follow my cursor in 3D space. I want a LookAt function for a general object rather than a camera. I want the object to look at the point I'm hovering (the empty position). I'm using a cube so one face should always face the empty.

All I have is a direction vector and I chose the X axis for the local look direction. So I need to calculate the Euler angles and convert them to axis-rotation angles (theta*[axis^]). I have in the Blender Game Engine mathutils (provide quaternions, Euler based rotations via axis-angles, and matrices). I have the object look at the empty when I rotate only the Z axis. I used trigonometry, so sign is handled and I don't need matrix or quaternions.

I want to rotate the Y axis for the up-down look (in 3D we need two rotations, the third is just for rotating the view upside-down, rolling the camera) since this rotation axis is the look direction vector.

My script:

import bge
from mathutils import Vector, Matrix
import math

# Basic stuff
cont = bge.logic.getCurrentController()
own = cont.owner
scene = bge.logic.getCurrentScene()

c = scene.objects["Cube"]
e = scene.objects["Empty"]

# axises (we're using localOrientation)
x = Vector((1.0,0.0,0.0))
y = Vector((0.0,1.0,0.0))
z = Vector((0.0,0.0,1.0))

vec = Vector(e.worldPosition - c.worldPosition) # direction vector

# Converting direction vector into euler angles
# Using trigonometry we get: tan(psi) = cos(phi2)/cos(phi1)
# Where phi1 is the angle between x axises (euler angle)
# and phi2 is the euler of the y axises.
# psi is the z rotation angle.

# get cos(euler_angle)
phi1 = vec.dot(x)/vec.length # = cos p1
phi2 = vec.dot(y)/vec.length # = cos p2
phi3 = vec.dot(z)/vec.length # = cos p3

# get the rotation/steer angles
zAngle = math.atan(phi2/phi1)
yAngle = math.atan2(phi3,phi1)
xAngle = math.atan(phi2/phi3)

# use only 2 as the third must adapt (also: view concept - x is the looking direction, rotating it would make rolling)
r = c.localOrientation.to_euler()
r.z = zAngle
r.y = -yAngle
#r.x = xAngle
c.localOrientation = r

Separately each axis works but combined there are jump glitches through the global Y axis. Also, it seems the "local" orientation in Blender is the same as the "worldOrientation" so I'm not sure in what frame of reference I'm working anymore.

1 Answer 1

0

I have a youtube tutorial on how to make the camera look at specific objects. It may help. https://www.youtube.com/watch?v=hwbObDkiJrE

But the concept, when using the gui, is to open the object->relations panel and for the object you want to be doing the LookAt, you make it the child of the object you want it to follow (the parent). You then select 'Vertex' as the relationship. This will then affect the rotation angles of the child object only.

Try this,

bpy.data.objects['child'].parent = bpy.data.objects['parent']
bpy.data.objects['child'].parent_type = 'VERTEX'

and actually there is more info here https://blender.stackexchange.com/questions/26108/how-do-i-parent-objects

Sign up to request clarification or add additional context in comments.

1 Comment

It's not really what I meant.. Either way I was just asking about how to implement LookAt without gimbal lock but also without quaternions. I tried this wierd function and found that it works well but explodes when facing upwords or downwords exactly. Which means something was off and indeed taking atan equivalent trigonometric functions we get gimbal lock.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.