@@ -127,6 +127,45 @@ def init_simple_mesh(device: str = "cpu"):
127
127
return Meshes (verts = verts , faces = faces )
128
128
129
129
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
+
130
169
class TestMeshes (TestCaseMixin , unittest .TestCase ):
131
170
def setUp (self ) -> None :
132
171
np .random .seed (42 )
@@ -1172,6 +1211,18 @@ def test_compute_faces_areas_cpu_cuda(self):
1172
1211
face_normals_cpu [nonzero ], face_normals_cuda .cpu ()[nonzero ], atol = 1e-6
1173
1212
)
1174
1213
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
+
1175
1226
@staticmethod
1176
1227
def compute_packed_with_init (
1177
1228
num_meshes : int = 10 , max_v : int = 100 , max_f : int = 300 , device : str = "cpu"
0 commit comments