CLI, along with several examples, plus model downloading
This commit is contained in:
1 parent
4f9e73a418
commit
51ace681a7
22 files changed
+1804
-18
No files matched your search
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Writes examples/models/boxwing.gltf: a simple box-wing satellite.
|
||||
|
||||
A 1 x 1 x 1.5 m bus wrapped in gold-colored insulation, a white radiator panel on
|
||||
its -Z face, and two 3 x 1 m dark blue solar arrays on short booms along +Y and -Y.
|
||||
The arrays and radiator are zero-thickness quads, which the renderer shades from
|
||||
whichever side faces the camera. Body frame: +X forward, +Z up through the bus.
|
||||
|
||||
No normals are stored, so the renderer gives every triangle a flat normal from its
|
||||
winding; faces are wound counterclockwise seen from outside.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import json
|
||||
import pathlib
|
||||
import struct
|
||||
|
||||
|
||||
def box(cx, cy, cz, sx, sy, sz):
|
||||
"""Triangles of an axis-aligned box centered at (cx, cy, cz) with sides s."""
|
||||
hx, hy, hz = sx / 2, sy / 2, sz / 2
|
||||
corner = lambda i: (cx + (hx if i & 1 else -hx), cy + (hy if i & 2 else -hy), cz + (hz if i & 4 else -hz))
|
||||
faces = [[0, 2, 3, 1], [4, 5, 7, 6], [0, 1, 5, 4], [2, 6, 7, 3], [0, 4, 6, 2], [1, 3, 7, 5]]
|
||||
tris = []
|
||||
for f in faces:
|
||||
tris += [(corner(f[0]), corner(f[1]), corner(f[2])), (corner(f[0]), corner(f[2]), corner(f[3]))]
|
||||
return tris
|
||||
|
||||
|
||||
def quad(a, b, c, d):
|
||||
return [(a, b, c), (a, c, d)]
|
||||
|
||||
|
||||
parts = {
|
||||
"bus": ((0.80, 0.60, 0.20), box(0, 0, 0, 1.0, 1.0, 1.5)),
|
||||
"radiator": ((0.85, 0.85, 0.85), quad((-0.45, -0.45, -0.76), (-0.45, 0.45, -0.76), (0.45, 0.45, -0.76), (0.45, -0.45, -0.76))),
|
||||
"boom +y": ((0.30, 0.30, 0.30), box(0, 0.75, 0, 0.05, 0.5, 0.05)),
|
||||
"boom -y": ((0.30, 0.30, 0.30), box(0, -0.75, 0, 0.05, 0.5, 0.05)),
|
||||
# Arrays face +X.
|
||||
"array +y": ((0.05, 0.08, 0.20), quad((0, 1.0, -0.5), (0, 4.0, -0.5), (0, 4.0, 0.5), (0, 1.0, 0.5))),
|
||||
"array -y": ((0.05, 0.08, 0.20), quad((0, -4.0, -0.5), (0, -1.0, -0.5), (0, -1.0, 0.5), (0, -4.0, 0.5))),
|
||||
}
|
||||
|
||||
buffer = bytearray()
|
||||
gltf = {"asset": {"version": "2.0", "generator": "resolved scripts/make-example-model.py"},
|
||||
"scene": 0, "scenes": [{"nodes": []}], "nodes": [], "meshes": [], "materials": [],
|
||||
"accessors": [], "bufferViews": [], "buffers": []}
|
||||
for i, (name, (color, tris)) in enumerate(parts.items()):
|
||||
points = [p for t in tris for p in t]
|
||||
offset = len(buffer)
|
||||
for p in points:
|
||||
buffer += struct.pack("<3f", *p)
|
||||
gltf["bufferViews"].append({"buffer": 0, "byteOffset": offset, "byteLength": 12 * len(points)})
|
||||
gltf["accessors"].append({"bufferView": i, "componentType": 5126, "count": len(points), "type": "VEC3",
|
||||
"min": [min(p[k] for p in points) for k in range(3)],
|
||||
"max": [max(p[k] for p in points) for k in range(3)]})
|
||||
gltf["materials"].append({"name": name, "pbrMetallicRoughness": {"baseColorFactor": [*color, 1.0]}})
|
||||
gltf["meshes"].append({"name": name, "primitives": [{"attributes": {"POSITION": i}, "material": i}]})
|
||||
gltf["nodes"].append({"name": name, "mesh": i})
|
||||
gltf["scenes"][0]["nodes"].append(i)
|
||||
gltf["buffers"].append({"byteLength": len(buffer),
|
||||
"uri": "data:application/octet-stream;base64," + base64.b64encode(buffer).decode()})
|
||||
|
||||
out = pathlib.Path(__file__).resolve().parent.parent / "examples" / "models" / "boxwing.gltf"
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
out.write_text(json.dumps(gltf, indent=1) + "\n")
|
||||
print(f"wrote {out}")
|
||||
Reference in new issue
Block a user