tower / files / src / ui / scales.ts
scales.ts
7cc177f6 2026-09-07 Pavel Safronov | 1 | /** |
| 2 | * Slider mappings shared by the panel and the views. | |
| 3 | * | |
| 4 | * This lives outside views/ on purpose: the panel needs the eye-height scale to | |
| 5 | * label its slider before the interior view exists, and importing the view for it | |
| 6 | * would statically pull Three.js into the entry chunk — the exact regression | |
| 7 | * D-021 fixed for the exterior. | |
| 8 | */ | |
| 9 | ||
| 10 | /** Standing eye height. */ | |
| 11 | export const EYE_MIN_M = 1.7 | |
3e898b51 2026-09-28 Pavel Safronov | 12 | import { BEAM_RADIUS_M, RADIUS_M } from '../canon/constants.js' |
| 13 | ||
| 14 | /** | |
| 15 | * The edge of the beam, above the datum: as high as anyone can go (D-084). The whole world | |
| 16 | * seen as a tube from inside its air (world-generation.md §6.4), with the beam filling the | |
| 17 | * sky overhead. It was 45 km, 3.4 km short of it, until the author asked for the beam to be | |
| 18 | * the top of the eye-height gauge. The interior stops you a little short of it, over | |
| 19 | * whatever ground you are above. | |
| 20 | */ | |
| 21 | export const EYE_MAX_M = RADIUS_M - BEAM_RADIUS_M | |
7cc177f6 2026-09-07 Pavel Safronov | 22 | |
| 23 | /** Eye height from a 0..1 slider position. Logarithmic, so 1.7 m is reachable. */ | |
| 24 | export const eyeHeightFromSlider = (v: number): number => | |
| 25 | EYE_MIN_M * (EYE_MAX_M / EYE_MIN_M) ** Math.min(1, Math.max(0, v)) | |
| 26 | ||
| 27 | export const sliderFromEyeHeight = (h: number): number => | |
| 28 | Math.log(Math.max(EYE_MIN_M, h) / EYE_MIN_M) / Math.log(EYE_MAX_M / EYE_MIN_M) |