davidvgilmore commited on
Commit
2dd594f
·
verified ·
1 Parent(s): 539f827

Upload hy3dgen/shapegen/postprocessors.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. hy3dgen/shapegen/postprocessors.py +157 -0
hy3dgen/shapegen/postprocessors.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Open Source Model Licensed under the Apache License Version 2.0
2
+ # and Other Licenses of the Third-Party Components therein:
3
+ # The below Model in this distribution may have been modified by THL A29 Limited
4
+ # ("Tencent Modifications"). All Tencent Modifications are Copyright (C) 2024 THL A29 Limited.
5
+
6
+ # Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved.
7
+ # The below software and/or models in this distribution may have been
8
+ # modified by THL A29 Limited ("Tencent Modifications").
9
+ # All Tencent Modifications are Copyright (C) THL A29 Limited.
10
+
11
+ # Hunyuan 3D is licensed under the TENCENT HUNYUAN NON-COMMERCIAL LICENSE AGREEMENT
12
+ # except for the third-party components listed below.
13
+ # Hunyuan 3D does not impose any additional limitations beyond what is outlined
14
+ # in the repsective licenses of these third-party components.
15
+ # Users must comply with all terms and conditions of original licenses of these third-party
16
+ # components and must ensure that the usage of the third party components adheres to
17
+ # all relevant laws and regulations.
18
+
19
+ # For avoidance of doubts, Hunyuan 3D means the large language models and
20
+ # their software and algorithms, including trained model weights, parameters (including
21
+ # optimizer states), machine-learning model code, inference-enabling code, training-enabling code,
22
+ # fine-tuning enabling code and other elements of the foregoing made publicly available
23
+ # by Tencent in accordance with TENCENT HUNYUAN COMMUNITY LICENSE AGREEMENT.
24
+
25
+ import tempfile
26
+ from typing import Union
27
+
28
+ import pymeshlab
29
+ import trimesh
30
+
31
+ from .models.vae import Latent2MeshOutput
32
+
33
+
34
+ def load_mesh(path):
35
+ if path.endswith(".glb"):
36
+ mesh = trimesh.load(path)
37
+ else:
38
+ mesh = pymeshlab.MeshSet()
39
+ mesh.load_new_mesh(path)
40
+ return mesh
41
+
42
+
43
+ def reduce_face(mesh: pymeshlab.MeshSet, max_facenum: int = 200000):
44
+ mesh.apply_filter(
45
+ "meshing_decimation_quadric_edge_collapse",
46
+ targetfacenum=max_facenum,
47
+ qualitythr=1.0,
48
+ preserveboundary=True,
49
+ boundaryweight=3,
50
+ preservenormal=True,
51
+ preservetopology=True,
52
+ autoclean=True
53
+ )
54
+ return mesh
55
+
56
+
57
+ def remove_floater(mesh: pymeshlab.MeshSet):
58
+ mesh.apply_filter("compute_selection_by_small_disconnected_components_per_face",
59
+ nbfaceratio=0.005)
60
+ mesh.apply_filter("compute_selection_transfer_face_to_vertex", inclusive=False)
61
+ mesh.apply_filter("meshing_remove_selected_vertices_and_faces")
62
+ return mesh
63
+
64
+
65
+ def pymeshlab2trimesh(mesh: pymeshlab.MeshSet):
66
+ with tempfile.NamedTemporaryFile(suffix='.ply', delete=True) as temp_file:
67
+ mesh.save_current_mesh(temp_file.name)
68
+ mesh = trimesh.load(temp_file.name)
69
+ # 检查加载的对象类型
70
+ if isinstance(mesh, trimesh.Scene):
71
+ combined_mesh = trimesh.Trimesh()
72
+ # 如果是Scene,遍历所有的geometry并合并
73
+ for geom in mesh.geometry.values():
74
+ combined_mesh = trimesh.util.concatenate([combined_mesh, geom])
75
+ mesh = combined_mesh
76
+ return mesh
77
+
78
+
79
+ def trimesh2pymeshlab(mesh: trimesh.Trimesh):
80
+ with tempfile.NamedTemporaryFile(suffix='.ply', delete=True) as temp_file:
81
+ if isinstance(mesh, trimesh.scene.Scene):
82
+ for idx, obj in enumerate(mesh.geometry.values()):
83
+ if idx == 0:
84
+ temp_mesh = obj
85
+ else:
86
+ temp_mesh = temp_mesh + obj
87
+ mesh = temp_mesh
88
+ mesh.export(temp_file.name)
89
+ mesh = pymeshlab.MeshSet()
90
+ mesh.load_new_mesh(temp_file.name)
91
+ return mesh
92
+
93
+
94
+ def export_mesh(input, output):
95
+ if isinstance(input, pymeshlab.MeshSet):
96
+ mesh = output
97
+ elif isinstance(input, Latent2MeshOutput):
98
+ output = Latent2MeshOutput()
99
+ output.mesh_v = output.current_mesh().vertex_matrix()
100
+ output.mesh_f = output.current_mesh().face_matrix()
101
+ mesh = output
102
+ else:
103
+ mesh = pymeshlab2trimesh(output)
104
+ return mesh
105
+
106
+
107
+ def import_mesh(mesh: Union[pymeshlab.MeshSet, trimesh.Trimesh, Latent2MeshOutput, str]) -> pymeshlab.MeshSet:
108
+ if isinstance(mesh, str):
109
+ mesh = load_mesh(mesh)
110
+ elif isinstance(mesh, Latent2MeshOutput):
111
+ mesh = pymeshlab.MeshSet()
112
+ mesh_pymeshlab = pymeshlab.Mesh(vertex_matrix=mesh.mesh_v, face_matrix=mesh.mesh_f)
113
+ mesh.add_mesh(mesh_pymeshlab, "converted_mesh")
114
+
115
+ if isinstance(mesh, (trimesh.Trimesh, trimesh.scene.Scene)):
116
+ mesh = trimesh2pymeshlab(mesh)
117
+
118
+ return mesh
119
+
120
+
121
+ class FaceReducer:
122
+ def __call__(
123
+ self,
124
+ mesh: Union[pymeshlab.MeshSet, trimesh.Trimesh, Latent2MeshOutput, str],
125
+ max_facenum: int = 40000
126
+ ) -> Union[pymeshlab.MeshSet, trimesh.Trimesh]:
127
+ ms = import_mesh(mesh)
128
+ ms = reduce_face(ms, max_facenum=max_facenum)
129
+ mesh = export_mesh(mesh, ms)
130
+ return mesh
131
+
132
+
133
+ class FloaterRemover:
134
+ def __call__(
135
+ self,
136
+ mesh: Union[pymeshlab.MeshSet, trimesh.Trimesh, Latent2MeshOutput, str],
137
+ ) -> Union[pymeshlab.MeshSet, trimesh.Trimesh, Latent2MeshOutput]:
138
+ ms = import_mesh(mesh)
139
+ ms = remove_floater(ms)
140
+ mesh = export_mesh(mesh, ms)
141
+ return mesh
142
+
143
+
144
+ class DegenerateFaceRemover:
145
+ def __call__(
146
+ self,
147
+ mesh: Union[pymeshlab.MeshSet, trimesh.Trimesh, Latent2MeshOutput, str],
148
+ ) -> Union[pymeshlab.MeshSet, trimesh.Trimesh, Latent2MeshOutput]:
149
+ ms = import_mesh(mesh)
150
+
151
+ with tempfile.NamedTemporaryFile(suffix='.ply', delete=True) as temp_file:
152
+ ms.save_current_mesh(temp_file.name)
153
+ ms = pymeshlab.MeshSet()
154
+ ms.load_new_mesh(temp_file.name)
155
+
156
+ mesh = export_mesh(mesh, ms)
157
+ return mesh