Spaces:
Runtime error
Runtime error
Upload hy3dgen/shapegen/postprocessors.py with huggingface_hub
Browse files
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
|