2

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?

Amir
  • 3,074
  • 2
  • 29
  • 55
  • That should be really easy if you know the distance – Rick Riggs Feb 08 '18 at 21:55
  • 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. – Rick Riggs Feb 08 '18 at 21:56

2 Answers2

4

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'])

J. Bakker
  • 3,051
  • 12
  • 30
  • 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!!! – user2734434 Feb 07 '21 at 15:12
1

Shift + A >> E >> P enter image description here

Set X Location to 1.00000 enter image description here

Add another Empty (it will automatically be named 'Empty.001')

Shift + A >> E >> P enter image description here

Now add a Camera

Shift + A >> E >> P enter image description here

Position the Camera as follows:

[1.00000, 0.00000, 0.00000]

Rotate the Angles as follows:

90°, 0°, 90° enter image description here

With the Camera still selected...

Shift + Select the First Empty >> Ctrl + P >> K (Object (Keep Transform)) enter image description here

Next select only the first Empty and add a Track To Modifier enter image description here

Then set the Target to: Empty.001

Then set To to: -X enter image description here


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. enter image description here

Here's an example of the result

enter image description here

n1cK
  • 230
  • 3
  • 9
Rick Riggs
  • 4,623
  • 14
  • 30