System Architecture
The engine is built around several core systems that interact to create the gameplay experience:Core Components
World System
TheWorld class (src/world.h/cpp) is the central coordinator that manages:
- Chunk Management: Hash map of chunks keyed by chunk coordinates (
glm::ivec3) - Block Type Registry: Array of
BlockType*loaded fromdata/blocks.mccpp - Lighting System: Dual propagation queues for block light and skylight
- Rendering Pipeline: Visibility culling, shadow mapping, and draw calls
src/world.h
Chunk System
Chunks are 16×128×16 voxel volumes (src/chunk/chunk.h/cpp):- Block Storage: 3D array
uint8_t blocks[16][128][16] - Lighting Data: Packed nibbles in
uint8_t lightmap[16][128][16](4 bits skylight + 4 bits block light) - Mesh Generation: Subdivided into 16-block-tall subchunks for efficient updates
- GPU Upload: VAO/VBO with packed vertex data (position, UV, light)
src/chunk/chunk.h
Player & Entity System
ThePlayer class (src/entity/player.h/cpp) extends the base Entity class:
- Physics Integration: Gravity, drag, AABB collision with block colliders
- Input Handling: Movement acceleration, sprint mechanics, flying mode
- Camera System: View/projection matrices with FOV adjustment for sprinting
- Interpolation: Smooth rendering between physics ticks
src/entity/player.h
Rendering Pipeline
The rendering system uses modern OpenGL with several advanced features:- Texture Array Atlas: All block textures in a single
GL_TEXTURE_2D_ARRAY(TextureManager) - Cascaded Shadow Maps (CSM): 4-cascade directional shadows from the sun
- Colored Lighting: Separate day/night and block light with smooth propagation
- Post-Processing: Underwater effects, fullscreen shader pass
- Chunk Sorting: Distance-based ordering for translucent rendering
Block Type System
Blocks are defined via:- Model Templates: Cube, plant, liquid, slab, torch, door, ladder, etc. (src/models/)
- Texture Bindings: Face-specific texture assignments
- Properties: Transparency, colliders, light emission
- Data File:
data/blocks.mccppmaps IDs to models/textures/names
Data Flow
Block Placement/Breaking
- Raycast:
HitRaytraces from player eye position - Collision Check:
World::try_set_blockvalidates against player AABB - Block Update:
World::set_blockmodifies chunk data - Light Update: Triggers light propagation queues
- Mesh Update:
Chunk::update_at_positionqueues affected subchunks - Neighbor Notification: Border blocks update adjacent chunks
Lighting Propagation
Lighting uses flood-fill propagation with separate queues:- Block Light: 15 levels, decays by 1 per block
- Skylight: 15 levels, no decay downward, 1 per horizontal
- Sources: Torches (block light), sky (skylight)
- Updates: Incremental per-tick with configurable step limits
Render Frame
- Update Phase: Player physics, world tick, lighting propagation
- Camera Setup: Update view/projection matrices
- Visibility Culling: Sort chunks by distance, build visible set
- Shadow Pass: Render depth for each CSM cascade
- Main Pass: Draw opaque chunks, then translucent with depth writes disabled
- Post-Process: Apply underwater/other effects
- UI Overlay: Crosshair, health bar, F3 debug screen
Persistence
World data is saved to disk using NBT format:- Save System (src/save.cpp): Chunk streaming, load/save, terrain generation
- NBT Format: Gzipped NBT with ByteArray encoding for blocks/light
- Streaming: Loads chunks near player, unloads distant ones
- Fallback: Generates flat terrain if no save data exists
Threading Model
The current implementation is single-threaded. All chunk meshing, lighting propagation, and physics run on the main thread with per-frame time budgets.
Performance Optimizations
- Subchunk Meshing: Only rebuild affected 16×16×16 regions when blocks change
- Incremental Lighting: Configurable steps per tick to avoid frame spikes
- Frustum Culling: Chunks sorted by distance, only visible ones rendered
- Texture Atlas: Single bind for all block textures
- Index Buffer: Shared IBO for all chunks (quad -> triangle conversion)
Dependencies
Third-party libraries (ininclude/):
- GLFW: Window/input management
- GLAD: OpenGL loader
- GLM: Math library (vectors, matrices)
- stb_image: Texture loading
- stb_truetype: Font rendering
- miniaudio: Music playback
- zlib: NBT compression
Next Steps
Game Loop
Detailed breakdown of the main game loop and frame execution
World System
Deep dive into world management, chunks, and coordinate systems