docs: the two-clause water presence rule (terrain-water task 15)

Server/README.md: why water presence is not just WBID. Records the
classify-vs-render identity that makes the second clause both necessary
(inside the crater carve) and safe (provably inert everywhere else), so
the next reader does not have to re-derive it from the commit log — or,
worse, "simplify" the second clause away.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stewart Howe 2026-08-10 00:57:05 -04:00
parent 69bf91b3d6
commit b9c7675e78

View file

@ -27,11 +27,20 @@ vector ends up parallel to the view direction, so camera roll is undefined and G
- **Road culling first.** Only the road segments whose bounding box reaches this chunk are kept,
each tagged with its `RoadTier`. The padding is derived from the widest shoulder any tier has plus
a margin, so widening a road cannot silently truncate it at chunk edges.
- **Water per column** (task 13) — the blueprint is the **authority** on where water is; the server
only reads it. `WBID` decides presence (it is the water stage's own classification output, the
same set the biome grid's Ocean/Lake pixels form by construction), `WSRF` gives the surface level
per pixel, and the `WBTB` body table is the fallback when a column is flagged wet but carries the
`WSRF` no-water sentinel. A body the table does not know leaves the column **dry** rather than
- **Water per column** (tasks 13, 15) — the blueprint is the **authority** on where water is and at
what level; the server only reads it. `WSRF` gives the surface level per pixel, and the `WBTB`
body table is the fallback when a column is flagged wet but carries the `WSRF` no-water sentinel.
**Presence takes two clauses.** `WBID` (the water stage's own classification output) OR *the
rendered ground being under the ocean's surface*. The second exists because `WBID` was classified
from the **uncurved** heightmap while the mesh renders the **curved** one. Outside the crater
those agree exactly — the curve is identity at sea and monotonic, so `Apply(raw) < sea` iff
`raw < sea`. Inside it they do not: the carve lerps two different bases toward one target
(classify from `raw`, rendered from `Apply(raw)`, and `Apply(raw) < raw` in the lowland band), so
the rendered surface sinks faster and leaves a ring rendering below the waterline that `WBID`
still calls dry — 375,824 px on the C1 seed, all of it inside the carve. The second clause tests
the height the mesh actually uses against the **ocean body's own level from `WBTB`**, so the
runtime still derives nothing, and by the identity above it can only ever fire inside the carve. A body the table does not know leaves the column **dry** rather than
guessing a level. The level is scaled by the same `HEIGHT_SCALE` as the terrain, so the sheet and
the seabed cannot drift apart. Depth for shading is taken from **blueprint** heights, not rendered
geometry — the terrain render clamps its floor at `Y = 2`, which would otherwise flatten every