From 9b5a3ffa6cba5b30182eeab89ca195a772b4614c Mon Sep 17 00:00:00 2001 From: Jeremy Reizenstein Date: Wed, 16 Mar 2022 05:42:34 -0700 Subject: [PATCH] PLY with uint face data (#1104) Summary: Fix assumption that face indices are signed in the PLY file, as reported in #1104. Reviewed By: nikhilaravi Differential Revision: D34892598 fbshipit-source-id: a8b23bfac1357bdc11bbbf752098319142239804 --- pytorch3d/io/ply_io.py | 2 +- tests/test_io_ply.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pytorch3d/io/ply_io.py b/pytorch3d/io/ply_io.py index 37c86517..da803d00 100644 --- a/pytorch3d/io/ply_io.py +++ b/pytorch3d/io/ply_io.py @@ -1040,7 +1040,7 @@ def _load_ply(f, *, path_manager: PathManager) -> _PlyData: if face.shape[1] < 3: raise ValueError("Faces must have at least 3 vertices.") face_arrays = [face[:, [0, i + 1, i + 2]] for i in range(face.shape[1] - 2)] - faces = torch.LongTensor(np.vstack(face_arrays)) + faces = torch.LongTensor(np.vstack(face_arrays).astype(np.int64)) else: face_list = [] for face_item in face: diff --git a/tests/test_io_ply.py b/tests/test_io_ply.py index d7583f2b..8297765e 100644 --- a/tests/test_io_ply.py +++ b/tests/test_io_ply.py @@ -510,6 +510,45 @@ class TestMeshPlyIO(TestCaseMixin, unittest.TestCase): torch.FloatTensor([3, 4, 5]) + 7 * torch.arange(8)[:, None], ) + def test_load_open3d_mesh(self): + # Header based on issue #1104 + header = "\n".join( + [ + "ply", + "format binary_little_endian 1.0", + "comment Created by Open3D", + "element vertex 3", + "property double x", + "property double y", + "property double z", + "property double nx", + "property double ny", + "property double nz", + "property uchar red", + "property uchar green", + "property uchar blue", + "element face 1", + "property list uchar uint vertex_indices", + "end_header", + "", + ] + ).encode("ascii") + vert_data = struct.pack("<" + "ddddddBBB" * 3, *range(9 * 3)) + face_data = struct.pack("<" + "BIII", 3, 0, 1, 2) + io = IO() + with NamedTemporaryFile(mode="wb", suffix=".ply") as f: + f.write(header) + f.write(vert_data) + f.write(face_data) + f.flush() + mesh = io.load_mesh(f.name) + + self.assertClose(mesh.faces_padded(), torch.arange(3)[None, None]) + self.assertClose( + mesh.verts_padded(), + (torch.arange(3) + 9.0 * torch.arange(3)[:, None])[None], + ) + def test_save_pointcloud(self): header = "\n".join( [