code wiki / (root) / nx_terrain_erode_lib.nx

nx_terrain_erode_lib.nx

buildroot/runtime/nx_terrain_erode_lib.nx

8548 B164 linesdepth 3pulls 3 transitivereach 12 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_terrain_erode_lib.nx -- TERRAIN-SCALE EROSION COMPOSITION + ITS REFEREE (PG20, procgen.plan). WHY THIS LIB EXISTS. nx_water_erosion.nx ships all seven Mei 2007 stages and is gate-proven (nx_water_erosion_gate, PG18) -- and the ranker measured it LIB-UNIMPORTED: nothing in the estate composed it. PG20's contract is that composition onto a terrain heightfield, plus the thermal-talus companion Musgrave 1989 pairs with hydraulic erosion, plus the referee that decides whether the result reads as terrain rather than as blobs. THREE THINGS LIVE HERE AND NOTHING ELSE: 1. te_thermal_pass -- THE ONE TALUS PASS IN THE ESTATE. nx_pets_voxel3d.vp_erode_pass already implemented the voxel form (shed exactly one unit to every 4-neighbour overhung by more than talus, mass-conserving by construction). That is a real lower-layer kernel and it is NOT deleted: this function GENERALISES it by one parameter and REPRODUCES it exactly at flux_q14 == 0, which is what makes retiring the private copy onto this owner provable rather than asserted. flux_q14 > 0 selects the Musgrave proportional law that a continuous heightfield needs, where a fixed one-unit shed would be a voxel quantum applied to a quantity that has no voxels. INDEX ORDER IS NOT A CONVENTION HERE, IT IS A PROVEN PROPERTY. vp_erode_pass indexes x*gn+z and nx_water_erosion indexes y*w+x. On a square grid the four neighbours of cell k are k-1, k+1, k-gn, k+gn under BOTH, the boundary guards map onto each other exactly, and the deltas are accumulated additively from the pre-pass state -- so the two orders produce byte-identical output. The gate asserts that against a reference written in the other order rather than leaving it as a comment nobody can check. 2. te_hypsometric_permil -- THE REFEREE. Strahler's hypsometric integral, (mean - min) / (max - min), in permille. It is the right referee for a procedural world for a reason that is decidable before any measurement is taken: IT IS DIMENSIONLESS. The plan named two published bands, hypsometric curve and DRAINAGE DENSITY -- and drainage density is kilometres of channel per square kilometre, so quoting a published band for it against a world with no metric scale binding would be a number about a subject we do not have. That half is declared open by name in the gate, not half-measured. The integral is invariant under h -> a*h + b for a > 0, which is exactly what makes it non-gameable: an implementation that merely lowers the terrain, or flattens it, or adds noise, moves it NOWHERE. Only moving mass from highs into lows moves it, and that is erosion. A flat field has no hypsometry, so this ABSTAINS with -1 rather than returning a number. 3. te_erode_grid -- the composed loop: seed the Mei state from a caller-owned height grid, tick the full seven-stage pipeline, interleave the talus pass, read the bed back. Every buffer is caller-owned and sized by te_state_bytes / te_grid_bytes, so there is no cap to guess and no

dependencies 3 imports · 1 importers

nx_syscalls.nx nx_tier.nx nx_water_erosion.nx nx_terrain_erode_lib.nx nx_worldpipe.nx

imports: nx_syscalls.nxnx_tier.nxnx_water_erosion.nx

imported by: nx_worldpipe.nx

structs

none

consts

57const TE_PERMIL: i64 = 1000
59const TE_HYPSO_UNOBSERVABLE: i64 = 0 - 1

functions

62func te_state_bytes(gn: i64) -> i64 { return gn * gn * NX_WATER_STRIDE * NX_SIZEOF_NX_INT }
63func te_grid_bytes(gn: i64) -> i64 { return gn * gn * NX_SIZEOF_NX_INT }
70func te_shed(hg: *i64, delta: *i64, src: i64, dst: i64, h: i64, talus: i64, flux_q14: i64) -> i64
called by 1: te_thermal_pass
85func te_thermal_pass(hg: *i64, gn: i64, talus: i64, flux_q14: i64, delta: *i64) -> i64
called by 1: te_erode_grid calls 1: te_shed
113func te_hypsometric_permil(hg: *i64, n: i64) -> i64
132func te_seed_bed(state: *i64, hg: *i64, n: i64) -> i64
called by 1: te_erode_grid
137func te_read_bed(state: *i64, hg: *i64, n: i64) -> i64
called by 1: te_erode_grid
148func te_erode_grid(hg: *i64, gn: i64, ticks: i64, rain_q14: i64, talus: i64, flux_q14: i64,