nx_water_erosion.nx
buildroot/runtime/nx_water_erosion.nx
about
nx_water_erosion.nx -- full Mei 2007 hydraulic erosion simulation.
Mei, Decaudin, Hu 2007: "Fast Hydraulic Erosion Simulation and
Visualization on GPU". Full implementation per cardinal
`feedback-maximum-capability-no-simplification`: this primitive
ships the entire shallow-water + sediment-transport algorithm,
not a slope-magnitude approximation.
Algorithm (Mei 2007 sections 3.1 - 3.5):
STAGE 1 -- WATER INCREMENT (rain)
d(t+dt) += dt * r_t where r_t = rain rate per cell
STAGE 2 -- FLOW SIMULATION (pipe model)
For each cell + each cardinal direction X:
f_X(t+dt) = max(0, f_X(t) + dt * A * g * dh_X / L)
where dh_X = h(this) + d(this) - h(neighbour_X) - d(neighbour_X),
A = pipe cross-section, L = pipe length, g = gravity.
Outflow scaling: if total_outflow * dt > available_water * cell_area,
scale all 4 outflows by min(1, available_water * cell_area /
(total_outflow * dt)).
STAGE 3 -- WATER UPDATE (mass conservation)
d(t+dt) = d(t) + dt * (total_inflow - total_outflow) / cell_area
STAGE 4 -- VELOCITY FIELD
delta_W_x = (f_R(left_neighbour) - f_L(this) + f_R(this) - f_L(right_neighbour)) / 2
u = delta_W_x / (cell_size * d_avg) (similar for v, y axis)
STAGE 5 -- EROSION + DEPOSITION
C = K_c * |sin(local_tilt)| * |velocity| (sediment capacity)
if C > s: erode -> h -= K_s * (C - s); s += K_s * (C - s)
if C < s: deposit -> h += K_d * (s - C); s -= K_d * (s - C)
STAGE 6 -- SEDIMENT TRANSPORT (semi-Lagrangian)
s_new(x, y) = s_old(x - u*dt, y - v*dt) -- bilinear interp
STAGE 7 -- EVAPORATION
d(t+dt) = d(t) * (1 - K_e * dt)
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_tier.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
| 79 | const NX_MAGIC_2000: i64 = 2000 |
| 82 | const NX_WATER_Q: nx_int = 16384 |
| 86 | const NX_WATER_STRIDE: nx_int = 9 |
| 87 | const NX_WATER_OFF_H: nx_int = 0 // terrain height (signed metres, Q14) |
| 88 | const NX_WATER_OFF_D: nx_int = 1 // water depth (metres, Q14) |
| 89 | const NX_WATER_OFF_S: nx_int = 2 // suspended sediment depth (metres, Q14) |
| 90 | const NX_WATER_OFF_FL: nx_int = 3 // outflow flux LEFT (m^3/s, Q14) |
| 91 | const NX_WATER_OFF_FR: nx_int = 4 // outflow flux RIGHT |
| 92 | const NX_WATER_OFF_FT: nx_int = 5 // outflow flux TOP (lower y) |
| 93 | const NX_WATER_OFF_FB: nx_int = 6 // outflow flux BOTTOM (higher y) |
| 94 | const NX_WATER_OFF_U: nx_int = 7 // x-velocity (m/s, Q14) |
| 95 | const NX_WATER_OFF_V: nx_int = 8 // y-velocity (m/s, Q14) |
| 101 | const NX_WATER_DEFAULT_GRAVITY: nx_int = 160760 // 9.81 m/s^2 |
| 102 | const NX_WATER_DEFAULT_PIPE_AREA: nx_int = 16384 // 1.0 m^2 |
| 103 | const NX_WATER_DEFAULT_PIPE_LENGTH: nx_int = 16384 // 1.0 m |
| 104 | const NX_WATER_DEFAULT_DT: nx_int = 1638 // 0.1 seconds per tick |
| 105 | const NX_WATER_DEFAULT_K_CAPACITY: nx_int = 1638 // 0.1 (Mei's K_c) |
| 106 | const NX_WATER_DEFAULT_K_SOIL: nx_int = 4915 // 0.3 |
| 107 | const NX_WATER_DEFAULT_K_DEPOSIT: nx_int = 4915 // 0.3 |
| 108 | const NX_WATER_DEFAULT_K_EVAP: nx_int = 164 // 0.01 |
| 109 | const NX_WATER_DEFAULT_CELL_SIZE: nx_int = 16384 // 1.0 m grid cell |
| 112 | const NX_WATER_PARAM_COUNT: nx_int = 9 |
| 113 | const NX_WATER_PARAM_GRAVITY: nx_int = 0 |
| 114 | const NX_WATER_PARAM_PIPE_AREA: nx_int = 1 |
| 115 | const NX_WATER_PARAM_PIPE_LENGTH: nx_int = 2 |
| 116 | const NX_WATER_PARAM_DT: nx_int = 3 |
| 117 | const NX_WATER_PARAM_K_CAPACITY: nx_int = 4 |
| 118 | const NX_WATER_PARAM_K_SOIL: nx_int = 5 |
| 119 | const NX_WATER_PARAM_K_DEPOSIT: nx_int = 6 |
| 120 | const NX_WATER_PARAM_K_EVAP: nx_int = 7 |
| 121 | const NX_WATER_PARAM_CELL_SIZE: nx_int = 8 |
| 124 | const NX_WATER_MODE_GENTLE_WEATHERING: nx_int = 0 |
| 125 | const NX_WATER_MODE_RIVERINE: nx_int = 1 |
| 126 | const NX_WATER_MODE_FLASH_FLOOD: nx_int = 2 |
| 127 | const NX_WATER_MODE_SUSTAINED: nx_int = 3 |
| 129 | const NX_WATER_MODE_COUNT: nx_int = 4 |
functions
| 131 | func nx_water_mode_is_valid(m: nx_int) -> nx_int |
| 140 | func nx_water_mode_params(mode: nx_int, out: *i64) called by 1: nx_water_erosion_delta |
| 163 | func nx_water_erosion_params_default(params: *i64) called by 1: main |
| 176 | func _w_cell_base(x: nx_int, y: nx_int, width: nx_int) -> nx_int |
| 183 | func nx_water_erosion_init(state: *i64, width: nx_int, gridh: nx_int) called by 1: main |
| 202 | func nx_water_erosion_add_rain( |
| 219 | func nx_water_erosion_compute_flow( |
| 321 | func nx_water_erosion_update_water_and_velocity( |
| 417 | func nx_water_erosion_terrain_update( |
| 509 | func nx_water_erosion_transport( |
| 573 | func nx_water_erosion_evaporate( |
| 594 | func nx_water_erosion_tick( |
| 614 | func nx_water_erosion_delta( |
| 632 | func nx_water_slope_at( called by 1: nx_water_erosion_at |
| 664 | func nx_water_erosion_at( |
| 677 | func main() -> i64 |