Q:

Script for getting Camera Look At co-ordinates

(I'm new to Blender)
Using a script, how can I get the an X, Y, Z set of co-ordinates showing me where the current camera is looking at?
My use case is that the user just moves the camera visually but I need a look at point. I have a manual way of creating an object and then getting the camera to track the object, but I don't really want to introduce this manual step in the workflow.
Thanks

A:

If you want the first surface point of where the camera is pointing at, you can use a variation of this script.
It casts a ray from the camera and checks for collision using the ray_cast function of the BVHTree module. I have documented the script with lots of comments. Paste in Blender Text Editor and press Run Script.

Demo of the raycasting.
import bpy
import bmesh
from mathutils.bvhtree import BVHTree
import mathutils

# the epsilon value for the BVHTree calculations
EPSILON = 0.00001

# maximum ray distance from camera
MAXIMUM_DISTANCE = 100

# make sure you have a Camera and an Empty named like this
camera = bpy.data.objects["Camera"]
empty = bpy.data.objects["Empty"]

# create the BVHTrees from bmeshes
# the bmesh conversion makes it easy to apply the individual objects transformation matrices
trees = []
for ob in bpy.data.objects:
    if ob.type == 'MESH':
        bm = bmesh.new()
        bm.from_object(ob, bpy.context.scene)
        bmesh.ops.transform(bm, matrix=ob.matrix_world, verts=bm.verts)
        trees.append(BVHTree.FromBMesh(bm, epsilon=EPSILON))

# the main method for calculating the distance
def measure_distance(scene = bpy.context.scene):

    # create a direction vector (dir) by applying the
    # camera's transformation matrix to (0, 0, -1)
    mat = camera.rotation_euler.to_matrix().to_4x4()
    if camera.rotation_mode == 'QUATERNION':
        mat = camera.rotation_quaternion.to_matrix().to_4x4()
    dir = mat * mathutils.Vector((0, 0, -1))

    # use the min_dist variable to keep track of the nearest collision location
    min_dist = MAXIMUM_DISTANCE

    # if no rays collide < MAX_DISTANCE, we'll display the Empty
    # at the camera's location
    vloc = camera.location

    # loop through each bvhtree and check if the is a collision
    # casting a ray; if the distance of the collision is smaller
    # than min_dist, we'll use this newfound location
    for bvh in trees:
        loc, no, i, d = bvh.ray_cast(camera.location, dir)
        if d is not None:
            if d < min_dist:
                min_dist = d
                vloc = loc

    # assign the location to the empty to visualize the ray collision
    empty.location = vloc

# remove all handlers, then create a new one with the measure_distance function
for h in bpy.app.handlers.scene_update_pre:
    bpy.app.handlers.scene_update_pre.remove(h)
bpy.app.handlers.scene_update_pre.append(measure_distance)

You can now use the found coordinates in the vector vloc to do whatever you want.

