Overview
Implement a real-world terrain generator that uses NASA SRTM 90m elevation data, ESA land-cover rasters, and OSM water features to generate accurate UK terrain as an optional world type.
This replaces the investigation in #128 with a concrete implementation plan.
Architecture
New subsystem: src/world/realworld/ — completely separate from existing noise generators.
Key Design Decisions
- DEM Source: NASA SRTM 90m behind a
DEMSource interface (swappable to Copernicus later)
- Cache: 10GB LRU disk cache for tiles
- Water: Pre-processed UK water mask (100m raster, build step)
- Vertical Stretch: Configurable per-world (1.0x / 1.5x / 2.0x)
- Scope: UK only for prototype (~49°N to 61°N, 8°W to 2°E)
- Threading: Async I/O on dedicated thread pool; gen workers never block
Implementation Phases
Phase 1: Geospatial Infrastructure
projection.zig — WGS84 ↔ block(x,z), equirectangular projection
tile_cache.zig — 10GB LRU disk cache (file-based or SQLite)
dem_source.zig — DEMSource interface with SRTM90Source implementation
tile_prefetcher.zig — Predicts needed tiles from player position, queues fetches
Phase 2: Data Pipeline
scripts/generate_uk_water_mask.py — Pre-process OSM water polygons to 100m raster mask
biome_mapper.zig — ESA land-cover class → BiomeId mapping table
realworld_data.zig — Aggregator: samples DEM, water mask, ESA raster per chunk
Phase 3: Generator Implementation
realworld_generator.zig — Implements existing Generator.VTable
generate() — Samples data, fills blocks, applies vertical stretch + noise detail
- Cache miss → returns "not ready", chunk retries next frame
- Slope-based material selection + water placement
Phase 4: Integration
- Register in
registry.zig as 4th generator option
- UI selector for stretch factor in
singleplayer.zig
- Store config in
level.dat (generator_index, stretch_factor, world_bounds)
Phase 5 (Future): Round World
- Deferred until after real-world gen is stable
- Will require chunk coordinate wrapping, spherical distance math, polar projection
Threading Model
[Main Thread] [Gen Workers] [I/O Workers]
| | |
WorldStreamer ──► chunk.gen_queue ──► generator.generate()
(predicts tiles) (4 workers) │ reads tile_cache
│ │ (hit: generate)
│ │ (miss: return NOT_READY)
▼ ▼
TilePrefetcher ◄──────── queue fetch ───┘
(queues async fetches) [I/O pool downloads
│ DEM/ESA/OSM tiles]
▼
tile_cache (disk/SQLite)
Critical: Worker threads never block on I/O. They either generate immediately (cache hit) or yield (cache miss).
Block Fill Logic
- Sample DEM elevation →
blockY = (elevation - sea_level) / scale + water_level
- Apply noise detail (±2 blocks from existing noise system)
- Slope-based material selection:
- Slope < 0.2: grass/dirt
- 0.2–0.6: stone
-
0.6: stone + gravel
- Water: if OSM lake/river polygon covers block, set water blocks up to sea level
Risks & Mitigations
- ESA raster availability: Verify UK coverage and license. Fallback: derived biomes from elevation/slope.
- SRTM server reliability: Retry logic + backoff in
SRTM90Source.
- Water mask complexity: If OSM→raster is too complex, fallback to dynamic rasterization (slower but simpler).
Acceptance Criteria
Overview
Implement a real-world terrain generator that uses NASA SRTM 90m elevation data, ESA land-cover rasters, and OSM water features to generate accurate UK terrain as an optional world type.
This replaces the investigation in #128 with a concrete implementation plan.
Architecture
New subsystem:
src/world/realworld/— completely separate from existing noise generators.Key Design Decisions
DEMSourceinterface (swappable to Copernicus later)Implementation Phases
Phase 1: Geospatial Infrastructure
projection.zig— WGS84 ↔ block(x,z), equirectangular projectiontile_cache.zig— 10GB LRU disk cache (file-based or SQLite)dem_source.zig—DEMSourceinterface withSRTM90Sourceimplementationtile_prefetcher.zig— Predicts needed tiles from player position, queues fetchesPhase 2: Data Pipeline
scripts/generate_uk_water_mask.py— Pre-process OSM water polygons to 100m raster maskbiome_mapper.zig— ESA land-cover class →BiomeIdmapping tablerealworld_data.zig— Aggregator: samples DEM, water mask, ESA raster per chunkPhase 3: Generator Implementation
realworld_generator.zig— Implements existingGenerator.VTablegenerate()— Samples data, fills blocks, applies vertical stretch + noise detailPhase 4: Integration
registry.zigas 4th generator optionsingleplayer.ziglevel.dat(generator_index, stretch_factor, world_bounds)Phase 5 (Future): Round World
Threading Model
Critical: Worker threads never block on I/O. They either generate immediately (cache hit) or yield (cache miss).
Block Fill Logic
blockY = (elevation - sea_level) / scale + water_levelRisks & Mitigations
SRTM90Source.Acceptance Criteria
BiomeIdvalues