# Pointing the camera in a particular direction programmatically

I'm trying to use Python to place a camera. I know the camera's location, and the forward and up vectors for the camera (i.e. the direction it's pointing and its orientation). How do I do this?

I know that it's possible to calculate a raw world matrix from the above information, which I can then apply to the camera, but I was rather hoping not to have to. Is there an easier way?

• do you want to set the cameras direction in the game engine? Dec 1, 2013 at 17:35
• No, I'm writing a script to create a scene with the camera in a specific location. Dec 1, 2013 at 17:37

Heres a script to make a camera point towards any point in space.

import bpy

def look_at(obj_camera, point):
loc_camera = obj_camera.matrix_world.to_translation()

direction = point - loc_camera
# point the cameras '-Z' and use its 'Y' as up
rot_quat = direction.to_track_quat('-Z', 'Y')

# assume we're using euler rotation
obj_camera.rotation_euler = rot_quat.to_euler()

# Test
obj_camera = bpy.data.objects["Camera"]
obj_other = bpy.data.objects["Cube"]

obj_camera.location = (5.0, 2.0, 3.0)
look_at(obj_camera, obj_other.matrix_world.to_translation())

• I'm afraid I don't understand this --- the docs for to_track_quat() are... brief. I don't see how the fixed axis parameters get rotated to point in my desired direction. (When I say I have the location and forward and up vectors, I mean literally I have a Point and two Vector objects.) Can you expand? Dec 2, 2013 at 18:22
• The camera starts off pointing along the -Z axis with the top of the camera pointing along the +Y axis. The variable "direction" is the vector from the camera to the point. The function direction.to_track_quat('-Z', 'Y') returns the quaternion that rotates '-Z' so that it aligns with the direction vector. This rotation is not unique because the rotated camera can still rotate about direction vector. Specifying Y gives the rotation quaternion with the -Z vector aligned with the direction vector and the Y vector pointing up. Nov 23, 2016 at 23:59
• You might want to call bpy.context.scene.update() after changing the camera's location to make sure the matrix is up to date. Mar 26, 2019 at 10:15
• +1 for @Daerst 's suggestion to update the scene, this fixed things for me. However, in Blender 2.8+ you'll need bpy.context.view_layer.update() instead. Apr 26, 2022 at 21:31

Here is a version of ideasman42's look_at function that also allows you to roll the camera (or any object) about the axis from camera to target:

def point_at(obj, target, roll=0):
"""
Rotate obj to look at target

:arg obj: the object to be rotated. Usually the camera
:arg target: the location (3-tuple or Vector) to be looked at
:arg roll: The angle of rotation about the axis from obj to target in radians.

Based on: https://blender.stackexchange.com/a/5220/12947 (ideasman42)
"""
if not isinstance(target, mathutils.Vector):
target = mathutils.Vector(target)
loc = obj.location
# direction points from the object to the target
direction = target - loc
tracker, rotator = (('-Z', 'Y'),'Z') if obj.type=='CAMERA' else (('X', 'Z'),'Y') #because new cameras points down(-Z), usually meshes point (-Y)
quat = direction.to_track_quat(*tracker)

quat = quat.to_matrix().to_4x4()
rollMatrix = mathutils.Matrix.Rotation(roll, 4, rotator)

# remember the current location, since assigning to obj.matrix_world changes it
loc = loc.to_tuple()
#obj.matrix_world = quat * rollMatrix
# in blender 2.8 and above @ is used to multiply matrices
# using * still works but results in unexpected behaviour!
obj.matrix_world = quat @ rollMatrix
obj.location = loc


It can be used like this:

import math
cube = bpy.data.objects["Cube"]
cube.location = (5, -5, 5)
cam = bpy.data.objects["Camera"]
cam.location = (5, -5, -2)

One way is to assign tuples directly to the camera object's location and rotation_euler attributes. For example, with the camera selected:
import bpy