@@ -207,7 +207,14 @@ class Meshes(object):
207
207
"equisized" ,
208
208
]
209
209
210
- def __init__ (self , verts = None , faces = None , textures = None ):
210
+ def __init__ (
211
+ self ,
212
+ verts = None ,
213
+ faces = None ,
214
+ textures = None ,
215
+ * ,
216
+ verts_normals = None ,
217
+ ):
211
218
"""
212
219
Args:
213
220
verts:
@@ -229,6 +236,17 @@ def __init__(self, verts=None, faces=None, textures=None):
229
236
the same number of faces.
230
237
textures: Optional instance of the Textures class with mesh
231
238
texture properties.
239
+ verts_normals:
240
+ Optional. Can be either
241
+
242
+ - List where each element is a tensor of shape (num_verts, 3)
243
+ containing the normals of each vertex.
244
+ - Padded float tensor with shape (num_meshes, max_num_verts, 3).
245
+ They should be padded with fill value of 0 so they all have
246
+ the same number of vertices.
247
+ Note that modifying the mesh later, e.g. with offset_verts_,
248
+ can cause these normals to be forgotten and normals to be recalculated
249
+ based on the new vertex positions.
232
250
233
251
Refer to comments above for descriptions of List and Padded representations.
234
252
"""
@@ -354,8 +372,8 @@ def __init__(self, verts=None, faces=None, textures=None):
354
372
self .equisized = True
355
373
356
374
elif torch .is_tensor (verts ) and torch .is_tensor (faces ):
357
- if verts .size (2 ) != 3 and faces .size (2 ) != 3 :
358
- raise ValueError ("Verts and Faces tensors have incorrect dimensions." )
375
+ if verts .size (2 ) != 3 or faces .size (2 ) != 3 :
376
+ raise ValueError ("Verts or Faces tensors have incorrect dimensions." )
359
377
self ._verts_padded = verts
360
378
self ._faces_padded = faces .to (torch .int64 )
361
379
self ._N = self ._verts_padded .shape [0 ]
@@ -412,6 +430,36 @@ def __init__(self, verts=None, faces=None, textures=None):
412
430
self .textures ._N = self ._N
413
431
self .textures .valid = self .valid
414
432
433
+ if verts_normals is not None :
434
+ self ._set_verts_normals (verts_normals )
435
+
436
+ def _set_verts_normals (self , verts_normals ) -> None :
437
+ if isinstance (verts_normals , list ):
438
+ if len (verts_normals ) != self ._N :
439
+ raise ValueError ("Invalid verts_normals input" )
440
+
441
+ for item , n_verts in zip (verts_normals , self ._num_verts_per_mesh ):
442
+ if (
443
+ not isinstance (item , torch .Tensor )
444
+ or item .ndim != 2
445
+ or item .shape [1 ] != 3
446
+ or item .shape [0 ] != n_verts
447
+ ):
448
+ raise ValueError ("Invalid verts_normals input" )
449
+ self ._verts_normals_packed = torch .cat (verts_normals , 0 )
450
+ elif torch .is_tensor (verts_normals ):
451
+ if (
452
+ verts_normals .ndim != 3
453
+ or verts_normals .size (2 ) != 3
454
+ or verts_normals .size (0 ) != self ._N
455
+ ):
456
+ raise ValueError ("Vertex normals tensor has incorrect dimensions." )
457
+ self ._verts_normals_packed = struct_utils .padded_to_packed (
458
+ verts_normals , split_size = self ._num_verts_per_mesh .tolist ()
459
+ )
460
+ else :
461
+ raise ValueError ("verts_normals must be a list or tensor" )
462
+
415
463
def __len__ (self ):
416
464
return self ._N
417
465
@@ -1253,6 +1301,7 @@ def split(self, split_sizes: list):
1253
1301
def offset_verts_ (self , vert_offsets_packed ):
1254
1302
"""
1255
1303
Add an offset to the vertices of this Meshes. In place operation.
1304
+ If normals are present they may be recalculated.
1256
1305
1257
1306
Args:
1258
1307
vert_offsets_packed: A Tensor of shape (3,) or the same shape as
@@ -1286,7 +1335,7 @@ def offset_verts_(self, vert_offsets_packed):
1286
1335
self ._verts_padded [i , : verts .shape [0 ], :] = verts
1287
1336
1288
1337
# update face areas and normals and vertex normals
1289
- # only if the original attributes are computed
1338
+ # only if the original attributes are present
1290
1339
if update_normals and any (
1291
1340
v is not None
1292
1341
for v in [self ._faces_areas_packed , self ._faces_normals_packed ]
0 commit comments