tower / cascadia / files / src / views / raster.ts
Branch cascadia · default branch · all branches
raster.ts
5a57ebae 2026-09-07 Pavel Safronov | 1 | /** |
| 2 | * Metadata for the rasters `npm run terrain` writes into static/. | |
| 3 | * | |
| 4 | * These must match the `render` block of content/geography.json — the generator | |
| 5 | * reads that file, the browser only ever sees the PNGs, and nothing in between | |
| 6 | * carries the numbers across. test/raster.test.ts asserts the two agree, because | |
| 7 | * a silent disagreement here would displace the terrain rather than break it, and | |
| 8 | * that failure mode has already cost this project once (D-024). | |
| 9 | */ | |
| 10 | export const RASTER_WIDTH = 2048 | |
| 11 | export const RASTER_HEIGHT = 1192 | |
| 12 | /** | |
| 13 | * The working range terrain-height.png is stretched across: black is the floor of | |
| 14 | * it, white the ceiling. It is deliberately not a round number and not anchored at | |
| 15 | * zero — it only has to cover the terrain that exists, and the tighter it is the | |
| 16 | * finer every step in it. Below zero is real: lake and sea floors are cut beneath | |
| 17 | * the datum, and the old fixed 0..5,000 m encoding clipped them flat. | |
| 18 | */ | |
9a621732 2026-09-08 Pavel Safronov | 19 | export const RASTER_MIN_HEIGHT_M = -560 |
5a57ebae 2026-09-07 Pavel Safronov | 20 | export const RASTER_MAX_HEIGHT_M = 4400 |
| 21 | export const RASTER_HEIGHT_SPAN_M = RASTER_MAX_HEIGHT_M - RASTER_MIN_HEIGHT_M | |
| 22 | ||
| 23 | export const COLOR_RASTER = 'terrain-color.png' | |
| 24 | export const HEIGHT_RASTER = 'terrain-height.png' | |
1affced2 2026-09-08 Pavel Safronov | 25 | |
| 26 | /** | |
| 27 | * Which surface the rasters describe. | |
| 28 | * | |
| 29 | * `canon` is Tower: authored geography, generated by `npm run terrain` from | |
| 30 | * content/geography.json. `cascadia` is **not Tower** — it is the Pacific | |
| 31 | * Northwest at 1:1, laid on the same cylinder because the ground from the Pacific | |
| 32 | * surf east to the Columbia is 312.8 km and Tower's circumference is 314.2, so the | |
| 33 | * real coast closes the ring on real terrain. It exists as a ruler, to answer "how | |
| 34 | * big is this actually", and it carries no Tower geography whatsoever. See D-055. | |
| 35 | */ | |
| 36 | export type Surface = 'canon' | 'cascadia' | |
| 37 | ||
| 38 | export const isSurface = (v: unknown): v is Surface => v === 'canon' || v === 'cascadia' | |
| 39 | ||
| 40 | /** | |
| 41 | * The two rasters for a surface. | |
| 42 | * | |
| 43 | * Every surface shares RASTER_WIDTH, RASTER_HEIGHT and the height window above — | |
| 44 | * that is not a coincidence to be relied on quietly but a requirement, because the | |
| 45 | * interior view bakes the window into its GLSL as literals and would otherwise | |
| 46 | * need one shader per surface. test/raster.test.ts holds the generators to it. | |
| 47 | */ | |
| 48 | export function rasterSet(surface: Surface): { color: string; height: string } { | |
| 49 | return surface === 'cascadia' | |
| 50 | ? { color: 'cascadia-color.png', height: 'cascadia-height.png' } | |
| 51 | : { color: COLOR_RASTER, height: HEIGHT_RASTER } | |
| 52 | } |