I want to position the camera around an object using Blender's Python API. Assuming that an object is centered at (0, 0, 0), I want to move the camera around it given a set of known (x, y, z) coordinate values while keeping its focus on the point (0, 0, 0) and its distance to middle of the object to be dist, a constant. I wonder how I can do that in Python?
- $\begingroup$ That should be really easy if you know the distance $\endgroup$Rick Riggs– Rick Riggs2018-02-08 21:55:20 +00:00Commented Feb 8, 2018 at 21:55
- $\begingroup$ As a matter of fact that should be easy even if you don't, we can calculate distance from to known points (Camera & Origin). Give me a few, I'll post an answer to this. $\endgroup$Rick Riggs– Rick Riggs2018-02-08 21:56:53 +00:00Commented Feb 8, 2018 at 21:56
2 Answers
The next function will rotate the camera towards the focus point. And then place the camera at a certain distance. The location of camera will only change along the direct line with the focus point.
import bpy import mathutils def update_camera(camera, focus_point=mathutils.Vector((0.0, 0.0, 0.0)), distance=10.0): """ Focus the camera to a focus point and place the camera at a specific distance from that focus point. The camera stays in a direct line with the focus point. :param camera: the camera object :type camera: bpy.types.object :param focus_point: the point to focus on (default=``mathutils.Vector((0.0, 0.0, 0.0))``) :type focus_point: mathutils.Vector :param distance: the distance to keep to the focus point (default=``10.0``) :type distance: float """ looking_direction = camera.location - focus_point rot_quat = looking_direction.to_track_quat('Z', 'Y') camera.rotation_euler = rot_quat.to_euler() # Use * instead of @ for Blender <2.8 camera.location = rot_quat @ mathutils.Vector((0.0, 0.0, distance)) update_camera(bpy.data.objects['Camera']) - $\begingroup$ I just wanted to point out that this answer is also useful for (re-)orienting lights as well!!! It's just a matter of passing a light object in the camera variable. Thanks to J Bakker!!! $\endgroup$user2734434– user27344342021-02-07 15:12:55 +00:00Commented Feb 7, 2021 at 15:12
Add another Empty (it will automatically be named 'Empty.001')
Now add a Camera
Position the Camera as follows:
[1.00000, 0.00000, 0.00000]
Rotate the Angles as follows:
With the Camera still selected...
Shift + Select the First Empty >> Ctrl + P >> K (Object (Keep Transform)) 
Next select only the first Empty and add a Track To Modifier 
Then set the Target to: Empty.001
Here's the Python Code to do basically all of the same steps as above
import bpy import math bpy.ops.object.empty_add(type='PLAIN_AXES', view_align=False, location=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) bpy.ops.object.empty_add(type='PLAIN_AXES', view_align=False, location=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) newEmpties = [] for objName in bpy.data.objects.keys(): if(len(objName.split("mpty")) > 1): newEmpties.append(objName) # print("-----") print(len(newEmpties)) print("-----") for i in newEmpties: print(i) cnt = len(newEmpties) myEmpties = [] myEmpties.append(newEmpties[cnt - 2]) myEmpties.append(newEmpties[cnt - 1]) e1 = bpy.data.objects[myEmpties[0]] e2 = bpy.data.objects[myEmpties[1]] e1.location.x = 1.0 bpy.ops.object.camera_add(view_align=True, enter_editmode=False, location=(0, 0, 0), rotation=(0.961699, 0.0122912, -0.897371), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) newCams = [] for objName in bpy.data.objects.keys(): if(len(objName.split("amera")) > 1): newCams.append(objName) # myCam = bpy.data.objects[newCams[len(newCams) - 1]] myCam.location.x = 1.0 myCam.rotation_euler.x = math.pi * 0.5 myCam.rotation_euler.z = math.pi * 0.5 bpy.ops.object.select_all(action='DESELECT') myCam.select = True e1.select = True bpy.context.scene.objects.active = e1 bpy.ops.object.parent_set(type='OBJECT', keep_transform=True) bpy.ops.object.constraint_add(type='TRACK_TO') e1.constraints['Track To'].target = e2 e1.constraints['Track To'].track_axis = 'TRACK_NEGATIVE_X' bpy.context.scene.objects.active = myCam scene = bpy.data.scenes['Scene'] scene.camera = myCam For Blender >2.8 (new python api)
import bpy import math def pointACamTo(toPoint, fromPoint): bpy.ops.object.empty_add(type='PLAIN_AXES', location=fromPoint) bpy.ops.object.empty_add(type='PLAIN_AXES', location=toPoint) newEmpties = [] for objName in bpy.data.objects.keys(): if(len(objName.split("mpty")) > 1): newEmpties.append(objName) # print("-----") print(len(newEmpties)) print("-----") for i in newEmpties: print(i) cnt = len(newEmpties) myEmpties = [] myEmpties.append(newEmpties[cnt - 2]) myEmpties.append(newEmpties[cnt - 1]) e1 = bpy.data.objects[myEmpties[0]] e2 = bpy.data.objects[myEmpties[1]] e1.location.x = fromPoint[0] e1.location.y = fromPoint[1] e1.location.z = fromPoint[2] bpy.ops.object.camera_add(align='VIEW', enter_editmode=False, location=(0, 0, 0), rotation=(0.961699, 0.0122912, -0.897371)) newCams = [] for objName in bpy.data.objects.keys(): if(len(objName.split("amera")) > 1): newCams.append(objName) # myCam = bpy.data.objects[newCams[len(newCams) - 1]] #myCam.location.x = fromPoint[0] myCam.location.x = fromPoint[0] myCam.location.y = fromPoint[1] myCam.location.z = fromPoint[2] myCam.rotation_euler.x = math.pi * 0.5 myCam.rotation_euler.z = math.pi * 0.5 bpy.ops.object.select_all(action='DESELECT') myCam.select = True e1.select = True #bpy.context.scene.objects.active = e1 # wrong, read-only bpy.context.active_object = e1 # select: eventually remove # wrong, for multiple selection eventually: e1.select_set(True) bpy.context.view_layer.objects.active = e1 bpy.ops.object.parent_set(type='OBJECT', keep_transform=True) bpy.ops.object.constraint_add(type='TRACK_TO') e1.constraints['Track To'].target = e2 e1.constraints['Track To'].track_axis = 'TRACK_NEGATIVE_X' # as safety measure: ##deselectAllObjectsInScene() # eventually remove #bpy.context.scene.objects.active = myCam bpy.context.view_layer.objects.active = myCam scene = bpy.data.scenes['Scene'] scene.camera = myCam #and run pointACamTo([0,0,0], [2,2,2]) Now in a separate python script you can use a function like follows to position the camera to a point. 
Here's an example of the result







