(self, save_dir, triplane_feat, reso, n_faces=10000, n_surf_pc=-1, texture_reso=2048, only_largest_cc=True,
save_highres_mesh=False, save_voxel=True, mtl_path=None, file_format="obj")
| 361 | |
| 362 | @torch.no_grad() |
| 363 | def decode_texmesh(self, save_dir, triplane_feat, reso, n_faces=10000, n_surf_pc=-1, texture_reso=2048, only_largest_cc=True, |
| 364 | save_highres_mesh=False, save_voxel=True, mtl_path=None, file_format="obj"): |
| 365 | from .utils3d import sdfgrid_to_mesh, xatlas_uvmap, save_mesh_with_tex, save_mesh_with_tex_to_glb, mesh_decimation, save_mesh_with_pbr, read_metarial_params_from_mtl |
| 366 | import point_cloud_utils as pcu |
| 367 | import cv2 |
| 368 | |
| 369 | H, W = triplane_feat[0].shape[-2:] |
| 370 | D = triplane_feat[1].shape[-1] |
| 371 | new_aabb = self._resize_aabb((H, W, D)) |
| 372 | |
| 373 | # maching cubes on sdf grid |
| 374 | os.makedirs(save_dir, exist_ok=True) |
| 375 | sdf_grid = self.decode_grid(triplane_feat, reso, aabb=new_aabb)[..., 0].detach().cpu().numpy() # (H, W, D, 1) |
| 376 | if save_voxel: |
| 377 | vox_grid = sdf_grid < 0 |
| 378 | save_path = os.path.join(save_dir, f"voxel.npz") |
| 379 | np.savez_compressed(save_path, vox_grid=vox_grid) |
| 380 | |
| 381 | save_path = os.path.join(save_dir, f"mesh_r{reso}.obj") if save_highres_mesh else None |
| 382 | v, f = sdfgrid_to_mesh(sdf_grid, save_path, only_largest_cc=only_largest_cc) |
| 383 | |
| 384 | # re normalize |
| 385 | box_min = new_aabb[:3].detach().cpu().numpy() |
| 386 | box_size = new_aabb[3:].max().item() - new_aabb[:3].min().item() |
| 387 | v = v / reso * box_size + box_min |
| 388 | |
| 389 | # decimation |
| 390 | v, f = mesh_decimation(v, f, n_faces) |
| 391 | |
| 392 | if not self.data_type != "sdf": |
| 393 | save_path = os.path.join(save_dir, f"sdfgrid_r{reso}.npz") |
| 394 | np.savez_compressed(save_path, sdf_grid=sdf_grid) |
| 395 | save_path = os.path.join(save_dir, f"mesh_r{reso}_simple.obj") |
| 396 | pcu.save_mesh_vf(save_path, v, f) |
| 397 | return |
| 398 | |
| 399 | # also save surface point cloud |
| 400 | if n_surf_pc > 0: |
| 401 | f_i, bc = pcu.sample_mesh_random(v, f, n_surf_pc) |
| 402 | surf_points = pcu.interpolate_barycentric_coords(f, f_i, bc, v) |
| 403 | |
| 404 | coords = torch.from_numpy(surf_points).float().to(self.device) |
| 405 | preds = self.decode_batch(triplane_feat, coords, aabb=new_aabb) |
| 406 | save_path = os.path.join(save_dir, f"surf_pc_n{n_surf_pc}.obj") |
| 407 | coords = coords.detach().cpu().numpy() |
| 408 | colors = preds[..., 1:4].detach().cpu().numpy() |
| 409 | colors = np.clip(colors, 0, 1) |
| 410 | pcu.save_mesh_vc(save_path, coords, colors) |
| 411 | |
| 412 | # uv map |
| 413 | v = torch.from_numpy(v).float().to(self.device) |
| 414 | f = torch.from_numpy(f.astype(int)).long().to(self.device) |
| 415 | uvs, mesh_tex_idx, gb_pos, mask = xatlas_uvmap(v, f, texture_reso) |
| 416 | |
| 417 | preds = self.decode_batch(triplane_feat, gb_pos.view(-1, 3)[mask.view(-1)], aabb=new_aabb) |
| 418 | tex_img = torch.zeros((texture_reso, texture_reso, preds.shape[-1] - 1), device=preds.device) |
| 419 | tex_img[mask.view(texture_reso, texture_reso)] = preds[..., 1:].clamp_(0, 1) |
| 420 | # tex_img = preds[..., 1:].clamp_(0, 1).view(texture_reso, texture_reso, 3).detach().cpu().numpy() |
no test coverage detected