Organic terrain, inspired by 7 Days to Die
The design for VoxelCut's terrain: what has been decided, what it implies for the engine, what is still genuinely open, and in what order it should be built.
The direction is decided — see the decisions. Nothing is implemented yet. World scale, previously the one topic flagged for its own conversation, is now largely settled: the world is finite and generated up front, which withdrew the design's only knowing divergence from the reference and reopened the LOD approach in risk 5. What remains open is a set of specific technical questions (section 7), the world's dimensions, and how terrain LOD is done.
The design in one paragraph
One voxel grid holding two representations that are never blended. Terrain is a density field meshed with Marching Cubes, textured with triplanar mapping and material splatting; mining it reduces a cell's density, so the surface visibly shrinks under the tool until the cell is gone. Construction stays discrete cubes with per-face tiles; damaging it never changes its shape, only its texture, which progresses through crack stages until the block breaks. Where the two meet they interpenetrate rather than stitch. The world is finite and generated up front, at a size that is a parameter rather than a constant, and generated worlds are stored artifacts. Structural integrity applies to both, and is deferred.
Decisions at a glance
| Question | Decision |
|---|---|
| Generation | fBm with domain warping, 3D noise caves, real strata, ambient occlusion in the mesher |
| Vertical composition | Layered geology — soils and sands over distinct rock types, mineral seams within specific host rocks, caves and rivers, down to unbreakable bedrock. Strata may sit at different depths or be absent; bedrock never is |
| World height | 384 to start, configurable — strata are anchored relative to the surface and to bedrock, so the number can move without retuning |
| Generator structure | Ordered steps, each holding one or more generators that run concurrently. Passes that need each other's output get separate steps, since a step reads only earlier ones. Bedrock clamp and LOD generation are the terminal steps |
| Distant terrain | A pre-generated static coarse mesh loaded from the world artifact — no runtime LOD hierarchy, no Transvoxel |
| Distant construction | Simplified LOD models generated separately, so cities keep their silhouette. Regenerating them for player-built structures is deferred |
| Liquids & gases | Wanted; behaviour deliberately deferred to its own discussion |
| Terrain silhouette | Marching Cubes specifically — matching the reference rather than picking a cheaper isosurface method |
| Target | Parity with the reference on both look and feel first; optimise or diverge afterwards |
| Caves & overhangs | Required |
| Terrain digging | Tool damage shrinks the voxel visibly — damage is density |
| Construction damage | Shape never changes; damage shows as crack textures |
| World scale | Finite, as the reference is — and the size is a runtime parameter, not a hardcoded constant |
| World creation | Generated up front as a distinct step, producing a stored artifact. Sharing worlds is an idea kept in view but deferred |
| Structural integrity | In scope for both representations; design deferred |
The pages
- 01 The decided design Each decision, its reasoning, and what it rules out — plus the one finding that falls straight out of the digging model.
- 02 What the reference actually does 7 Days to Die as a structural reference, with confidence levels, and this repo's own reverted attempt as the more useful case study.
- 03 Target architecture Two representations, two meshers, two damage models, and a subsystem-by-subsystem delta from where the code is today.
- 04 Open risks Ranked. Collision under a continuously shrinking surface is first; per-strike remesh cost is a new risk created by the digging decision.
- 05 World scale A finite world of configurable size, generated up front and stored up front: what that settles, what it leaves open, and what it does not remove.
- 06 Roadmap Six phases, ordered so each one is verifiable on its own and the expensive commitments come after the cheap de-risking.
- 07 Open questions The specific technical decisions the direction has now surfaced, each with a recommendation attached.
- 08 Streaming and persistence Phase 2 in detail: chunk lifetime, GPU resource lifetime, ownership, write-back, residency and the world format — ten decisions with their alternatives.
- 09 Marching Cubes in detail Phase 3's remaining decisions: material weights, the vertex format, triplanar cost, AO, the interpenetration and the texture array.
- 10 The two damage models Phase 4 in detail: density as terrain damage, the per-chunk crack buffer and its persistence, and the fuller damage model this leaves room for.
- — Glossary Every acronym and term used here, defined and searchable. Terms are also hoverable inline on every page.
How to read this
Technical terms and acronyms are marked with a dotted underline on their first appearance on each page. Hover — or tab to them, they open on focus — for a short definition plus a note on why the term matters specifically here. The full list is on the glossary page.
The code this is written against
| Concern | Today | Where |
|---|---|---|
| Meshing | One naive face-culling cube mesher; no greedy meshing, no LOD, no AO | src/voxel/CubeMesher.cpp |
| Voxel data | Type, material index, density byte, class tag — density and class carried but unused by meshing | src/voxel/Voxel.h |
| World | Dense vector of 323 chunks, fixed size at construction, no streaming | src/voxel/VoxelWorld.h |
| Generation | Single-octave sin(0.1x)·cos(0.1z) heightmap, three material bands by depth |
src/Engine.cpp (fillDensityTerrain) |
| Picking | Grid DDA raycast; already returns both a gradient normal and the crossed face normal | src/voxel/Raycast.h |
| Physics | Player AABB swept against grid cells, snapping to integer grid lines | src/physics/VoxelCollision.h |
| Editing | Whole-cell place/remove; game mode wears a cell down over several strikes | src/voxel/EditOps.h |
| Damage | One sparse DamageMap for all voxels, keyed by world cell | src/voxel/VoxelDamage.h |
| Texturing | Per-face UV into a texture array, indexed by material and FaceKind | src/voxel/VoxelMaterials.h |
| Remesh | Synchronous full-grid dirty sweep behind a waitIdle, on the main thread | src/Engine.cpp (remeshDirtyChunks) |