nx_river_carve.nx
buildroot/runtime/nx_river_carve.nx
about
nx_river_carve.nx -- specialized river generator (NOT FBM noise).
Second demonstration of the kind-specific-generator cardinal
`feedback-kind-specific-generators-not-broad-noise`. Rivers have
INTERNAL LOGIC -- meandering polyline paths, downstream widening,
banks with depth ramp, river-stage sealed enum -- none of which is
FBM noise.
River-internal logic in v1:
- Polyline path with N control points -- caller can pre-supply
real-river data OR call nx_river_generate_path() to procgen
a meandering sinuous line via hash-perturbed random walk.
- 4 river types (HEADWATERS / MIDDLE / LOWER / DELTA) with
characteristic width + bank profile + meander tightness.
- Downstream widening: river gets wider as it flows (caller
parameterises via per-segment width or uses the type-default).
- Banks: linear ramp from full depth at channel axis to 0 at
bank_width. Caller composes the carve depth into their base
heightmap by subtraction.
- Closest-point-on-polyline lookup -- iterates segments, finds
min squared distance to any segment's line, returns the carve
depth at that distance (parabolic falloff within the river +
bank zone, 0 outside).
FULL CAPABILITY (per feedback-maximum-capability-no-simplification
cardinal, 2026-05-16):
- True sin/cos meandering via nx_camera_sin/cos_q14_centideg
(replaces 8-octant axis-aligned approximation; rivers now bend
at arbitrary angles, not just multiples of 45°)
- Oxbow lake detection + carving: scans for meander segments that
loop back near themselves, marks the enclosed pinch-off as a
stagnant water carve (no flow, full depth)
- Delta braiding: for NX_RIVER_TYPE_DELTA paths,
nx_river_generate_delta produces N branching channels fanning
from the upstream point to spread-targets at the terminus
Loss audit: Q14 integer arithmetic; squared-distance compare avoids
sqrt for the per-pixel hot path. Hash-deterministic meander
generation (Park-Miller LCG), no randomness leak. Genevaux 2013
drainage-graph integration NOT implemented here (the upgrade path
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_tier.nxnx_camera_q14.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 69 | const NX_MAGIC_4096: i64 = 4096 |
| 70 | const NX_MAGIC_6144: i64 = 6144 |
| 71 | const NX_MAGIC_5120: i64 = 5120 |
| 72 | const NX_MAGIC_3125: i64 = 3125 |
| 73 | const NX_MAGIC_3072: i64 = 3072 |
| 74 | const NX_MAGIC_1875: i64 = 1875 |
| 75 | const NX_MAGIC_2654435761: i64 = 2654435761 |
| 76 | const NX_MAGIC_1597334677: i64 = 1597334677 |
| 77 | const NX_MAGIC_4500: i64 = 4500 |
| 78 | const NX_MAGIC_18000: i64 = 18000 |
| 79 | const NX_MAGIC_9000: i64 = 9000 |
| 80 | const NX_MAGIC_5730: i64 = 5730 |
| 81 | const NX_MAGIC_5000: i64 = 5000 |
| 84 | const NX_RIVER_Q: nx_int = 16384 |
| 87 | const NX_RIVER_LCG_A: nx_int = 48271 |
| 88 | const NX_RIVER_LCG_M: nx_int = 2147483647 |
| 91 | const NX_RIVER_POINT_STRIDE: nx_int = 2 |
| 94 | const NX_RIVER_NO_CARVE: nx_int = 0 |
| 99 | const NX_RIVER_TYPE_HEADWATERS: nx_int = 0 // narrow + steep, tight bends |
| 100 | const NX_RIVER_TYPE_MIDDLE: nx_int = 1 // moderate width + meanders |
| 101 | const NX_RIVER_TYPE_LOWER: nx_int = 2 // wide + slow + lazy oxbows |
| 102 | const NX_RIVER_TYPE_DELTA: nx_int = 3 // braided + multiple channels at terminus |
| 104 | const NX_RIVER_TYPE_COUNT: nx_int = 4 |
functions
| 107 | func nx_river_type_is_valid(t: nx_int) -> nx_int |
| 126 | func nx_river_type_params(t: nx_int, out: *i64) |
| 160 | func _river_hash(seed: nx_int, i: nx_int, axis: nx_int) -> nx_int called by 1: nx_river_generate_path |
| 170 | func _river_signed_q14(h: nx_int) -> nx_int called by 1: nx_river_generate_path |
| 189 | func nx_river_generate_path( |
| 295 | func nx_river_detect_oxbows( called by 1: main |
| 345 | func nx_river_oxbow_carve_at( called by 1: main |
| 383 | func nx_river_generate_delta( |
| 432 | func _river_dist_sq_to_segment_2d( called by 1: nx_river_carve_at |
| 469 | func nx_river_carve_at( |
| 521 | func main() -> i64 |