docs: erosion hierarchy defaults, EROS v2, and where erosion cannot reach (terrain-water task 18)
Records the four governors and the task-18 defaults, and states the measured limit plainly: erosion concentrates ~9x on the curve's shelf risers because that is where sustained slope is, so flat shelves and lowlands are barely touched and the lowland continuation of a trunk is river promotion's job, not erosion's. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cc6a24d2b9
commit
85e7bceb72
2 changed files with 36 additions and 21 deletions
|
|
@ -57,7 +57,7 @@ Every section: `[u32 tag][u64 payload-length in bytes][payload]`.
|
|||
| `TOWN` / `0x4E574F54` | `i32 count`, then per town: `f32 X` · `f32 Y` · `u8 tier` · `u8 isHighwayNode` (0/1) | Tier ordinals from `Enums.cs::TownTier`, append-only, range-checked on read. The highway-node flag is what the generator's road topology was built from (v1 dropped it); carried and exposed on the parsed blueprint, consumed by nothing server-side yet. |
|
||||
| `TCRV` / `0x56524354` | 50 B base: `u16 curveVersion` · `f32 knot1..knot4` · `f32 spikeMax` · `f32 sea` · `f32 orangeCeil` · `f32 redCeil` · `f32 benchLo` · `f32 benchHi` · `f32 peakCap` · `f32 tailSlope`. **When `curveVersion ≥ 4`, a 36 B modulation extension follows:** `f32 benchAmp` · `f32 plateauAmp` · `f32 shelfSpanMin` · `f32 shelfSpanMax` · `f32 elevFreqIslands` · `f32 strengthFreqIslands` · `i32 benchSeedOffset` · `i32 plateauSeedOffset` · `i32 strengthSeedOffset`. **When `curveVersion ≥ 5`, a 9 B preset extension follows:** `u8 presetId` (1 = compact, 2 = balanced) · `f32 k5` · `f32 k6` — with the four base knot slots this makes the effective curve unambiguous from the record alone (record total 95 B; the length-framed section + version byte keep every layout change safe) | Optional — present iff the height-redistribution curve shaped this blueprint's `HGTS` (config `TerrainCurve: "v3"`); absent = raw legacy profile. **The `u16 curveVersion` selects the field semantics and the unserialized anchor set:** v1 — knots t1..t4, spikeMax = pooled calibration max, benchLo/Hi = the 50 m plateau's lo/hi. v2 — as v1 but spikeMax = the seed's effective raw pre-curve maximum (per-seed spike normalizer). v3 — knots = K1..K4 of six (K5 = 0.930304, K6 = 1.050720 are version constants, not serialized), spikeMax per-seed, benchLo/benchHi = the fixed 100 m / 220 m shelves. **v4 (current)** — as v3, but benchLo/benchHi are the shelf **BASE** anchors and the extension record carries the spatial-modulation parameters: shelf elevations vary ±benchAmp/±plateauAmp and shelf strength blends the output span across `[shelfSpanMin, shelfSpanMax]`, via Simplex fields seeded `resolvedWorldSeed + seedOffset` at `freq/MapSize` (frequencies stated in undulations per island width). Because spikeMax is per-seed (v2+), blueprints are not reproducible from curve constants alone — that is why it is recorded. **Metadata only:** exported heights are already curved; nothing re-applies the map. Calibration provenance: `HeightCurve.cs` header + the task-05/06/07 reports. |
|
||||
| `TDTL` / `0x4C544454` | 30 B: `u16 detailVersion` · `f32 reliefAmpM` · `f32 reliefFreqIslands` · `i32 reliefSeedOffset` · `f32 edgeAmpM` · `f32 edgeFreqIslands` · `i32 edgeSeedOffset` · `f32 edgeMaxShiftM` | Optional — present iff the terrain detail passes shaped this blueprint's `HGTS` (config `TerrainDetail: "v1"`, requires the curve). **`detailVersion` selects the body layout and a reader that does not recognise it SKIPS the section** (leaving detail metadata null) rather than misreading a differently shaped payload — the one section whose body is versioned rather than extended, because v1's layout was retired rather than grown. **v1 (retired, never shipped)** — shelf micro-relief + D8 drainage incision, 38 B; the incision produced grid-aligned artifacts and was reverted whole, so the only v1 payloads that exist are in that batch's own tree. **v2 (current)** — shelf micro-relief (±`reliefAmpM` output metres, shelf-ness weighted) + shelf-edge variation: a per-column shift of the curve's shelf/riser knot block K3/K4/K5, drawn from a Simplex field seeded `resolvedWorldSeed + edgeSeedOffset` at `edgeFreqIslands/MapSize`, amplitude ±`edgeAmpM` **metres of INPUT height** — a displacement of the shelf boundary contour, not an elevation change. `edgeAmpM` is recorded **as applied**, after the clamp to `edgeMaxShiftM` (the preset's band-squeeze bound), so the record always describes the terrain rather than the request. **Metadata only** — heights are already detailed. Machinery: `Tools/Scripts/TerrainDetailPass.cs`. |
|
||||
| `EROS` / `0x534F5245` | 58 B: `u16 erosionVersion` · `i32 dropletCount` · `i32 lifetime` · `i32 brushRadius` · `i32 seedOffset` · `f32 carveCapM` · `f32 seaMarginM` · `f32 inertia` · `f32 capacityFactor` · `f32 minSlopeM` · `f32 erodeRate` · `f32 depositRate` · `f32 evaporation` · `f32 gravity` · `f32 craterExclFactor` | Optional — present iff the droplet hydraulic-erosion pass shaped this blueprint's `HGTS` (config `Erosion: "v1"`, terrain-water task 17). **`erosionVersion` selects the body layout; an unrecognised version is SKIPPED whole** (erosion metadata left null), same rule as `TDTL`. **v1 (current)** — the carve-and-deposit droplet model: `dropletCount`/`lifetime`/`carveCapM` are the three hard governors (total droplets, max steps each, max cumulative erosion depth per cell in metres); `seaMarginM` is the flood-guard clamp (no cell carved below sea + margin; below-sea cells untouched entirely, so the rendered coastline cannot move); droplets are deterministic from `resolvedWorldSeed + seedOffset` (PCG32); no cell within `craterExclFactor × CraterRadius` of the impact centre is modified. Strength constants (`inertia`, `capacityFactor`, `minSlopeM`, `erodeRate`, `depositRate`, `evaporation`, `gravity`) are the standard droplet-model dials; slopes/amounts in metres (1 raw = 251 m). All values recorded **as applied** (post config clamping). **Metadata only** — heights are already eroded, and the classify-side sections (`BIOM`/`WBID`/…) never saw the pass by design. Machinery: `Tools/Scripts/HydraulicErosion.cs`. |
|
||||
| `EROS` / `0x534F5245` | 62 B: `u16 erosionVersion` · `i32 dropletCount` · `i32 lifetime` · `i32 brushRadius` · `i32 seedOffset` · `f32 carveCapM` · `f32 depositCapM` · `f32 seaMarginM` · `f32 inertia` · `f32 capacityFactor` · `f32 minSlopeM` · `f32 erodeRate` · `f32 depositRate` · `f32 evaporation` · `f32 gravity` · `f32 craterExclFactor` | Optional — present iff the droplet hydraulic-erosion pass shaped this blueprint's `HGTS` (config `Erosion: "v1"`, terrain-water tasks 17–18). **`erosionVersion` selects the body layout; an unrecognised version is SKIPPED whole** (erosion metadata left null), same rule as `TDTL`. **v1 (task 17, superseded)** — 58 B, no `depositCapM`; deposition was bilinear over 4 cells and unbounded, which built isolated cones (measured 15.5 m). The only v1 payloads in existence are in that task's batch tree. **v2 (task 18, current)** — deposition is spread over the same cone brush as carving and bounded per cell by `depositCapM` (`<= 0` = unbounded, the reference model). The FOUR governors are `dropletCount`/`lifetime`/`carveCapM`/`depositCapM`; both caps are enforced against one per-cell NET displacement ledger (positive = carved below the height the pass found, negative = built up above it) and asserted on exit. `seaMarginM` is the flood-guard clamp — no cell is carved below sea + margin, and below-sea cells are untouched in BOTH directions, so the rendered coastline cannot move. Droplets are deterministic from `resolvedWorldSeed + seedOffset` (PCG32); no cell within `craterExclFactor × CraterRadius` of the impact centre is modified. Remaining fields are the droplet-model strength dials; slopes/amounts in metres (1 raw = 251 m). All values recorded **as applied** (post config clamping). **Metadata only** — heights are already eroded, and the classify-side sections (`BIOM`/`WBID`/…) never saw the pass by design. Machinery: `Tools/Scripts/HydraulicErosion.cs`. |
|
||||
| `WBID` / `0x44494257` | `MapSize²` × `u16` water-body id, same pixel order as `HGTS` | Optional (absent = no water data, e.g. a legacy re-encode). `0` = no water, `1` = **the** ocean body, `2..N` = lakes. Ids assigned in deterministic scan order (X outer / Y inner, first-encountered pixel), lakes labeled with the **same 4-connectivity as `CalculateTrueOcean`**. Membership is exactly the generator's water classification — the biome grid's Ocean/Lake pixels and this grid's nonzero pixels are the same set **by construction** (shared predicates). Length must equal `2·MapSize²`. |
|
||||
| `WBTB` / `0x42544257` | `i32 count`, then per body (20 B): `u16 id` · `u8 type` (0 ocean, 1 lake) · `u8 salinity` (0 fresh, 1 salt) · `f32 surfaceLevel` · `i32 pixelCount` · `f32 centroidX` · `f32 centroidY` | Optional, paired with `WBID`. **`surfaceLevel` is a documented TRANSITIONAL rule:** one flat level per body — `GetSeaLevel` at the body's pixel centroid (ocean: at the map centre) under the still-live latitude field; superseded by the flat-scalar sea model (minted, lands with the coast change set). The field's per-pixel slope is deliberately NOT baked into any section. **Salinity is a provisional default** (ocean salt, lake fresh) — a placeholder for the future fresh/salt irrigation mechanic, not a mechanic. |
|
||||
| `WSRF` / `0x46525357` | `MapSize²` × `u16` quantized water-surface elevation, same pixel order | Optional, paired with `WBID`. `0` is the reserved **no-water sentinel**; a real level `L` (raw height units) encodes as `1 + round(L × 32768)` so it can never encode to 0; decode `(q − 1)/32768` (`BlueprintFormat.EncodeWaterLevel`/`DecodeWaterLevel`). Covers `[0 … ~1.99997]` raw at `1/32768` raw ≈ **7.7 mm** of world height (1 raw = 251 m) — far finer than the 1 m voxel. Nonzero exactly where `WBID` is nonzero; the value is the pixel's body level. |
|
||||
|
|
@ -123,14 +123,18 @@ body).
|
|||
follow the curved terrain. When on, `TCRV` records the effective parameters including the
|
||||
per-seed `spikeMax`.
|
||||
- **`Erosion`** (`"v1"` | `"off"`, default `"off"` — opt-in until the developer's gate approves
|
||||
it) — the task-17 droplet hydraulic-erosion pass: carve-and-deposit drainage detailing of
|
||||
`HGTS` after the detail passes and before the crater carve. Governor dials
|
||||
(`ErosionDropletCount` / `ErosionDropletLifetime` / `ErosionCarveCap`, defaults 400 000 / 48 /
|
||||
8 m; bounds clamped loudly at load) plus the sea-clamp margin and strength constants — the
|
||||
full dial list and semantics live in the `EROS` row above and `ConfigManager.cs`. Output-height
|
||||
only: the classify path reads pre-erosion heights, so `BIOM` and every water section stay
|
||||
bit-identical with erosion on or off, and the sea clamp keeps even the RENDERED coastline
|
||||
fixed. When on, `EROS` records the parameters as applied.
|
||||
it) — the droplet hydraulic-erosion pass (tasks 17–18): carve-and-deposit drainage detailing of
|
||||
`HGTS` after the detail passes and before the crater carve. FOUR governor dials
|
||||
(`ErosionDropletCount` / `ErosionDropletLifetime` / `ErosionCarveCap` / `ErosionDepositCap`,
|
||||
defaults 250 000 / 384 / 15 m / 6 m; bounds clamped loudly at load) plus the sea-clamp margin
|
||||
and strength constants — the full dial list and semantics live in the `EROS` row above and
|
||||
`ConfigManager.cs`. The task-18 defaults tune for a drainage HIERARCHY: droplets live long
|
||||
enough (384 steps at inertia 0.35) for their paths to overlap and deepen shared low lines into
|
||||
trunk channels rather than dying as short independent scratches, and the raised carve cap lets
|
||||
those trunks separate from the fine rills instead of both piling against one ceiling.
|
||||
Output-height only: the classify path reads pre-erosion heights, so `BIOM` and every water
|
||||
section stay bit-identical with erosion on or off, and the sea clamp keeps even the RENDERED
|
||||
coastline fixed. When on, `EROS` records the parameters as applied.
|
||||
|
||||
- **`CoastProfile`** (`"wide"` | `"steep"`, default `"wide"`) — the submarine shelf. The height
|
||||
curve is identity at and below sea level, so it never reshaped the seabed; `"wide"` compresses
|
||||
|
|
|
|||
|
|
@ -43,22 +43,33 @@ Generates the entire 2D blueprint. Roughly in order:
|
|||
bit-identical to an unwarped one outside the shelf/riser stack. Drops the `0_height` hillshade
|
||||
snapshot (hypsometric bands × NW hillshade) in both modes.
|
||||
|
||||
**Erosion (task 17, Phase C0)** — with `Erosion: "v1"` (default **"off"**, opt-in until the
|
||||
**Erosion (tasks 17–18, Phase C0)** — with `Erosion: "v1"` (default **"off"**, opt-in until the
|
||||
developer's gate approves it) a droplet-based hydraulic erosion pass (`HydraulicErosion.cs`,
|
||||
standalone numeric, deterministic from the resolved seed) details the curved+detailed render
|
||||
map after the detail passes and before the crater carve: droplets walk downhill with inertia,
|
||||
eroding steep fast stretches over a small brush and depositing where the ground flattens —
|
||||
organic, sinuous drainage, not grid hatching. Three hard governors bound it
|
||||
(`ErosionDropletCount`/`ErosionDropletLifetime`/`ErosionCarveCap` — the cap is per-cell, in
|
||||
metres, ledger-enforced), a sea clamp forbids carving below sea + margin and leaves below-sea
|
||||
cells untouched entirely (the rendered coastline cannot move — asserted every generation), and
|
||||
nothing within 1.2× the crater radius is modified. Output-height only: biome/water
|
||||
eroding steep fast stretches and depositing where the ground flattens — both spread over the
|
||||
same cone brush, so neither carving nor dumping can spike a single cell. **Four** hard
|
||||
governors bound it (`ErosionDropletCount`/`ErosionDropletLifetime`/`ErosionCarveCap`/
|
||||
`ErosionDepositCap`; both caps are per-cell metres against one net-displacement ledger and are
|
||||
asserted on exit), a sea clamp forbids carving below sea + margin and leaves below-sea cells
|
||||
untouched in both directions (the rendered coastline cannot move — asserted every generation),
|
||||
and nothing within 1.2× the crater radius is modified. Output-height only: biome/water
|
||||
classification reads the retained pre-erosion map, so `1_biomes`/`0_water` are bit-identical
|
||||
with erosion on or off. **No rivers yet** — the carved channels are the designated future river
|
||||
routes (Phase C0b promotes them). The predecessor D8 drainage-incision pass was written and
|
||||
reverted in task 10 — per-cell steepest descent on a regular grid can only route along eight
|
||||
headings, and at map scale that reads as straight hatching, not drainage; the droplet model is
|
||||
the working replacement.
|
||||
with erosion on or off.
|
||||
The task-18 defaults tune for a drainage **hierarchy** — fine rills everywhere feeding a set of
|
||||
clearly deeper convergent channels — by letting droplets live long enough (384 steps at inertia
|
||||
0.35, low evaporation) that their paths overlap and deepen shared low lines, and by raising the
|
||||
carve cap to 15 m so trunks separate from rills instead of both piling against one ceiling.
|
||||
Measured on seed 1280587109: ~1.9 M cells carved past 0.5 m, 42 k past 5 m, 1.4 k past 10 m,
|
||||
and 177 connected channel systems of 200+ cells at the 3 m threshold. Erosion concentrates
|
||||
~9× on the curve's shelf risers, because that is where sustained slope exists; the flat
|
||||
shelves and lowlands are barely touched, so **the lowland continuation of a trunk is not
|
||||
erosion's to cut** — that is river promotion's job. **No rivers yet** — the carved channels are
|
||||
the designated future river routes (Phase C0b promotes them by flow accumulation).
|
||||
The predecessor D8 drainage-incision pass was written and reverted in task 10 — per-cell
|
||||
steepest descent on a regular grid can only route along eight headings, and at map scale that
|
||||
reads as straight hatching, not drainage; the droplet model is the working replacement (its
|
||||
carve field measures isotropic to within 1.5 % across the folded 45° grid period).
|
||||
3. **Sea level and water** — sea level per the configured model (`SeaLevelModel`: `"flat"` scalar
|
||||
— the default, `SeaLevelValue` 0.15 — or the legacy `"field"` latitude Lerp); flood fill
|
||||
separates true ocean from inland lakes; a mainland fill guarantees one contiguous landmass.
|
||||
|
|
|
|||
Loading…
Reference in a new issue