[render] round 1 NOTES

Decisions, verification evidence, honest limitations, and 3 contract
requests (BeltItem stable id, optional MachineDef.color, main.ts placing
on any pointer button).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-17 16:31:10 +10:00
parent 883dd4b02b
commit 5ee0fb9e78

View File

@ -65,3 +65,92 @@ clean. NOTES written.
### Round N — YYYY-MM-DD — [your model]
SHIPPED: / DECISIONS: / BLOCKED/BROKEN: / CONTRACT REQUEST: / PROPOSAL: / NEXT:
```
### Round 1 — 2026-07-17 — Opus 4.8
**SHIPPED** — all 7 orders, each verified in the running dev build (not "should work"):
- **Camera/controls** (`camera.ts`): ortho iso, wheel zoom clamped 8..40, middle/right-drag
pan, WASD+arrows, resize via ResizeObserver.
- **Ground** (`ground.ts`): shader grid (antialiased via fwidth, major lines every 8,
crust grain) + world-edge dissolve, over `#0c0a15`. Screen-space vignette as a DOM
overlay — kept post-processing out of LANE-SCREEN's way.
- **Registry + hot-swap** (`registry.ts`): placeholder factories per kind; probes
`assets/models/<key>.glb` on init + every 10s in dev. **Verified live**: dropped a
GLB into `public/assets/models/quantizer.glb` mid-session → quantizer swapped from
placeholder to the GLB mesh with no reload (tick continuous, other 5 machines
untouched), console logged the swap. Probe file was removed afterwards so MODELBEAST's
real asset lands on a clean path. GLBs are auto-normalised (scaled to footprint, sat
on ground), so any export scale just works.
- **Entities** (`entities.ts`), **belts** (`belts.ts`, instanced + chevron scroll),
**belt items** (`beltitems.ts`, InstancedMesh per type, interpolated), **ghost +
picking** (`ghost.ts`), jam blink + brownout dimming.
**VERIFIED (numbers, not vibes)**
- **Perf standing rule met with 5x headroom**: `?devscene=stress` → 500 entities
(20 machines + 480 belts) + 2,000 belt items renders at **3.2ms/frame avg** (budget
16.6ms). The 2,480 belts+items cost **5 instanced draw calls** total.
- **Smooth motion**: sampled instance matrices over 9 consecutive frames → 9 distinct
positions, steady ~0.0166 tiles/frame (2 tiles/s on a 120Hz panel). Interpolating
continuously, not stepping at 30tps.
- **Ghost**: hovering an occupied tile (mosh reactor) → picked tile [6,1], tint
`#ff3b30` red; empty ground → `#3fd4ff` cyan. Driven through main.ts's real glue.
- **Brownout**: exposure 1.35 → 0.644 with flicker. **Jam**: amber `#ffa726`, blinking.
**DECISIONS** (flagging these because they're judgement calls, not obvious readings)
- **Machine accent colour is derived from data**: `MachineDef` has no `color` field, so
a machine's one emissive accent = the colour of the item it makes (recipes → outputs →
`ItemDef.color`). Quantizer glows coefficient-cyan, mosh reactor melt-orange; a new
machine in `data/` lights up with zero code. Matches §8's "colour = value = literally
the resource". See CONTRACT REQUEST below.
- **Legibility floor on data colours.** Raw products are near-black by design (MDAT ORE
`#1a1a22`). Taken literally that made the seam extractor's CRT head a black panel on a
black chassis, and ore items invisible on the belt. Derived accents below L=0.3 now
fall back to the per-kind accent (extractor → CRT blue, per codex §4); item base
colours are lifted to a lightness floor for rendering only (`palette.readable`). Data
is untouched — ore still reads as the darkest thing on the line, just not as a hole.
- **Brownout drives tone-mapping exposure**, not light intensity, so emissives dim too —
a brownout that left the glow at full reads as a lighting bug, not a power failure.
- **Fog is banded around the camera distance**, not absolute. Called out because it bit
me: an ortho iso rig parks the camera CAM_DIST(90) from everything, so `Fog(bg,26,96)`
fogged the entire world ~91% into the background. Anything touching `CAM_DIST` must
keep `index.ts`'s fog band in step.
- Dev scaffold (`devscene.ts`) is gated behind `import.meta.env.DEV` **and** `?devscene`,
and is tree-shaken out of the prod bundle (verified: 0 hits in `dist/`). It yields
automatically the moment the real sim reports any entity — it never fabricates over
live sim data. `?devscene=stress` is the perf rig.
**BLOCKED/BROKEN** — nothing blocking. Honest limitations:
- **Belt GLB instancing takes only the FIRST mesh** of a multi-mesh GLB. Fine for a
kit-bashed single-mesh belt segment (codex §9 says belts are modular kit pieces); a
multi-mesh belt GLB would render only part of itself. Machines are unaffected.
- **GLB animation clips are not played** (no AnimationMixer yet). Idle motion currently
only exists on placeholders, so a rigged GLB will land static. Wanted for M4.
- **Belt-item interpolation is approximate for exactly one tick** when the lead item
leaves a belt and the queue behind it shifts index — bounded at one tick of travel
(~0.07 tiles), imperceptible. Root cause is the missing stable id; see below.
- Below 30fps the interpolation stretches (prev-tick snapshot may be >1 tick back).
Not observed; noting it rather than hiding it.
**CONTRACT REQUEST**
1. `BeltItem.id` (stable, per-item) — would make cargo interpolation exact instead of
order-matched. Low priority; current error is imperceptible.
2. `MachineDef.color?: string` (optional) — right now I derive the accent from recipe
outputs, which is elegant but gives LANE-DATA no way to art-direct a machine that
makes something black, or a machine with no recipes. Optional field, derived fallback.
3. **`main.ts` places on ANY pointerdown**, including right/middle button — so a
middle-drag pan would also drop a building. I worked around it inside my lane
(`camera.ts` stops non-left buttons from bubbling to `#game`), but the clean fix is
`if (e.button !== 0) return;` in main.ts's handler. Flagging since it's your file.
**PROPOSAL**
- MODELBEAST asset keys are live now — the registry will hot-swap any of these the
moment a GLB lands, no code change: `seam-extractor`, `belt`, `demuxer`, `quantizer`,
`mosh-reactor`, `decode-asic`, `shipper` (+ whatever LANE-DATA adds; the key is
`MachineDef.asset`). Hero assets (mosh reactor, muxer) are the ones worth `fal_trellis2`.
- Shadows are on (2048 map, tight ortho shadow camera). Cheap at current load; if a big
factory drags, that's the first dial to turn.
**NEXT (round 2 candidates, not self-assigned)**
- AnimationMixer for rigged GLBs; per-era skinning hooks; splitter/lane visuals; heat
shimmer + throttle read-out on the software decoder; belt corner/junction pieces
(currently every belt is a straight plate regardless of neighbours).