0
$\begingroup$

(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

$\endgroup$
3
  • $\begingroup$ A camera looks in a direction (axis), not a point in particolar, imho... whatever the 'lens' aperture sees in y axis, eg. A 'trackto' constraint ensures that axis is always targeted at a specific object. $\endgroup$
    – m.ardito
    Commented Jun 6, 2018 at 7:08
  • $\begingroup$ Do you want the focal point to be generated? A ray from the camera to the first touching surface? $\endgroup$
    – Bert VdB
    Commented Jun 6, 2018 at 8:28
  • $\begingroup$ @BertVdB A co-ordinate point from anywhere along the ray from the camera. I will try an answer below as it looks like that could work for me. $\endgroup$
    – jimbo
    Commented Jun 7, 2018 at 1:42

1 Answer 1

5
$\begingroup$

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.

ray_cast collision
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.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .