Procedural Generation
A planet-scale hexagonal grid engine with adaptive level-of-detail refinement, Perlin noise terrain, and a trait-based simulation system — designed for deterministic, networked ecosystem simulation.
- Rust
- Bevy
- ECS
- H3
- Procedural Generation
H3 Hexagonal Grid
The planet surface is partitioned using Uber's H3 hierarchical hexagonal grid system. Unlike square or triangular grids, H3's hexagons have uniform neighbour distances and no pole singularities — every cell on the sphere has the same geometric relationship to its neighbours. The hierarchy runs from resolution 0 (122 base cells covering the globe) up to resolution 15 (sub-metre cells), where each hex subdivides into 7 children.
Adaptive LOD Refinement
Cell resolution is managed dynamically based on camera proximity. Cells
near the camera are in Refining state — they spawn their 7 children and despawn themselves. Cells the
camera moves away from enter Coarsening state — their parent is respawned and they are removed. The transition
is driven by Bevy ECS systems on a custom SimulationUpdate schedule that runs independently of the render loop.
The result is a globe that renders only as much geometry as the current viewpoint demands — a low-resolution wireframe from orbit that resolves to fine-grained detail on the ground without ever loading the full grid into memory.
Terrain
Terrain height is sampled using multi-octave Perlin noise from the noise crate. Each H3 cell's geographic centroid is converted to lat/lng
coordinates, which are fed into the noise function to produce a stable,
deterministic height value. Higher octaves add fine surface detail without
altering coarse topology — this means the terrain is consistent regardless
of which resolution level samples it.
Trait-Based Simulation System
Simulation logic is plugged in via a Simulation trait. Each implementation receives a cell's current state and its
neighbours' states and returns an updated state. This keeps the simulation
logic completely decoupled from the grid management code — swapping in a
different ecosystem model is a one-line change.
When the LOD changes, simulation data is preserved through an aggregate/subdivide pattern: child cells inherit subdivided values from their parent, and when cells coarsen, children aggregate back up to produce a consistent parent state. No simulation history is lost across resolution transitions.
Determinism
Every system that touches simulation state is audited for determinism.
HashMaps have been replaced with BTreeMaps where iteration order matters.
Bevy query ordering is explicitly controlled via system ordering constraints.
A DETERMINISM_ANALYSIS.md tracks every known nondeterministic pattern and its resolution status —
floating-point variance, query iteration order, and hash randomisation
are each addressed individually.