Updraft slice 1 — THE TOWER. The Codex Tower: shaft, 22 galleries, shelving, two hundred thousand volumes, the leaded lantern dome, the slate reading floor, the plain.
lerp(a: number, b: number, u: number) → number
════════════════════════════════════════════════════════════ small helpers
| arg | type | description |
|---|
| a | number | |
| b | number | |
| u | number | |
clamp01(x: number) → number
| arg | type | description |
|---|
| x | number | |
mix3(a: { number }, b: { number }, u: number) → void
| arg | type | description |
|---|
| a | { number } | |
| b | { number } | |
| u | number | |
rng(seed: number) → void
A deterministic stream, so the tower is the same tower on every build.
| arg | type | description |
|---|
| seed | number | |
qAxis(ax: number, ay: number, az: number, a: number) → void
Quaternions, because a swinging lamp needs two rotations composed.
| arg | type | description |
|---|
| ax | number | |
| ay | number | |
| az | number | |
| a | number | |
qMul(a: { number }, b: { number }) → void
| arg | type | description |
|---|
| a | { number } | |
| b | { number } | |
qOutward(theta: number) → void
The yaw that turns an entity's local +Z into the outward radial at theta.
| arg | type | description |
|---|
| theta | number | |
galleryY(i: number) → number
| arg | type | description |
|---|
| i | number | |
v(x: number, y: number, z: number, nx: number, ny: number, nz: number, tu: number, tv: number) → number
| arg | type | description |
|---|
| x | number | |
| y | number | |
| z | number | |
| nx | number | |
| ny | number | |
| nz | number | |
| tu | number | |
| tv | number | |
tri(a: number, b: number, c: number) → void
| arg | type | description |
|---|
| a | number | |
| b | number | |
| c | number | |
face(a: { number }, b: { number }, c: { number }, d: { number }, uvScale: number?) → void
One quad from four world-space corners, wound a→b→c→d, normal from the
winding so a face is never lit from behind by accident.
| arg | type | description |
|---|
| a | { number } | |
| b | { number } | |
| c | { number } | |
| d | { number } | |
| uvScale | number? | |
box(cx: number, cy: number, cz: number, hx: number, hy: number, hz: number) → void
An axis-aligned box, six outward faces.
| arg | type | description |
|---|
| cx | number | |
| cy | number | |
| cz | number | |
| hx | number | |
| hy | number | |
| hz | number | |
genShaftWall( ) → void
════════════════════════════════════════════════════════════ the geometry
The shaft's inner wall: stone courses from the vault to the dome springing,
facing inward, with the four ground-floor doors cut out of it.
inDoor(th: number, ya: number, yb: number) → boolean
| arg | type | description |
|---|
| th | number | |
| ya | number | |
| yb | number | |
genExterior( ) → void
The drum's outside, its pilasters and its cornice — what shot 14 sees.
genDeck(notch: boolean) → void
A gallery deck: oak boards on radial joists, an oak fascia at the void edge.
`notch` cuts the four door azimuths out of Gallery 1.
| arg | type | description |
|---|
| notch | boolean | |
pt(r: number, y: number, sd: number) → void
| arg | type | description |
|---|
| r | number | |
| y | number | |
| sd | number | |
genRail(gapA: number?, gapB: number?) → void
The brass rail and its stanchions, at the walkway's void edge.
`gapA`/`gapB` leave a run out for the hero section shot 9 sags.
| arg | type | description |
|---|
| gapA | number? | |
| gapB | number? | |
inGap(t: number) → boolean
| arg | type | description |
|---|
| t | number | |
ring(t: number, y: number) → void
| arg | type | description |
|---|
| t | number | |
| y | number | |
genBook( ) → void
One volume. Base at y = 0, one unit tall and one unit wide/deep, so the
instance matrix reads straight as (spine width, height, depth). The spine
face carries three facets, which is what makes shot 3 legible.
genFloor( ) → void
The black slate reading floor, laid as slabs, and the grille ring that
vents the sunken vault (the draught shot 1 lifts the folio's corner with).
genGrille( ) → void
The iron grilles over the vault ring: radial bars with air between them.
pt(r: number, y: number, sd: number) → void
| arg | type | description |
|---|
| r | number | |
| y | number | |
| sd | number | |
genPlain( ) → void
The frozen plain: a wide, gently-drifted disc, dark except where the tower
throws light on it.
h(r: number, t: number) → number
| arg | type | description |
|---|
| r | number | |
| t | number | |
domeProfile(u: number) → void
| arg | type | description |
|---|
| u | number | |
genDomePane(ring: number) → void
| arg | type | description |
|---|
| ring | number | |
p(r: number, y: number, c: number, s: number) → void
| arg | type | description |
|---|
| r | number | |
| y | number | |
| c | number | |
| s | number | |
p(y: number, c: number, s: number) → void
| arg | type | description |
|---|
| y | number | |
| c | number | |
| s | number | |
genCameRib( ) → void
One lead-came meridian rib, from the springing to the oculus, plus the
ring bar at its foot.
genCameRing(ring: number) → void
| arg | type | description |
|---|
| ring | number | |
genLanternCap( ) → void
The little lead cap that finishes the lantern above the glazing.
genDesk( ) → void
A reading desk: oak top on four legs, with the small brass lamp's plinth.
drum(y0: number, y1: number, r0: number, r1: number) → void
| arg | type | description |
|---|
| y0 | number | |
| y1 | number | |
| r0 | number | |
| r1 | number | |
genFlame( ) → void
A flame: a tapered blade, one unit tall, so the instance scale IS its size.
genSheet( ) → void
One sheet of paper, one unit square, centred, drawn from both sides.
genFolioPages( ) → void
The folio on Desk 7: an open book, both leaves splayed off the spine.
genFolioCorner( ) → void
The corner flap that lifts in the draught. Hinged on its local Z axis at
x = 0, extending +X, so a rotation about local Z lifts it off the page.
genReadingLamp( ) → void
A gallery reading lamp on its counterweight arm. The pivot is the origin;
the arm reaches inward over the void along local -Z.
genRailSeg( ) → void
A short length of rail, for the twenty hero segments that sag in shot 9.
makeMat(key: string, base: { number }, rough: number, metal: number, extra: any?) → void
| arg | type | description |
|---|
| key | string | |
| base | { number } | |
| rough | number | |
| metal | number | |
| extra | any? | |
bandKey(surface: string, g: number) → string
| arg | type | description |
|---|
| surface | string | |
| g | number | |
fireFront(heat: number) → number
Where the flame front stands, as a gallery number. Pinned to the shot list:
shot 7 (t 38..44, heat .22 → .32) has to read as Gallery 3 climbing to
Gallery 7, and it does — front(.22) = 3.6, front(.32) = 6.6.
| arg | type | description |
|---|
| heat | number | |
galleryHeat(heat: number, g: number) → number
| arg | type | description |
|---|
| heat | number | |
| g | number | |
floorHeat(heat: number) → number
The floor and the vault take light only once the fire owns the shaft.
| arg | type | description |
|---|
| heat | number | |
fireColorAt(y: number) → void
The fire's colour at a height, which is the film's whole Movement IV look.
| arg | type | description |
|---|
| y | number | |
meshOf(geom: any) → void
| arg | type | description |
|---|
| geom | any | |
meshAsset(name: string, geom: any) → void
The two meshes a POPULATION draws have to be assets: a population variant
names its mesh by asset reference, and a runtime GPU guid put there resolves
to nothing and registers no draw at all. They are also authored ONCE and
never re-authored — an asset rewritten under its own guid leaves the
renderer's GPU store holding the entry it already had, and every population
drawing from it reports "not resident" once per variant per frame while the
shelves are silently absent from the picture.
| arg | type | description |
|---|
| name | string | |
| geom | any | |
populationAsset(name: string, variants: { any }) → void
A population asset is authored ONCE, for the same reason a mesh asset is.
Re-authoring one during a build costs more than the write: while play is
running a /source write lands on the play shadow, and a population read back
from the shadow never reaches the GPU — it reports its full instance count,
reports `usable`, registers ZERO draws, and logs nothing at all. The archive
is then simply absent from every interior shot while the film reports
success. Resolving the asset that is already on disk is what keeps the two
hundred and thirty thousand volumes in the picture when the film is built
from `onLoad()`, which is the only way it is ever built.
| arg | type | description |
|---|
| name | string | |
| variants | { any } | |
spawn(name: string, parent: any, opts: any) → void
| arg | type | description |
|---|
| name | string | |
| parent | any | |
| opts | any | |
modelEnt(name: string, parent: any, meshHandle: any, key: string, pos: any, rot: any?, scale: any?) → void
| arg | type | description |
|---|
| name | string | |
| parent | any | |
| meshHandle | any | |
| key | string | |
| pos | any | |
| rot | any? | |
| scale | any? | |
buildBooks(root: any, bookMeshGuid: string) → void
| arg | type | description |
|---|
| root | any | |
| bookMeshGuid | string | |
buildBays(root: any, bayMeshGuid: string) → void
| arg | type | description |
|---|
| root | any | |
| bayMeshGuid | string | |
buildCollapse(root: any, bookMeshHandle: any, timberMeshHandle: any) → void
| arg | type | description |
|---|
| root | any | |
| bookMeshHandle | any | |
| timberMeshHandle | any | |
buildDome(root: any) → void
| arg | type | description |
|---|
| root | any | |
homeAt(centre: { number }, th: number) → void
A pane's home is its own centre, spun round the axis to its meridian.
| arg | type | description |
|---|
| centre | { number } | |
| th | number | |
buildDesks(root: any) → void
| arg | type | description |
|---|
| root | any | |
buildFolio(root: any, desk7: any) → void
| arg | type | description |
|---|
| root | any | |
| desk7 | any | |
buildLamps(root: any) → void
| arg | type | description |
|---|
| root | any | |
buildSkidPages(root: any) → void
| arg | type | description |
|---|
| root | any | |
buildHeroRail(root: any) → void
| arg | type | description |
|---|
| root | any | |
pushBand(surface: string, g: number, char: number, glow: number, y: number) → void
════════════════════════════════════════════════════════════ per-frame look
Push a band's charred colour and its glow. Only when it actually moved:
a uniform that has not changed is a write nobody sees.
| arg | type | description |
|---|
| surface | string | |
| g | number | |
| char | number | |
| glow | number | |
| y | number | |
tickFolio(s: any) → void
════════════════════════════════════════════════════════════ per-frame motion
Shot 1: the folio's top corner lifting and settling in the draught coming
up off the vault grilles.
tickLamps(s: any) → void
Shot 3: the brass reading lamps swinging on their counterweight arms.
Dead calm to start; the indraft agitates them as the tower starts drawing.
tickSkidPages(s: any) → void
Shot 3: a loose page skidding along the gallery boards ahead of the lens.
tickFlames(s: any) → void
Shot 2 / 11: the forty desk lamps guttering.
tickHeroRail(s: any) → void
Shot 9: the Gallery 6 rail going from cold metal to glowing to slumping,
and a rivet head running and dripping off it.
pt(u: number) → void
| arg | type | description |
|---|
| u | number | |
tickEmptying(s: any) → void
Shot 5 / 12: the shelves empty in the order the fire reached them.
tickCollapse(s: any) → void
fly(list: { any }, gain: number, tumble: boolean) → void
| arg | type | description |
|---|
| list | { any } | |
| gain | number | |
| tumble | boolean | |
reset( ) → void
════════════════════════════════════════════════════════════ reset & tick
tickResidency(s: any) → void
A population whose mesh has left the GPU store draws nothing, silently, for
the rest of the film. Two hundred thousand volumes is too much to lose to
that, so the tower checks its own geometry twice a second and puts it back.
report( ) → void
What the tower knows about itself, for a probe or a capture loop.
poseAt(t: number) → void
Pose the tower at a film time without running the film — the door for a
capture session checking one moment. The film itself never calls this.
| arg | type | description |
|---|
| t | number | Film seconds. |
rebuild( ) → void
Rebuild the place outside the film, for authoring. play() calls build()
itself; this is the door for a capture session that has not pressed play.