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