This is an extension question of the following question I asked earlier here. In this case, I have a cube and a camera. I want to extract whatever cube's portion falls inside the camera view. The python script provided below can give the expected output as shown in the image below.
However, the main issue is - there are some cut-out portions into the output object. It is happening as the whole cube does not fall inside the camera view and the excluded portion is clipped from the cube, thus, leaving open sides to the newly created object. Is there any way of closing the cut-out portion with a face without manually selecting vertices and pressing F? Can it be done editing any portion of the following scripts I am using?
import bpy
import bmesh
def camera_as_planes(scene, obj):
"""
Return planes in world-space which represent the camera view bounds.
"""
from mathutils.geometry import normal
camera = obj.data
# normalize to ignore camera scale
matrix = obj.matrix_world.normalized()
frame = [matrix @ v for v in camera.view_frame(scene=scene)]
origin = matrix.to_translation()
planes = []
from mathutils import Vector
is_persp = (camera.type != 'ORTHO')
for i in range(4):
# find the 3rd point to define the planes direction
if is_persp:
frame_other = origin
else:
frame_other = frame[i] + matrix.col[2].xyz
n = normal(frame_other, frame[i - 1], frame[i])
d = -n.dot(frame_other)
planes.append((n, frame_other, d))
if not is_persp:
# add a 5th plane to ignore objects behind the view
n = normal(frame[0], frame[1], frame[2])
d = -n.dot(origin)
planes.append((n, frame[0], d))
return planes
context = bpy.context
scene = context.scene
dg = context.evaluated_depsgraph_get()
ob = context.object
camera = scene.camera
cloc = camera.matrix_world.translation
bm = bmesh.new()
bm.from_object(ob, dg)
bm.transform(ob.matrix_world)
for n, cf, _ in camera_as_planes(scene, scene.camera):
bmesh.ops.bisect_plane(
bm,
geom=bm.verts[:] + bm.edges[:] + bm.faces[:],
plane_no=-n,
plane_co=cf,
clear_outer=True,
)
# create a new object
ob = bpy.data.objects.new("Test", bpy.data.meshes.new("Test"))
bm.to_mesh(ob.data)
context.collection.objects.link(ob)