feat: add optional GeoTIFF importer #10
@@ -0,0 +1,167 @@
|
||||
# Terrain Generation Roadmap
|
||||
|
||||
## Purpose
|
||||
|
||||
Define the next terrain-generation workstream so future slices stay small, deterministic, and testable. This plan is intentionally clean-room: it uses only project-owned synthetic fixtures and open math/algorithm ideas, never proprietary VistaPro material.
|
||||
|
||||
## Current baseline
|
||||
|
||||
OpenVistaPro already has:
|
||||
|
||||
- `src/terrain.rs` with immutable `HeightGrid` storage, safe indexing, min/max, and deterministic `plane` / `radial_hill` fixtures.
|
||||
- `src/render.rs` with a deterministic top-down preview and a CPU perspective spike that only depends on `HeightGrid` + `Scene`.
|
||||
- `src/scene.rs` and `src/app_state.rs` for scene controls and preview wiring.
|
||||
- `src/import.rs` for the open-format import boundary.
|
||||
- `docs/plans/initial-roadmap.md` and `docs/plans/phase-4-formats-scripts-ui.md` for the broader project sequence.
|
||||
|
||||
The missing piece is a dedicated procedural terrain generator pipeline that can produce richer synthetic landscapes without mixing algorithm state into `HeightGrid`.
|
||||
|
||||
## Decision summary
|
||||
|
||||
### First generator family: seeded 2D value-noise fBm
|
||||
|
||||
Implement a deterministic, seedable fractal terrain family first, built from 2D value noise with fBm-style octaves.
|
||||
|
||||
Why this first:
|
||||
|
||||
- It is fully clean-room and easy to describe/test.
|
||||
- It produces organic terrain that is more representative than the current plane/hill fixtures.
|
||||
- It works well with tiny synthetic grids, which keeps tests fast and stable.
|
||||
- It can grow into ridged / warped / terraced variants later without changing the external boundary.
|
||||
|
||||
Initial scope should stay modest: generate a single height grid from a seed, dimensions, and a small set of parameters. Do not add erosion, climate, or streaming at first.
|
||||
|
||||
## API boundary
|
||||
|
||||
Keep `HeightGrid` as pure data plus basic helpers.
|
||||
|
||||
Recommended split:
|
||||
|
||||
- `src/terrain.rs`: immutable grid storage, validation, indexing, min/max, and tiny deterministic fixtures like `plane` and `radial_hill`.
|
||||
- New generator module, e.g. `src/terrain/generation.rs` or `src/generation.rs`: procedural generation logic, seed handling, interpolation/noise helpers, and generator presets.
|
||||
- Public API should return `HeightGrid` and nothing renderer-specific.
|
||||
- Any generator metadata should live in a separate spec/config type, not in the grid itself.
|
||||
|
||||
A good minimal boundary is:
|
||||
|
||||
- `TerrainGenerationSpec` or similar: dimensions, seed, octave count, lacunarity, gain, base frequency, amplitude.
|
||||
- `generate(spec) -> Result<HeightGrid, TerrainError>`
|
||||
|
||||
If the implementation later needs richer provenance, add a lightweight wrapper beside the spec, but keep the renderer and scene code consuming `HeightGrid` only.
|
||||
|
||||
## Roadmap slices
|
||||
|
||||
### Slice 1: generator module skeleton
|
||||
|
||||
Goal: introduce the procedural terrain namespace without changing renderer behavior.
|
||||
|
||||
Deliverables:
|
||||
|
||||
- module scaffolding for generator code
|
||||
- a small spec type with seed and size fields
|
||||
- a deterministic construction path that still returns a `HeightGrid`
|
||||
|
||||
Acceptance:
|
||||
|
||||
- `HeightGrid` stays unchanged as a storage type
|
||||
- generator tests compile without touching render code
|
||||
|
||||
### Slice 2: deterministic value-noise core
|
||||
|
||||
Goal: implement the smallest reusable noise primitive.
|
||||
|
||||
Deliverables:
|
||||
|
||||
- seeded lattice/value-noise helper
|
||||
- interpolation across grid cells
|
||||
- deterministic output for identical inputs
|
||||
|
||||
Acceptance:
|
||||
|
||||
- same seed + same spec always yields identical samples
|
||||
- different seeds produce different grids
|
||||
- tiny grids do not panic at edges
|
||||
|
||||
### Slice 3: fBm terrain composition
|
||||
|
||||
Goal: layer octaves into usable synthetic landscapes.
|
||||
|
||||
Deliverables:
|
||||
|
||||
- octave accumulation
|
||||
- amplitude/frequency controls
|
||||
- normalization into the range expected by the renderer/palette logic
|
||||
|
||||
Acceptance:
|
||||
|
||||
- output min/max remain bounded and predictable
|
||||
- generated terrain exercises multiple elevation bands in the preview
|
||||
|
||||
### Slice 4: preset profiles
|
||||
|
||||
Goal: provide a few named generator presets for common shapes.
|
||||
|
||||
Suggested first presets:
|
||||
|
||||
- `plain`-like flat terrain via zeroed noise amplitude
|
||||
- `island` / `continental` profile with a radial falloff mask
|
||||
- `mountain` profile with stronger octave contrast
|
||||
|
||||
Acceptance:
|
||||
|
||||
- preset selection is deterministic
|
||||
- presets remain thin wrappers around the shared generator core
|
||||
|
||||
### Slice 5: later enhancements
|
||||
|
||||
Only after the core is stable:
|
||||
|
||||
- ridged multifractal terrain
|
||||
- domain warping
|
||||
- terraces / plateaus
|
||||
- simple erosion pass
|
||||
- derived slope / normal helpers if the renderer needs them
|
||||
- CLI/script integration so generated terrain can be rendered and scripted like imported terrain
|
||||
|
||||
## Test matrix
|
||||
|
||||
Use tiny synthetic fixtures only.
|
||||
|
||||
### Unit tests
|
||||
|
||||
- dimensions are preserved exactly
|
||||
- zero dimensions are rejected
|
||||
- identical seed/spec pairs produce identical grids
|
||||
- different seeds change output
|
||||
- sample access stays in-bounds and row-major expectations remain intact
|
||||
- min/max are sane after normalization
|
||||
- presets produce the expected broad shape characteristics
|
||||
|
||||
### Behavior tests
|
||||
|
||||
- a small generated grid renders successfully through the existing top-down path
|
||||
- the perspective spike accepts generated grids without special-case code
|
||||
- the generator does not mutate renderer or scene state
|
||||
|
||||
### Validation commands
|
||||
|
||||
Run these for each generator slice:
|
||||
|
||||
```bash
|
||||
cargo fmt --check
|
||||
cargo test terrain
|
||||
cargo test
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
```
|
||||
|
||||
Add one feature-specific smoke command for the slice once the generator has a public entry point, for example a tiny render or sample-generation command that writes to `/tmp` and proves the generated grid is usable end-to-end.
|
||||
|
||||
## Definition of done for the workstream
|
||||
|
||||
The terrain-generation workstream is ready to close when:
|
||||
|
||||
- the generator module is separate from `HeightGrid`
|
||||
- at least one seeded procedural family exists
|
||||
- tests prove determinism and shape invariants
|
||||
- generated terrain can flow into the existing render pipeline without special handling
|
||||
- future slices can add more generator families without changing the grid storage contract
|
||||
Reference in New Issue
Block a user