From the camera view frame.
bpy: How do you find the corners of a camera frustum?
A camera points in the -Z direction. For a perspective camera can find the vectors of the origin to the frustum and if and where they intersect with the XY plane.
Test script. Have kept it simple. Uses the scene camera, finds the frustum, adds a cube on XY plane given image (0, 1) coordinate.
Please note: have used (0, 0) as bottom left and (1, 1) as top right.
import bpy
from math import inf
from mathutils.geometry import intersect_line_plane as ilp
# Global XY plane
plane_co = (0, 0, 0)
plane_no = (0, 0, 1)
context = bpy.context
scene = context.scene
cam = scene.camera
mw = cam.matrix_world
o = mw.translation
camdata = cam.data
tr, br, bl, tl = [
mw @ f for f in camdata.view_frame(scene=scene)]
# offset vectors from bl.
# eg middle would be bl + 0.5 * (x + y)
x = tr - tl
y = tr - br
# roll around in CCW direction
for image_coord in ((0, 0), (0, 1), (1, 0), (1, 1)):
cx, cy = image_coord
# vector pointing from cam origin thru image point (PERSP)
v = (bl + (cx * x + cy * y)) - o
pt = ilp(o, o + v, plane_co, plane_no, True)
if pt and (pt - o).dot(v) > 0:
print("Adding cube at ", pt)
bpy.ops.mesh.primitive_cube_add(
location=pt,
)
elif pt and (pt - o).dot(v) < 0:
print("BEHIND THE CAMERA")
else:
print("NOT POSSIBLE")
A plane to represent this.
Make a plane outlining the possible locations seen by camera. Tweak to make a plane mesh based on the points.
Plane defining allowable locations in default scene
coords = []
for image_coord in ((0, 0), (1, 0), (1, 1), (0, 1)):
cx, cy = image_coord
# vector pointing from cam origin thru image point (PERSP)
v = (bl + (cx * x + cy * y)) - o
pt = ilp(o, o + v, plane_co, plane_no, True)
if pt:
coords.append(pt)
print(coords)
if coords:
name = f"{cam.name}_ViewPlane"
me = bpy.data.meshes.new(name)
faces = [range(len(coords))] if len(coords) > 2 else []
me.from_pydata(coords, [], faces)
ob = bpy.data.objects.new(name, me)
context.collection.objects.link(ob)
Tests
59 random scaled dots per click at random(), random()
150 Foos
Related.
How to find all objects in the Camera's view with Python?
Camera coverage calculation inside a room
projecting onto a mirror and back?
https://blender.stackexchange.com/a/160388/15543