fuzzyworld

tower / cascadia / files / src / views / raster.ts

Branch cascadia · default branch · all branches

raster.ts

2.4 KB · history · blame

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 */
10export const RASTER_WIDTH = 2048
11export 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 */
19export const RASTER_MIN_HEIGHT_M = -560
20export const RASTER_MAX_HEIGHT_M = 4400
21export const RASTER_HEIGHT_SPAN_M = RASTER_MAX_HEIGHT_M - RASTER_MIN_HEIGHT_M
22
23export const COLOR_RASTER = 'terrain-color.png'
24export const HEIGHT_RASTER = 'terrain-height.png'
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 */
36export type Surface = 'canon' | 'cascadia'
37
38export 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 */
48export 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}