mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2026-10-17 03:35:43 +08:00
Speed up save_obj text formatting, tidy _save helpers
Summary: Format OBJ text through detached numpy views instead of per-element tensor indexing, and simplify the helpers accordingly. ___ Differential Revision: D119966991 fbshipit-source-id: a3c0bc069431eb1feb913069de922914c2e1ab5e
This commit is contained in:
committed by
meta-codesync[bot]
parent
fa22ad16c4
commit
87a6e51e34
@@ -834,24 +834,22 @@ def _save(
|
||||
return
|
||||
|
||||
verts, faces = verts.cpu(), faces.cpu()
|
||||
vert_rows = verts.detach().cpu().numpy()
|
||||
|
||||
lines = ""
|
||||
lines = []
|
||||
|
||||
if decimal_places is None:
|
||||
float_str = "%f"
|
||||
else:
|
||||
float_str = "%" + ".%df" % decimal_places
|
||||
|
||||
if len(verts):
|
||||
V, D = verts.shape
|
||||
for i in range(V):
|
||||
vert = [float_str % verts[i, j] for j in range(D)]
|
||||
lines += "v %s\n" % " ".join(vert)
|
||||
for vert in vert_rows:
|
||||
lines.append("v %s\n" % " ".join(float_str % v for v in vert))
|
||||
|
||||
if save_normals:
|
||||
assert normals is not None
|
||||
assert faces_normals_idx is not None
|
||||
lines += _write_normals(normals, faces_normals_idx, float_str)
|
||||
lines.append(_write_normals(normals, float_str))
|
||||
|
||||
if save_uvs:
|
||||
assert faces_uvs is not None
|
||||
@@ -866,15 +864,13 @@ def _save(
|
||||
raise ValueError(message)
|
||||
|
||||
verts_uvs, faces_uvs = verts_uvs.cpu(), faces_uvs.cpu()
|
||||
uv_rows = verts_uvs.detach().cpu().numpy()
|
||||
|
||||
# Save verts uvs after verts
|
||||
if len(verts_uvs):
|
||||
uV, uD = verts_uvs.shape
|
||||
for i in range(uV):
|
||||
uv = [float_str % verts_uvs[i, j] for j in range(uD)]
|
||||
lines += "vt %s\n" % " ".join(uv)
|
||||
for uv in uv_rows:
|
||||
lines.append("vt %s\n" % " ".join(float_str % u for u in uv))
|
||||
|
||||
f.write(lines)
|
||||
f.write("".join(lines))
|
||||
|
||||
if torch.any(faces >= verts.shape[0]) or torch.any(faces < 0):
|
||||
warnings.warn("Faces have invalid indices")
|
||||
@@ -888,26 +884,16 @@ def _save(
|
||||
)
|
||||
|
||||
|
||||
def _write_normals(
|
||||
normals: torch.Tensor, faces_normals_idx: torch.Tensor, float_str: str
|
||||
) -> str:
|
||||
if faces_normals_idx.dim() != 2 or faces_normals_idx.size(1) != 3:
|
||||
message = (
|
||||
"'faces_normals_idx' should either be empty or of shape (num_faces, 3)."
|
||||
)
|
||||
raise ValueError(message)
|
||||
|
||||
def _write_normals(normals: torch.Tensor, float_str: str) -> str:
|
||||
if normals.dim() != 2 or normals.size(1) != 3:
|
||||
message = "'normals' should either be empty or of shape (num_verts, 3)."
|
||||
raise ValueError(message)
|
||||
|
||||
normals, faces_normals_idx = normals.cpu(), faces_normals_idx.cpu()
|
||||
normal_rows = normals.detach().cpu().numpy()
|
||||
|
||||
lines = []
|
||||
V, D = normals.shape
|
||||
for i in range(V):
|
||||
normal = [float_str % normals[i, j] for j in range(D)]
|
||||
lines.append("vn %s\n" % " ".join(normal))
|
||||
for normal in normal_rows:
|
||||
lines.append("vn %s\n" % " ".join(float_str % n for n in normal))
|
||||
return "".join(lines)
|
||||
|
||||
|
||||
@@ -917,31 +903,37 @@ def _write_faces(
|
||||
faces_uvs: Optional[torch.Tensor],
|
||||
faces_normals_idx: Optional[torch.Tensor],
|
||||
) -> None:
|
||||
face_rows = faces.detach().cpu().numpy()
|
||||
uv_rows = faces_uvs.detach().cpu().numpy() if faces_uvs is not None else None
|
||||
normal_rows = (
|
||||
faces_normals_idx.detach().cpu().numpy()
|
||||
if faces_normals_idx is not None
|
||||
else None
|
||||
)
|
||||
|
||||
F, P = faces.shape
|
||||
for i in range(F):
|
||||
if faces_normals_idx is not None:
|
||||
if faces_uvs is not None:
|
||||
face_row = face_rows[i]
|
||||
if normal_rows is not None:
|
||||
normal_row = normal_rows[i]
|
||||
if uv_rows is not None:
|
||||
uv_row = uv_rows[i]
|
||||
# Format faces as {verts_idx}/{verts_uvs_idx}/{verts_normals_idx}
|
||||
face = [
|
||||
"%d/%d/%d"
|
||||
% (
|
||||
faces[i, j] + 1,
|
||||
faces_uvs[i, j] + 1,
|
||||
faces_normals_idx[i, j] + 1,
|
||||
)
|
||||
"%d/%d/%d" % (face_row[j] + 1, uv_row[j] + 1, normal_row[j] + 1)
|
||||
for j in range(P)
|
||||
]
|
||||
else:
|
||||
# Format faces as {verts_idx}//{verts_normals_idx}
|
||||
face = [
|
||||
"%d//%d" % (faces[i, j] + 1, faces_normals_idx[i, j] + 1)
|
||||
for j in range(P)
|
||||
"%d//%d" % (face_row[j] + 1, normal_row[j] + 1) for j in range(P)
|
||||
]
|
||||
elif faces_uvs is not None:
|
||||
elif uv_rows is not None:
|
||||
uv_row = uv_rows[i]
|
||||
# Format faces as {verts_idx}/{verts_uvs_idx}
|
||||
face = ["%d/%d" % (faces[i, j] + 1, faces_uvs[i, j] + 1) for j in range(P)]
|
||||
face = ["%d/%d" % (face_row[j] + 1, uv_row[j] + 1) for j in range(P)]
|
||||
else:
|
||||
face = ["%d" % (faces[i, j] + 1) for j in range(P)]
|
||||
face = ["%d" % (face_row[j] + 1) for j in range(P)]
|
||||
|
||||
if i + 1 < F:
|
||||
f.write("f %s\n" % " ".join(face))
|
||||
|
||||
Reference in New Issue
Block a user