File size: 4,137 Bytes
ec0c8fa |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
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) |