Voxel data and chunk storage
Coordinates and ownership
Section titled “Coordinates and ownership”World positions are integer voxel coordinates. Chunk coordinates identify horizontal regions; section coordinates partition a chunk vertically. VoxelMath centralizes conversions and dimensions. Check those helpers before writing coordinate arithmetic so negative coordinates and section boundaries follow one convention.
Sections are the hot-path unit
Section titled “Sections are the hot-path unit”ChunkSection stores voxel data in fixed-size arrays for its 4096 cells. This layout makes indexed reads predictable and keeps inner loops compact. Chunk groups sections and provides the larger storage boundary. Avoid replacing this with per-voxel objects or allocations in meshing, lighting, and bulk scans.
The ownership chain is WorldManager → ChunkColumn → ChunkSection: the manager finds or creates columns, columns provide vertical sections, and sections own compact cell data and bounded mesh work. Treat these as nested lifetimes rather than interchangeable containers.
Block type and state
Section titled “Block type and state”BlockType identifies a registered block; block definitions are shared instances in BlockRegistry. Per-cell state is stored separately in BlockStateData. These have distinct responsibilities: registry identity answers which block, while state answers which encoded variant. The current compact state representation does not express every vanilla property; consult the fidelity ledger before assuming stair shape, crop age, or other state is represented.
Writes and derived data
Section titled “Writes and derived data”World writes may affect block entities, neighbors, scheduled ticks, lighting, and section meshes. The world manager coordinates these effects. Keep storage mutation and derived updates consistent by using the established level write APIs rather than editing arrays from gameplay code.
When tracking stale world state, follow the full path: requested position/state → column and section lookup → block-entity lifecycle → neighbor/tick updates → light and mesh invalidation → renderer refresh. Correct block IDs do not prove the downstream updates ran.
Performance boundaries
Section titled “Performance boundaries”- Keep section dimensions and index lookup centralized.
- Avoid heap allocation and virtual dispatch inside voxel-wide loops.
- Rebuild only the affected section when the write path supports it.
- Treat rendering data as derived from storage; do not make the mesh the source of truth.
Save and load boundary
Section titled “Save and load boundary”Sections are runtime storage; ChunkSerializer and the surrounding storage types define the persisted representation. Check block identity, encoded state, fluids, light, and block-entity payloads independently. A value being available in memory does not prove it is saved. Follow the paired reader and writer before extending a versioned format.
Source map
Section titled “Source map”Look in src/Voxel/ for ChunkSection, Chunk, state types, coordinate helpers, registry, and mesher. The design rationale is in docs/VOXEL_ENGINEERING_GUIDE.md; open issues are tracked in docs/FIDELITY_LEDGER.md.
Related: rendering and lighting, world lifecycle, and the chunk storage and rendering map.