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) |