Files
settled-reach/docs/workshops/body-map-viewer/architecture-briefing-final.md
T
jpmschweitzerandClaude Fable 5 29c22cb728 docs(meta): body-map-viewer workshop — rounds, measurements, outcomes, as-built briefing
The complete workshop record: four round-1 positions, five round-2 syntheses
(incl. Troblum's adversarial pass with addendum + final scorecard — all seven
findings resolved), both lead interviews, Qatux's round notes and the 8-section
workshop-outcomes.md (the lakes message-crossing documented as process
history), measurement ⑥ (set_pixel/c1) + the population-survey and chunk/S2
addenda in the measurement docs, the brief's appendix updated through ⑥, and
architecture-briefing-final.md — Jeroen's outline written back as-built
(six-level ladder, lakes, ~9MB resident global tier). README row: Complete.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 10:57:45 +02:00

4.7 KiB
Raw Blame History

title, description, type, status, workshop, created
title description type status workshop created
Body Map Viewer — How It Now Works Jeroen's original outline written back as-built: the ratified architecture in the same style and brevity workshop active body-map-viewer 2026-07-25

How it now works

Written back at Jeroen's request after the final ratifications, in the style and brevity of his original outline; corrected after his Global/Region rung review and the lakes reconciliation.


To honor late/lazy compute, everything is designed around LoD information exposure with two separate eviction axes: nothing is ever stale (determinism — a canvas for a fixed seed is byte-valid forever), but sub-global geometry still gets evicted on time-since-last-visit to save storage for planets you visit once. Only the live sim-state components carry a real TTL: one clock-bucket of the field's own fastest driver (tidal for flooded on moon-bearing bodies, seasonal otherwise) — the map can be at most one bucket stale, and the sim has no fresher answer than that. The global level for each body is always kept (~9 MB for all 267 bodies, PNG-encoded — small enough to simply stay resident in memory) so atlas navigation is snappy after first calc.

architecture:

  • pixel drawing is a function of the client. The map component has two layers: a render-to-texture terrain layer (the data canvas colorized CPU-side — measured cheap, ~78 ns/cell — into texel-exact textures, L8 planes where single-channel) and an unscaled screen-space annotation layer for names, glyphs, rivers-as-lines and markers. There is no zoom-scaled canvas anymore; the entire compensation error class is dead by construction. What is shown and drawn is a map art function, not a data function — the client styles and tweens, but never invents geometry the wire didn't carry.

  • content determination is a server function. The server answers "what is at this world coordinate at this zoom step" with one flat tagged StepCanvasResponse: dense per-gridunit fields (biome/morphology, elevation, temperature, moisture, vegetation, settlement-id — plus frozen and flooded as separately-fetchable short-TTL planes), sparse feature lists (river courses, cliffs — zero-length almost everywhere), and whole-body name lookups joined client-side. PNG-per-field encoding: a full data canvas is ~638 KB, ~5 ms to encode.

  • zoom levels are stepped. The map opens on the body surface — the global view, rung 0: a canvas sized by the body itself (as many regions as the body has, one gridunit per region — the elastic seam made visible), and this is the one canonical, always-kept canvas. Below it, five fixed-size rungs, each pinned to a D-243 unit: Region → District → Quarter → Block → Chunk (64 m, the deepest) — all viewport-sized and evictable, never whole-body. Scroll clicks step through them, cursor-anchored, edge-scroll panning. The bottom-out rule is simply 1 screen px per 64 m gridunit — no magnification margin needed, because a chunk is already a legible map feature. The tile (1 m) level is not map content; walking on tiles is the Phase-5 viewport's job. Display fidelity is step-dependent: 1×1 px per gridunit at the deep steps where detail matters, relaxing toward ~5×5 only at the shallow end where extent is what grows.

  • on opening of a body: the heightmap and inputs are read, the seed generators run the global calculations — including settled hydrology: rivers that end in basins fill lakes to their true spill level, overflow onward to the sea or hold as endorheic when the climate supports it, and carve gorges only where the geometry truly demands it (measured across all 267 real bodies: it never has yet — the cliff fields ship empty but the arithmetic is proven for the body that someday needs them). This all lands in the global canvas: not drawn, but determining what is in each gridunit — and it is kept forever. The lakes it fills draw on the map as water (the existing Lake classification, sourced from the settled solver; lake edges refine with zoom the same way coastlines do), and an endorheic basin reads exactly as it should: a lake with no river leaving it.

  • on zooming a step: the server takes the viewport bounds, derives the step's data canvas at that rung's spacing (~64 ms for a typical canvas, everything measured, worst cases bounded), with each finer step consuming the coarser layers as seed information the deterministic way — reading the continuous primitives and baselines (cache-accelerated when the coarser canvas is resident, derived fresh when not, byte-identical either way). The client colorizes, textures, annotates, and the map simply shows more truth the closer you look.