68 lines
3.2 KiB
Python
Executable File
68 lines
3.2 KiB
Python
Executable File
#!/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}")
|