Skip to content

Commit a0f7931

Browse files
nikhilaravifacebook-github-bot
authored andcommitted
Culling to frustrum bug fix
Summary: When `z_clip_value = None` and faces are outside the view frustum the shape of one of the tensors in `clip.py` is incorrect. `faces_num_clipped_verts` should be (F,) but it was (F,3). Added a new test to ensure this case is handled. Reviewed By: bottler Differential Revision: D29051282 fbshipit-source-id: 5f4172ba4d4a75d928404dde9abf48aef18c68bd
1 parent ef16253 commit a0f7931

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

pytorch3d/renderer/mesh/clip.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ def clip_faces(
372372
# (F) dim tensor containing the number of clipped vertices in each triangle
373373
faces_num_clipped_verts = faces_clipped_verts.sum(1)
374374
else:
375-
faces_num_clipped_verts = torch.zeros([F, 3], device=device)
375+
faces_num_clipped_verts = torch.zeros([F], device=device)
376376

377377
# If no triangles need to be clipped or culled, avoid unnecessary computation
378378
# and return early
Binary file not shown.

tests/test_render_meshes_clipped.py

+32-11
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
import torch
1616
from common_testing import TestCaseMixin, get_tests_dir, load_rgb_image
1717
from pytorch3d.io import save_obj
18-
from pytorch3d.renderer.cameras import FoVPerspectiveCameras, look_at_view_transform
18+
from pytorch3d.renderer.cameras import (
19+
FoVPerspectiveCameras,
20+
look_at_view_transform,
21+
PerspectiveCameras,
22+
)
1923
from pytorch3d.renderer.lighting import PointLights
2024
from pytorch3d.renderer.mesh import (
2125
ClipFrustum,
@@ -27,8 +31,9 @@
2731
from pytorch3d.renderer.mesh.rasterizer import MeshRasterizer, RasterizationSettings
2832
from pytorch3d.renderer.mesh.renderer import MeshRenderer
2933
from pytorch3d.renderer.mesh.shader import SoftPhongShader
34+
from pytorch3d.renderer.mesh.textures import TexturesVertex
3035
from pytorch3d.structures.meshes import Meshes
31-
36+
from pytorch3d.utils import torus
3237

3338
# If DEBUG=True, save out images generated in the tests for debugging.
3439
# All saved images have prefix DEBUG_
@@ -97,9 +102,9 @@ def load_cube_mesh_with_texture(self, device="cpu", with_grad: bool = False):
97102
return mesh, verts
98103
return mesh
99104

100-
def test_cube_mesh_render(self):
105+
def debug_cube_mesh_render(self):
101106
"""
102-
End-End test of rendering a cube mesh with texture
107+
End-End debug run of rendering a cube mesh with texture
103108
from decreasing camera distances. The camera starts
104109
outside the cube and enters the inside of the cube.
105110
"""
@@ -132,22 +137,16 @@ def test_cube_mesh_render(self):
132137
# the camera enters the cube. Check the output looks correct.
133138
images_list = []
134139
dists = np.linspace(0.1, 2.5, 20)[::-1]
140+
135141
for d in dists:
136142
R, T = look_at_view_transform(d, 0, 0)
137143
T[0, 1] -= 0.1 # move down in the y axis
138144
cameras = FoVPerspectiveCameras(device=device, R=R, T=T, fov=90)
139145
images = renderer(mesh, cameras=cameras)
140146
rgb = images[0, ..., :3].cpu().detach()
141-
filename = "DEBUG_cube_dist=%.1f.jpg" % d
142147
im = (rgb.numpy() * 255).astype(np.uint8)
143148
images_list.append(im)
144149

145-
# Check one of the images where the camera is inside the mesh
146-
if d == 0.5:
147-
filename = "test_render_mesh_clipped_cam_dist=0.5.jpg"
148-
image_ref = load_rgb_image(filename, DATA_DIR)
149-
self.assertClose(rgb, image_ref, atol=0.05)
150-
151150
# Save a gif of the output - this should show
152151
# the camera moving inside the cube.
153152
if DEBUG:
@@ -655,3 +654,25 @@ def test_case_4_no_duplicates(self):
655654
double_hit = torch.tensor([0, 0, -1], device=device)
656655
check_double_hit = any(torch.allclose(i, double_hit) for i in unique_vals)
657656
self.assertFalse(check_double_hit)
657+
658+
def test_mesh_outside_frustrum(self):
659+
"""
660+
Test the case where the mesh is completely outside the view
661+
frustrum so all faces are culled and z_clip_value = None.
662+
"""
663+
device = "cuda:0"
664+
mesh = torus(20.0, 85.0, 32, 16, device=device)
665+
tex = TexturesVertex(verts_features=torch.rand_like(mesh.verts_padded()))
666+
mesh.textures = tex
667+
raster_settings = RasterizationSettings(image_size=512, cull_to_frustum=True)
668+
R, T = look_at_view_transform(1.0, 0.0, 0.0)
669+
cameras = PerspectiveCameras(device=device, R=R, T=T)
670+
renderer = MeshRenderer(
671+
rasterizer=MeshRasterizer(cameras=cameras, raster_settings=raster_settings),
672+
shader=SoftPhongShader(cameras=cameras, device=device),
673+
)
674+
images = renderer(mesh)
675+
676+
# Mesh is completely outside the view frustrum
677+
# The image should be white.
678+
self.assertClose(images[0, ..., :3], torch.ones_like(images[0, ..., :3]))

0 commit comments

Comments
 (0)