mapUV(rect: { number }, s: number, t: number) → void
| arg | type | description |
|---|
| rect | { number } | |
| s | number | |
| t | number | |
flatUV(rect: { number }) → void
The middle of a flat-paint rectangle, inset far enough that no mip level of
the atlas bleeds a neighbouring paint into it.
| arg | type | description |
|---|
| rect | { number } | |
normalize(x: number, y: number, z: number) → void
| arg | type | description |
|---|
| x | number | |
| y | number | |
| z | number | |
vert(self: any, x: number, y: number, z: number, nx: number, ny: number, nz: number, u: number, v: number) → number
Add one vertex; returns its 0-based index (the base `indices` counts from).
| arg | type | description |
|---|
| self | any | |
| x | number | |
| y | number | |
| z | number | |
| nx | number | |
| ny | number | |
| nz | number | |
| u | number | |
| v | number | |
tri(self: any, a: number, b: number, c: number) → void
| arg | type | description |
|---|
| self | any | |
| a | number | |
| b | number | |
| c | number | |
triOriented(self: any, a: number, b: number, c: number) → void
Emit a triangle wound so its front face agrees with the normal its vertices
carry. Winding is the one thing a hand-written loft gets wrong silently — a
reversed face draws nothing and the shape reads as a hole — so every face in
this file goes through here rather than through a remembered vertex order.
| arg | type | description |
|---|
| self | any | |
| a | number | |
| b | number | |
| c | number | |
quad(self: any, a: number, b: number, c: number, d: number) → void
| arg | type | description |
|---|
| self | any | |
| a | number | |
| b | number | |
| c | number | |
| d | number | |
quadFixed(self: any, a: number, b: number, c: number, d: number) → void
A quad wound exactly as given. `triOriented` decides winding from the vertex
normals, which is right where the outward direction is obvious (a tube, a
disc, a box) and wrong on a surface that closes on itself — an aerofoil's
leading and trailing edges pinch to zero thickness, the normals there answer
nothing, and the triangles touching them came out facing whichever way. This
is for a loft that states its own winding.
| arg | type | description |
|---|
| self | any | |
| a | number | |
| b | number | |
| c | number | |
| d | number | |
geometry(self: any) → Geometry
| arg | type | description |
|---|
| self | any | |
bounds(g: Geometry) → void
The local-space AABB of a geometry, as `{ min = {x,y,z}, max = {x,y,z} }`.
| arg | type | description |
|---|
| g | Geometry | |
recentre(g: Geometry, key: string) → Geometry
Move a part's geometry so its own pivot sits at the origin. The entity
carrying it is then placed at that pivot, and the part's transform reads as
where the part is on the toy.
| arg | type | description |
|---|
| g | Geometry | |
| key | string | |
mirrorX(g: Geometry) → Geometry
Mirror a geometry across the YZ plane: every x negates, and so does every
normal's x, which leaves each triangle facing the way it did before.
| arg | type | description |
|---|
| g | Geometry | |
merge(parts: { Geometry }) → Geometry
Merge geometries into one, offsetting each one's indices as it lands.
| arg | type | description |
|---|
| parts | { Geometry } | |
tube(b: any, stations: { Station }, segs: number, rect: { number }, inward: boolean, u0: number, u1: number, byLength: boolean?) → void
A tube lofted along +Z through elliptical stations. `inward` builds the duct
case: normals point at the axis so the surface is seen from inside.
`uMap` turns a station index into the atlas u it samples.
| arg | type | description |
|---|
| b | any | |
| stations | { Station } | |
| segs | number | |
| rect | { number } | |
| inward | boolean | |
| u0 | number | |
| u1 | number | |
| byLength | boolean? | |
disc(b: any, z: number, radius: number, segs: number, dir: number, rect: { number }, cy: number) → void
A flat disc facing `dir` (+1 = +Z, -1 = -Z) at `z`, radial UVs into `rect`.
| arg | type | description |
|---|
| b | any | |
| z | number | |
| radius | number | |
| segs | number | |
| dir | number | |
| rect | { number } | |
| cy | number | |
foilT(c: number) → number
The half-thickness of the toy's aerofoil at chord fraction `c`, as a share of
the section's stated thickness. Blunt at the nose, tapering to a closed edge.
| arg | type | description |
|---|
| c | number | |
foilC(idx: number) → number
Where along the chord step `idx` sits. Cosine spacing, so the steps crowd at
the leading and trailing edges where the aerofoil turns hardest and thin out
across the flat middle: an evenly-spaced loft spends its vertices where the
surface is already straight and reads as a run of chordwise facets over the
wing's top, which is exactly where a top-down camera looks.
| arg | type | description |
|---|
| idx | number | |
foil(b: any, sections: { Section }, rect: { number }, capRoot: boolean, capTip: boolean) → void
Loft an aerofoil through a run of sections. The loop runs LE -> TE over the
upper surface and TE -> LE back along the lower one, so u is the chord
fraction on both faces and the two sides wear the same paint.
| arg | type | description |
|---|
| b | any | |
| sections | { Section } | |
| rect | { number } | |
| capRoot | boolean | |
| capTip | boolean | |
cap(loop: { number }, s: Section, spanV: number, outward: number) → void
A cap reads the loft's OWN paint at the span it closes, so a red-tipped
wing and a red fin end in red rather than in a stripe of bare white. It
faces along the span, not along the thickness — it is the end of the
wing, not another face of it.
The cap gets its own ring of vertices, every one carrying the cap's
normal. That is what makes `triOriented` unambiguous here: all three
vertices of every fan triangle agree on which way out is, so the winding
it picks is the right one whichever hand the loft is.
| arg | type | description |
|---|
| loop | { number } | |
| s | Section | |
| spanV | number | |
| outward | number | |
box(b: any, x0: number, y0: number, z0: number, x1: number, y1: number, z1: number, rect: { number }) → void
A box, one flat paint on every face.
| arg | type | description |
|---|
| b | any | |
| x0 | number | |
| y0 | number | |
| z0 | number | |
| x1 | number | |
| y1 | number | |
| z1 | number | |
| rect | { number } | |
ringXY(b: any, cy: number, cz: number, major: number, minor: number, big: number, small: number, rect: { number }, squash: number, vSpan: { number }?) → void
A ring of circular cross-section standing in the XY plane, centred at
(0, cy, cz) — the wind-up key's bow and its collar. `vSpan` maps the ring's
own minor angle across that slice of `rect`'s v, so the OUTER circumference
(minor angle 0, which the loop meets at both ends) lands on both edges of the
band and the paint can put the rubbed ring exactly there. Without it the
whole ring samples one flat texel.
| arg | type | description |
|---|
| b | any | |
| cy | number | |
| cz | number | |
| major | number | |
| minor | number | |
| big | number | |
| small | number | |
| rect | { number } | |
| squash | number | |
| vSpan | { number }? | |
noseRadius(t: number) → number
| arg | type | description |
|---|
| t | number | |
hullStations( ) → void
Every ring of the hull, sampled off `Geo.HULL`.
push(z: number, rx: number, ry: number, cy: number) → void
| arg | type | description |
|---|
| z | number | |
| rx | number | |
| ry | number | |
| cy | number | |
fuselage( ) → Geometry
The hull: a chunky toy airliner body, nose at -Z, tail cone swept up at +Z.
wingSections(side: number) → void
| arg | type | description |
|---|
| side | number | |
wing(side: number) → Geometry
One wing, `side` = 1 for the right wing and -1 for the left.
| arg | type | description |
|---|
| side | number | |
tailplane( ) → Geometry
The tailplane: both horizontal stabilisers in one mesh.
fin( ) → Geometry
The vertical fin, swept back over the tail cone.
engine(side: number) → Geometry
One engine: nacelle, inlet duct, fan face, spinner and the pylon that hangs
it under the wing. `side` = 1 right, -1 left.
| arg | type | description |
|---|
| side | number | |
key( ) → Geometry
The wind-up key: a shaft up out of the spine and a flat bow to turn it by.
The shaft's axis is x = 0, z = KZ, which is exactly where `Geo.PIVOTS.key`
stands, so the child entity carrying this mesh spins the key in place when
it is rotated about its own local Y.