# Rotate camera around target object (within limits) using python & math utils, whilst maintaining camera facing toward target

I am writing a script to procedurally generate images of a target object on a terrain. The basic logic I am thinking of is to have the camera directly above the target pointing straight down, apply some XYZ offsets so that the target object is not exactly centred, then rotate the camera around the target (by a random amount from zero to a specified maximum rotation value, keeping the offsets, and keeping the direction of the camera relative to the target)

This has to be all in python scripting, as it will be running headless without the GUI. This function will be called multiple times to generate images, with the target object moving every time, so needs to reset the camera position & orientation, apply the offsets, then rotate.

Here is a dummy version of what I have so far, using the default cube & camera.

    import bpy
from random import uniform
from mathutils import Matrix, Euler
import math

def add_jitter(base_value: int = None, jitter: int = None) -> int:
"""
helper function to add random jitter to camera position
"""
jittered_value = base_value + uniform(-jitter, jitter)
return jittered_value

def place_camera(
cam_obj: object = None,
cam_height: int = None,
xy_jitter: int = None,
height_jitter: int = None,
rotation_bound: int = None,
target: object = None,
) -> None:

# Reset camera orientation (straight down)
cam_obj.rotation_euler = (0, 0, 0)

# Add random jitter to xyz coordinates
height_jittered = add_jitter(target.location.z + cam_height, height_jitter)

# Generate random rotations to apply

# Generate translation & rotation matrices, apply sequentially to camera
T = Matrix.Translation((x_jittered, y_jittered, height_jittered))
R = Euler((theta_x, theta_y, theta_z), "XYZ").to_matrix()
mat = R.to_4x4() @ T
cam_obj.matrix_world = mat

cam_obj = bpy.context.scene.objects["Camera"]
target = bpy.context.scene.objects["Cube"]
camera_height = 10
xy_jitter = 2
height_jitter = 2
max_rotation = 45
place_camera(cam_obj, camera_height, xy_jitter, height_jitter, max_rotation, target)


However, this does not seem to do the translation & rotation around the target object as intended, I get strange camera placements and orientations that dont face the target. I am relatively new to scripting in blender, and very new to matrix transformations, so its very possible I'm applying my rotations & transform matrices incorrectly

• Hello ! Shouldn't cam_obj.rotation_euler = (0, 0, -1) be cam_obj.rotation_euler = (0, 0, 0) ? Are you by any chance using a generative language model like chatGPT to write your script ? Commented May 24, 2023 at 13:02
• No I didnt use chatGPT, why do you ask? The initial rotation is (0, 0, -1) so that the camera points directly downwards to begin with, as explained in the text Commented May 24, 2023 at 13:13
• Ah I see, you're correct that (0, 0, 0) would be neutral orientation. The angle relative to the z axis is more important than the z rotation, so I hadn't picked up on this. Edited to reflect this. Commented May 24, 2023 at 13:20
• Because the syntax of the code looks as an output out of chatGPT, and having this information may be helpful in solving your problem. Have you tested it in the 3D viewport ? A rotation of -1 radians is approximately -57,3° around the Z axis;, so it does point downwards but at a random angle Commented May 24, 2023 at 13:20
• You should convert all your angles to radians using math.radians, trigonometric operations use radians instead of degrees Commented May 24, 2023 at 13:22