Postprocess a mesh by simplifying, removing invisible faces, and removing isolated pieces. Args: vertices (np.array): Vertices of the mesh. Shape (V, 3). faces (np.array): Faces of the mesh. Shape (F, 3). simplify (bool): Whether to simplify the mesh, using quadric
(
vertices: np.array,
faces: np.array,
simplify: bool = True,
simplify_ratio: float = 0.9,
fill_holes: bool = True,
fill_holes_max_hole_size: float = 0.04,
fill_holes_max_hole_nbe: int = 32,
fill_holes_resolution: int = 1024,
fill_holes_num_views: int = 1000,
debug: bool = False,
verbose: bool = False,
)
| 198 | |
| 199 | |
| 200 | def postprocess_mesh( |
| 201 | vertices: np.array, |
| 202 | faces: np.array, |
| 203 | simplify: bool = True, |
| 204 | simplify_ratio: float = 0.9, |
| 205 | fill_holes: bool = True, |
| 206 | fill_holes_max_hole_size: float = 0.04, |
| 207 | fill_holes_max_hole_nbe: int = 32, |
| 208 | fill_holes_resolution: int = 1024, |
| 209 | fill_holes_num_views: int = 1000, |
| 210 | debug: bool = False, |
| 211 | verbose: bool = False, |
| 212 | ): |
| 213 | """ |
| 214 | Postprocess a mesh by simplifying, removing invisible faces, and removing isolated pieces. |
| 215 | |
| 216 | Args: |
| 217 | vertices (np.array): Vertices of the mesh. Shape (V, 3). |
| 218 | faces (np.array): Faces of the mesh. Shape (F, 3). |
| 219 | simplify (bool): Whether to simplify the mesh, using quadric edge collapse. |
| 220 | simplify_ratio (float): Ratio of faces to keep after simplification. |
| 221 | fill_holes (bool): Whether to fill holes in the mesh. |
| 222 | fill_holes_max_hole_size (float): Maximum area of a hole to fill. |
| 223 | fill_holes_max_hole_nbe (int): Maximum number of boundary edges of a hole to fill. |
| 224 | fill_holes_resolution (int): Resolution of the rasterization. |
| 225 | fill_holes_num_views (int): Number of views to rasterize the mesh. |
| 226 | verbose (bool): Whether to print progress. |
| 227 | """ |
| 228 | |
| 229 | if verbose: |
| 230 | tqdm.write(f'Before postprocess: {vertices.shape[0]} vertices, {faces.shape[0]} faces') |
| 231 | |
| 232 | # Simplify |
| 233 | if simplify and simplify_ratio > 0: |
| 234 | mesh = pv.PolyData(vertices, np.concatenate([np.full((faces.shape[0], 1), 3), faces], axis=1)) |
| 235 | mesh = mesh.decimate(simplify_ratio, progress_bar=verbose) |
| 236 | vertices, faces = mesh.points, mesh.faces.reshape(-1, 4)[:, 1:] |
| 237 | if verbose: |
| 238 | tqdm.write(f'After decimate: {vertices.shape[0]} vertices, {faces.shape[0]} faces') |
| 239 | |
| 240 | # Remove invisible faces |
| 241 | if fill_holes: |
| 242 | vertices, faces = torch.tensor(vertices).cuda(), torch.tensor(faces.astype(np.int32)).cuda() |
| 243 | vertices, faces = _fill_holes( |
| 244 | vertices, faces, |
| 245 | max_hole_size=fill_holes_max_hole_size, |
| 246 | max_hole_nbe=fill_holes_max_hole_nbe, |
| 247 | resolution=fill_holes_resolution, |
| 248 | num_views=fill_holes_num_views, |
| 249 | debug=debug, |
| 250 | verbose=verbose, |
| 251 | ) |
| 252 | vertices, faces = vertices.cpu().numpy(), faces.cpu().numpy() |
| 253 | if verbose: |
| 254 | tqdm.write(f'After remove invisible faces: {vertices.shape[0]} vertices, {faces.shape[0]} faces') |
| 255 | |
| 256 | return vertices, faces |
| 257 |