Skip to content

Commit 7f097b0

Browse files
Krzysztof Chalupkafacebook-github-bot
Krzysztof Chalupka
authored andcommitted
Submesh 1/n: Implement mesh equality
Summary: Adding a mesh equality operator. Two Meshes objects m1, m2 are equal iff their vertex lists, face lists, and normals lists are equal. Textures meshes are not supported yet, but will be added for vertex textures down the stack. Reviewed By: bottler, nikhilaravi Differential Revision: D35440655 fbshipit-source-id: 69974a59c091416afdb2892896859a189f5ebf3a
1 parent aab9557 commit 7f097b0

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

tests/test_meshes.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,45 @@ def init_simple_mesh(device: str = "cpu"):
127127
return Meshes(verts=verts, faces=faces)
128128

129129

130+
def mesh_structures_equal(mesh1, mesh2) -> bool:
131+
"""
132+
Two meshes are equal if they have identical verts_list and faces_list.
133+
134+
Use to_sorted() before passing into this function to obtain meshes invariant to
135+
vertex permutations. Note that this operator treats two geometrically identical
136+
meshes as different if their vertices are in different coordinate frames.
137+
"""
138+
if mesh1.__class__ != mesh1.__class__:
139+
return False
140+
141+
if mesh1.textures is not None or mesh2.textures is not None:
142+
raise NotImplementedError(
143+
"mesh equality is not implemented for textured meshes."
144+
)
145+
146+
if len(mesh1.verts_list()) != len(mesh2.verts_list()) or not all(
147+
torch.equal(verts_mesh1, verts_mesh2)
148+
for (verts_mesh1, verts_mesh2) in zip(mesh1.verts_list(), mesh2.verts_list())
149+
):
150+
return False
151+
152+
if len(mesh1.faces_list()) != len(mesh2.faces_list()) or not all(
153+
torch.equal(faces_mesh1, faces_mesh2)
154+
for (faces_mesh1, faces_mesh2) in zip(mesh1.faces_list(), mesh2.faces_list())
155+
):
156+
return False
157+
158+
if len(mesh1.verts_normals_list()) != len(mesh2.verts_normals_list()) or not all(
159+
torch.equal(normals_mesh1, normals_mesh2)
160+
for (normals_mesh1, normals_mesh2) in zip(
161+
mesh1.verts_normals_list(), mesh2.verts_normals_list()
162+
)
163+
):
164+
return False
165+
166+
return True
167+
168+
130169
class TestMeshes(TestCaseMixin, unittest.TestCase):
131170
def setUp(self) -> None:
132171
np.random.seed(42)
@@ -1172,6 +1211,18 @@ def test_compute_faces_areas_cpu_cuda(self):
11721211
face_normals_cpu[nonzero], face_normals_cuda.cpu()[nonzero], atol=1e-6
11731212
)
11741213

1214+
def test_equality(self):
1215+
meshes1 = init_mesh(num_meshes=2)
1216+
meshes2 = init_mesh(num_meshes=2)
1217+
meshes3 = init_mesh(num_meshes=3)
1218+
empty_mesh = Meshes([], [])
1219+
self.assertTrue(mesh_structures_equal(empty_mesh, Meshes([], [])))
1220+
self.assertTrue(mesh_structures_equal(meshes1, meshes1))
1221+
self.assertTrue(mesh_structures_equal(meshes1, meshes1.clone()))
1222+
self.assertFalse(mesh_structures_equal(empty_mesh, meshes1))
1223+
self.assertFalse(mesh_structures_equal(meshes1, meshes2))
1224+
self.assertFalse(mesh_structures_equal(meshes1, meshes3))
1225+
11751226
@staticmethod
11761227
def compute_packed_with_init(
11771228
num_meshes: int = 10, max_v: int = 100, max_f: int = 300, device: str = "cpu"

0 commit comments

Comments
 (0)