Spaces:
Running
on
Zero
Running
on
Zero
| from typing import * | |
| from pathlib import Path | |
| import numpy as np | |
| def write_glb(path: Union[str, Path], vertices: np.ndarray, faces: np.ndarray, vertex_colors: np.ndarray = None, uv: np.ndarray = None): | |
| import pygltflib | |
| has_colors = vertex_colors is not None | |
| has_uv = uv is not None | |
| triangles_bytes = faces.astype(np.uint32).flatten().tobytes() | |
| vertices_bytes = vertices.astype(np.float32).tobytes() | |
| vertex_colors_bytes = vertex_colors.astype(np.float32).tobytes() if has_colors else None | |
| uv_bytes = uv.astype(np.float32).tobytes() if has_uv else None | |
| gltf = pygltflib.GLTF2( | |
| scene=0, | |
| scenes=[pygltflib.Scene(nodes=[0])], | |
| nodes=[pygltflib.Node(mesh=0)], | |
| meshes=[ | |
| pygltflib.Mesh( | |
| primitives=[ | |
| pygltflib.Primitive( | |
| attributes=pygltflib.Attributes( | |
| POSITION=1, | |
| COLOR_0=2 if has_colors else None, | |
| TEXCOORD_0=2 + has_colors if has_uv else None | |
| ), | |
| indices=0 | |
| ) | |
| ] | |
| ) | |
| ], | |
| accessors=list(filter(None, [ | |
| pygltflib.Accessor( # triangles accessor | |
| bufferView=0, | |
| componentType=pygltflib.UNSIGNED_INT, | |
| count=faces.size, | |
| type=pygltflib.SCALAR, | |
| max=[int(faces.max())], | |
| min=[int(faces.min())], | |
| ), | |
| pygltflib.Accessor( # vertices accessor | |
| bufferView=1, | |
| componentType=pygltflib.FLOAT, | |
| count=len(vertices), | |
| type=pygltflib.VEC3, | |
| max=vertices.max(axis=0).tolist(), | |
| min=vertices.min(axis=0).tolist(), | |
| ), | |
| pygltflib.Accessor( # vertex colors accessor | |
| bufferView=2, | |
| componentType=pygltflib.FLOAT, | |
| count=len(vertices), | |
| type=pygltflib.VEC3, | |
| max=vertex_colors.max(axis=0).tolist(), | |
| min=vertex_colors.min(axis=0).tolist(), | |
| ) if has_colors else None, | |
| pygltflib.Accessor( # uv accessor | |
| bufferView=3, | |
| componentType=pygltflib.FLOAT, | |
| count=len(uv), | |
| type=pygltflib.VEC2, | |
| max=uv.max(axis=0).tolist(), | |
| min=uv.min(axis=0).tolist(), | |
| ) if has_uv else None, | |
| ])), | |
| bufferViews=list(filter(None, [ | |
| pygltflib.BufferView( # triangles buffer view | |
| buffer=0, | |
| byteLength=len(triangles_bytes), | |
| target=pygltflib.ELEMENT_ARRAY_BUFFER, | |
| ), | |
| pygltflib.BufferView( # vertices buffer view | |
| buffer=0, | |
| byteOffset=len(triangles_bytes), | |
| byteLength=len(vertices_bytes), | |
| target=pygltflib.ARRAY_BUFFER, | |
| ), | |
| pygltflib.BufferView( # vertex colors buffer view | |
| buffer=0, | |
| byteOffset=len(triangles_bytes) + len(vertices_bytes), | |
| byteLength=len(vertex_colors_bytes), | |
| target=pygltflib.ARRAY_BUFFER, | |
| ) if has_colors else None, | |
| pygltflib.BufferView( # uv buffer view | |
| buffer=0, | |
| byteOffset=len(triangles_bytes) + len(vertices_bytes) + (len(vertex_colors_bytes) if has_colors else 0), | |
| byteLength=len(uv_bytes), | |
| target=pygltflib.ARRAY_BUFFER, | |
| ) if has_uv else None, | |
| ])), | |
| buffers=[ | |
| pygltflib.Buffer( | |
| byteLength=len(triangles_bytes) + len(vertices_bytes) + (len(vertex_colors_bytes) if has_colors else 0) + (len(uv_bytes) if has_uv else 0), | |
| ) | |
| ] | |
| ) | |
| gltf.set_binary_blob(triangles_bytes + vertices_bytes + (vertex_colors_bytes or b'') + (uv_bytes or b'')) | |
| with open(path, 'wb') as f: | |
| for chunk in gltf.save_to_bytes(): | |
| f.write(chunk) |