SyntheticShapes: real-size display pieces whose UVs run metres / tileSize, so a
library material shows at its real scale on them (materialLibraryKit's convention:
one repeat per UV unit, `tileSize` metres per repeat). Model.model is shared with
every player, so the pieces are real mesh assets, baked once per tile size into the
package's meshes/ folder, and SyntheticSurface swaps to the one matching whatever
material the library puts on an entity. The method is fabricsMaterials' FabricDrape
(Warp and Weft, MIT).
meshes/carPanel_<mm> a car body side panel 1.6 m long and 0.9 m tall, crowned
both ways with a character line, facing +Z (two-sided)
meshes/counter_<mm> a worktop slab 1.2 x 0.03 x 0.62 m
meshes/door_<mm> a cupboard door 0.6 x 0.72 x 0.018 m, its V running up
meshes/mug_<mm> a mug 82 mm across and 95 mm tall with a loop handle (+X)
meshes/pot_<mm> a lidded pot 220 mm across with two side handles
meshes/mat_<mm> a floor mat 0.9 x 0.012 x 0.6 m, its top's V running front to back
All sizes are in metres on an unscaled entity, origin at the piece's base centre.
Runtime-safe except `S.bakeAll()` and `S.bakeMesh()`, which write files (tool code).
norm3(x: number, y: number, z: number) → void
| arg | type | description |
|---|
| x | number | |
| y | number | |
| z | number | |
vert(g: Geo, p: { number }, n: { number }, uv: { number }, t: { number }) → number
| arg | type | description |
|---|
| g | Geo | |
| p | { number } | |
| n | { number } | |
| uv | { number } | |
| t | { number } | |
tri(g: Geo, a: number, b: number, c: number) → void
A triangle wound counter-clockwise as seen from the side its vertex normals face.
| arg | type | description |
|---|
| g | Geo | |
| a | number | |
| b | number | |
| c | number | |
p(k: number, o: number) → number return P
| arg | type | description |
|---|
| k | number | |
| o | number | |
gridSurface(g: Geo, cols: number, rows: number, P: (number, number) → void
A grid surface P(i, j) over (cols + 1) x (rows + 1) points, normals from the
grid's own derivatives (flipped by `flip`), tangents along increasing i, UVs from
the arc length along each row and column in metres / tile.
| arg | type | description |
|---|
| g | Geo | |
| cols | number | |
| rows | number | |
| P | (number, number | |
dist(a: { number }, b: { number }) → number
| arg | type | description |
|---|
| a | { number } | |
| b | { number } | |
box(g: Geo, x0: number, y0: number, z0: number, x1: number, y1: number, z1: number, tile: number) → void
An axis-aligned box from (x0, y0, z0) to (x1, y1, z1), each face with UVs in
metres / tile and tangents along the face's U.
| arg | type | description |
|---|
| g | Geo | |
| x0 | number | |
| y0 | number | |
| z0 | number | |
| x1 | number | |
| y1 | number | |
| z1 | number | |
| tile | number | |
lathe(g: Geo, profile: { { number } }, segs: number, tile: number, cx: number?, cz: number?) → void
A surface of revolution about +Y from a profile of { r, y } points, `segs`
around. U runs round at the profile's widest radius, V along the profile, both in
metres / tile; normals face away from the side `inward` profiles are on.
| arg | type | description |
|---|
| g | Geo | |
| profile | { { number } } | |
| segs | number | |
| tile | number | |
| cx | number? | |
| cz | number? | |
torusArc(g: Geo, c: { number }, ax: { number }, R: number, rr: number, a0: number, a1: number, tile: number) → void
A loop handle: part of a torus in the plane through `c` spanned by `ax` (out) and
+Y, major radius R, tube radius rr, from angle a0 to a1 (radians, 0 = out along ax).
| arg | type | description |
|---|
| g | Geo | |
| c | { number } | |
| ax | { number } | |
| R | number | |
| rr | number | |
| a0 | number | |
| a1 | number | |
| tile | number | |
smooth(a: number, b: number, x: number) → number
| arg | type | description |
|---|
| a | number | |
| b | number | |
| x | number | |
carPanelGeometry(tile: number) → Geo
A car body side panel 1.6 m long and 0.9 m tall, base at y = 0, bulging toward +Z: crowned along its length, rounded over its height (tumblehome) and creased by a character line at 0.6 m. Two-sided, so it reads from behind too.
| arg | type | description |
|---|
| tile | number | |
P(i: number, j: number) → void
| arg | type | description |
|---|
| i | number | |
| j | number | |
counterGeometry(tile: number) → Geo
A worktop slab 1.2 m long, 0.03 m thick and 0.62 m deep; its top face's V runs back to front.
| arg | type | description |
|---|
| tile | number | |
doorGeometry(tile: number) → Geo
A cupboard door 0.6 m wide, 0.72 m tall and 18 mm thick, front face toward +Z with V running up (woodgrain runs up the door).
| arg | type | description |
|---|
| tile | number | |
mugGeometry(tile: number) → Geo
A mug 82 mm across and 95 mm tall with a 4 mm wall and a loop handle toward +X.
| arg | type | description |
|---|
| tile | number | |
potGeometry(tile: number) → Geo
A lidded pot 220 mm across and 125 mm tall to the rim, with a rolled rim, a domed lid with a knob, and two loop handles on the sides (+X and -X).
| arg | type | description |
|---|
| tile | number | |
matGeometry(tile: number) → Geo
A floor mat 0.9 m wide, 12 mm thick and 0.6 m deep, lying on the floor (base at y = 0).
| arg | type | description |
|---|
| tile | number | |
nearestMm(tile: number) → number
| arg | type | description |
|---|
| tile | number | |
meshFor(shape: string, tileSize: number) → string
The identity of the baked mesh for `shape` (carPanel, counter, door, mug, pot or mat) whose UVs are laid for the tile size closest to `tileSize` metres.
| arg | type | description |
|---|
| shape | string | |
| tileSize | number | |
bakeMesh(name: string, g: Geo) → any
Write one mesh asset into meshes/ (tool code). The geometry goes in as encoded ZMSH bytes, because asset.create's own geometry options take no tangents and the anisotropic carbon needs them.
| arg | type | description |
|---|
| name | string | |
| g | Geo | |
bakeAll(shapes: { string }?) → void
Bake every shape for every tile size (tool code). Returns the names written.
| arg | type | description |
|---|
| shapes | { string }? | |