Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f124dc4

Browse files
committedOct 6, 2022
Add test and switch to padded instead of packed
1 parent edf4afb commit f124dc4

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed
 

‎pytorch3d/structures/meshes.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,27 +1545,35 @@ def sample_textures(self, fragments):
15451545
else:
15461546
raise ValueError("Meshes does not have textures")
15471547

1548-
def centroid(self):
1548+
def volume_centroid(self):
15491549
"""
15501550
Compute the volumetric centroid of this mesh, which is distinct from the center of mass.
15511551
The center of mass (average of all vertices) will be closer to where there are a
15521552
higher density of points in a mesh are, but the centroid, which is based on volume,
15531553
will be closer to a perceived center of the mesh, as opposed to based on the density
1554-
of vertices.
1554+
of vertices. This function assumes that the mesh is watertight, and that the faces are
1555+
all oriented in the same direction.
15551556
15561557
Returns:
15571558
The position of the centroid as a tensor of shape (3).
15581559
"""
1559-
v_idxs = self.faces_packed().split([1, 1, 1], dim=-1)
1560-
verts = self.verts_packed()
1561-
v0, v1, v2 = [verts[idx].squeeze(-2) for idx in v_idxs]
1560+
v_idxs = self.faces_padded().split([1, 1, 1], dim=-1)
1561+
verts = self.verts_padded()
1562+
1563+
v0, v1, v2 = [torch.gather(verts, 1, idx.expand(-1, -1, 3)) for idx in v_idxs]
1564+
15621565
tetra_center = (v0 + v1 + v2) / 4
15631566
signed_tetra_vol = (v0 * torch.cross(v1, v2, dim=-1)).sum(
15641567
dim=-1, keepdim=True
15651568
) / 6
1566-
return (tetra_center * signed_tetra_vol).sum(dim=-2) / signed_tetra_vol.sum(
1567-
dim=-2
1568-
).clamp(min=1e-5)
1569+
denom = signed_tetra_vol.sum(dim=-2)
1570+
# clamp the denominator to prevent instability for degenerate meshes.
1571+
denom = torch.where(
1572+
denom < 0,
1573+
denom.clamp(max=-1e-5),
1574+
denom.clamp(min=1e-5)
1575+
)
1576+
return (tetra_center * signed_tetra_vol).sum(dim=-2) / denom
15691577

15701578
def submeshes(
15711579
self,

‎tests/test_meshes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,14 @@ def test_assigned_normals(self):
12981298
yes_normals.offset_verts_(torch.FloatTensor([1, 2, 3]).expand(12, 3))
12991299
self.assertFalse(torch.allclose(yes_normals.verts_normals_padded(), verts))
13001300

1301+
def test_centroid(self):
1302+
cube = init_cube_meshes()
1303+
self.assertClose(cube.volume_centroid(), torch.tensor([
1304+
[0.5] * 3,
1305+
[1.5] * 3,
1306+
[2.5] * 3,
1307+
[3.5] * 3,
1308+
]))
13011309
def test_submeshes(self):
13021310
empty_mesh = Meshes([], [])
13031311
# Four cubes with offsets [0, 1, 2, 3].

0 commit comments

Comments
 (0)
Please sign in to comment.