During the multi-view export (the operator that calls cull_objects_outside_all_frustums), objects that are clearly visible in a camera's rendered frame are sometimes still culled (hide_render = True) because the visibility test only samples discrete points, not the object's full extent.
is_object_in_camera_frustum() tests only:
Each of the object's 8 bounding-box corners, and
The object's origin/center point
against the camera frustum planes, returning True only if one of those specific points lies inside the frustum.
This fails for large, thin, close-up geometry — most obviously walls. When a camera is close to (or aimed straight at) a wall, the wall's face fills the entire frame, but its bounding-box corners can all lie outside the frustum's angular bounds (past the left/right/top/bottom edges), and its origin can likewise fall outside the frustum test. The function concludes the object is "not visible from any camera" and sets hide_render = True on it, even though it's plainly visible in the rendered image.
Steps to reproduce
Build a room with wall geometry (large planes) and position/aim a training camera so it's close to and facing one wall head-on, such that the wall fills the camera's field of view.
Run the multi-view export operator (the one that calls cull_objects_outside_all_frustums).
Inspect the exported render / the object's hide_render state afterward.
Expected behavior
Any object that is visibly rendered from at least one training camera should not have hide_render set to True.
Actual behavior
The wall is hidden from render (hide_render = True) even though it's directly in frame for at least one camera, because none of its bounding-box corners or its center point individually satisfy the point-in-frustum test.
Root cause
In is_object_in_camera_frustum():
python
bbox_corners = [obj.matrix_world @ Vector(corner) for corner in obj.bound_box]
for corner in bbox_corners:
if _check_point_in_frustum(corner, cam_loc, cam_forward, cam_right, cam_up,
clip_start, clip_end, cam_data, aspect, fov, half_width, half_height):
return True
obj_center = obj.matrix_world.translation
return _check_point_in_frustum(obj_center, cam_loc, cam_forward, cam_right, cam_up,
clip_start, clip_end, cam_data, aspect, fov, half_width, half_height)
This is a point-sampling test, not a true box/frustum intersection test. It can't detect the case where the camera frustum is entirely contained within the object's silhouette (frustum inside the box, rather than box corners inside the frustum) — which is exactly what happens when a camera is close to a large flat surface like a wall.
Suggested fix
Replace the point-sampling check with a proper AABB/frustum intersection test (e.g. a separating-axis test against the 6 frustum planes), or at minimum add a symmetric check: if none of the object's points are inside the frustum, also test whether the frustum's near-plane corners (projected into world space) fall inside the object's bounding box, to catch the "frustum inside object" case.
During the multi-view export (the operator that calls cull_objects_outside_all_frustums), objects that are clearly visible in a camera's rendered frame are sometimes still culled (hide_render = True) because the visibility test only samples discrete points, not the object's full extent.
is_object_in_camera_frustum() tests only:
Each of the object's 8 bounding-box corners, and
The object's origin/center point
against the camera frustum planes, returning True only if one of those specific points lies inside the frustum.
This fails for large, thin, close-up geometry — most obviously walls. When a camera is close to (or aimed straight at) a wall, the wall's face fills the entire frame, but its bounding-box corners can all lie outside the frustum's angular bounds (past the left/right/top/bottom edges), and its origin can likewise fall outside the frustum test. The function concludes the object is "not visible from any camera" and sets hide_render = True on it, even though it's plainly visible in the rendered image.
Steps to reproduce
Build a room with wall geometry (large planes) and position/aim a training camera so it's close to and facing one wall head-on, such that the wall fills the camera's field of view.
Run the multi-view export operator (the one that calls cull_objects_outside_all_frustums).
Inspect the exported render / the object's hide_render state afterward.
Expected behavior
Any object that is visibly rendered from at least one training camera should not have hide_render set to True.
Actual behavior
The wall is hidden from render (hide_render = True) even though it's directly in frame for at least one camera, because none of its bounding-box corners or its center point individually satisfy the point-in-frustum test.
Root cause
In is_object_in_camera_frustum():
python
bbox_corners = [obj.matrix_world @ Vector(corner) for corner in obj.bound_box]
for corner in bbox_corners:
if _check_point_in_frustum(corner, cam_loc, cam_forward, cam_right, cam_up,
clip_start, clip_end, cam_data, aspect, fov, half_width, half_height):
return True
obj_center = obj.matrix_world.translation
return _check_point_in_frustum(obj_center, cam_loc, cam_forward, cam_right, cam_up,
clip_start, clip_end, cam_data, aspect, fov, half_width, half_height)
This is a point-sampling test, not a true box/frustum intersection test. It can't detect the case where the camera frustum is entirely contained within the object's silhouette (frustum inside the box, rather than box corners inside the frustum) — which is exactly what happens when a camera is close to a large flat surface like a wall.
Suggested fix
Replace the point-sampling check with a proper AABB/frustum intersection test (e.g. a separating-axis test against the 6 frustum planes), or at minimum add a symmetric check: if none of the object's points are inside the frustum, also test whether the frustum's near-plane corners (projected into world space) fall inside the object's bounding box, to catch the "frustum inside object" case.