How can I analyze whether my camera is looking up/down?

The question is exactly the same as the title: How can I analyze whether my camera is looking up/down? :)

A bit of explanation: I am writing a script that handles both 3rd and 1st person view, and now got stuck at the point where I want setting a cap to prevent the view from turning around vertically.

For this I made an "if... elif... elif..." statement. The first branch tests, whether the sight is between the caps, and if so, then lets the user move the view. So after that, I need to check which direction the user wants to move the view, plus which direction is it stuck to. These do for the 2 other branches.

So this is why I'd need your help.

When the camera's X rotation (in euler rotation) is at 90 degrees it is looking parallel to the ground. Less than 90 it will be pointing down at the ground, greater than 90 is pointing up.

if camera.rotation_euler.x > 90 and camera.rotation_euler.x < 180:
# looking up
elif camera.rotation_euler.x < 90 and camera.rotation_euler.x > 0:
# looking down

• This simply stops my script from working. :( – user1733 Dec 3 '13 at 17:08
• BTW, am using Blender 2.69 – user1733 Dec 3 '13 at 17:09
• If you just copy and pasted then you will also need to add something like camera = bge.logic.getCurrentScene().active_camera so it knows what object camera is meant to be referring to. – sambler Dec 3 '13 at 19:14
• scene = bge.logic.getCurrentScene() ... empty = scene.objects["empty"] ->this is what I want to rotate, so this is not the problem – user1733 Dec 3 '13 at 19:38
• Note, using rotation_euler is incorrect, it wont take constraints or parenting into account. use matrix_world.to_euler() instead if you need the worldspace euler. – ideasman42 Dec 3 '13 at 23:40

This simple script gets the angle from the up axis to the cameras view-axis.

import bpy
from mathutils import Vector

camera = bpy.data.objects["Camera"]
z_up = Vector((0.0, 0.0, 1.0))
z_camera  = z_up * camera.matrix_world.to_3x3()
angle = z_camera.angle(z_up)

is_up = angle < math.degrees(90.0)


Note that matrix_world and not rotation_euler, this is important since rotation_euler is the rotation input from fcurves and drivers, and not the final transformation of the object with constraints and parents.

• erm, where does "z_camera" come from? – user1733 Dec 5 '13 at 1:38
• @user1733 oops - corrected. – ideasman42 Dec 5 '13 at 4:16

Got it! :)

#_CAPPED STATUS:
aroundX = logic.getCurrentController().owner.worldOrientation.to_euler().x      #_getting rotation direction: + on Up & - on Down
capped = False                                                                  #_capped is "False" as default
if (aroundX > 1.3 and y > 0) or (aroundX < -1.1 and y < 0) == True:     #_capped becomes "True" when  it has to
capped = True


y shows the mouse movement's 2nd coordinate

I have another idea, you could calculate the angle between the z-axis which points upward and convert the camera rotation to a transformation matrix to create another vector pointing to the camera. After that you can determine the angle of the camera to the z-axis with the dot product which returns the cosine of the angle. @samblers suggestion doesn't seem to take rotations on the cameres y and z-axis into account.

With this method you could limit (if..else) the angle from 0..70 (max 90)

import bpy
import math
from mathutils import Vector

camera = bpy.data.objects["Camera"]
origin_z = Vector((0,0,1))
cam_rot  = camera.rotation_euler.to_matrix().to_4x4()
z_cam  = origin_z * cam_rot
angle = math.degrees(math.acos( origin_z.dot( z_cam )))
print( angle )


I verified this with the Math Vis addon enabled:

You might find this a great tool when coping with rotations and vectors. Simply enter

origin_z = Vector((0,0,1))
cam_rot  = camera.rotation_euler.to_matrix().to_4x4()


into the console and see how it looks like.

Some examples:

Prints 0.0

Prints 39.00000357556496

Prints 39.00001985547789

Prints 53.46396688981824

• Thanks for the idea, but I just cannot find any way to implement it into my script to get any use of it. :( BTW, does it give back numbers like °s? or radians? or something else? – user1733 Dec 3 '13 at 20:42
• It prints degrees 'angle = math.degrees' if you need radians simply omit 'math.degrees' in the last line. – stacker Dec 3 '13 at 21:59