Architecture Overview
This page is the high-level map of how GridForge is put together.
If you only need one sentence, it is this:
GridForge is a deterministic voxel-grid system where GridWorld owns one
isolated world's runtime state, VoxelGrid owns per-grid state, Voxel is the
core mutable cell model, ScanCell accelerates occupant queries, and managers
plus tracers provide mutation and query workflows on top of that state.
Architectural Shape
GridForge is organized as a small set of cooperating layers:
| Layer | Main Types | Primary Responsibility |
|---|---|---|
| World coordination | GridWorld |
World lifecycle, registration, adaptive top-level lookup, world events |
| Configuration and identity | GridConfiguration, GridConfigurationKey, BoundsKey, ObstacleToken, OccupantTicket, VoxelIndex, WorldVoxelIndex |
Configuration and geometry values plus exact transient runtime identity |
| Per-grid storage | VoxelGrid, Voxel, ScanCell, dense/sparse storage strategies |
Core spatial data, local lookup, grid neighbors, occupancy and obstacle state |
| Mutation services | GridObstacleManager, GridOccupantManager, Blocker |
Safe state changes, events, and higher-level world-space mutations |
| Query services | GridScanManager, GridTracer |
Radius scans, filtered retrieval, line tracing, coverage enumeration |
| Extension and diagnostics | IVoxelOccupant, IVoxelPartition, PartitionProvider, GridForgeLogger, GridDiagnostics |
Domain integration, metadata hooks, logging, diagnostic cell projection, and dirty tracking |
Repository Layout By Responsibility
| Path | Architectural Role |
|---|---|
src/GridForge/Configuration |
Grid creation inputs and bounds identity |
src/GridForge/Grids/Managers |
World orchestration and mutation/query manager APIs |
src/GridForge/Grids/Nodes |
Concrete runtime storage types: Voxel and ScanCell |
src/GridForge/Grids/Storage |
Dense and sparse physical voxel storage strategies |
src/GridForge/Grids/Topology |
Per-grid topology metrics, snapping, dimensions, and world/index projection |
src/GridForge/Grids/Support |
Pooled resources and event payload types |
src/GridForge/Spatial |
Shared coordinate, direction, occupant, and partition abstractions |
src/GridForge/Blockers |
World-space obstacle application on top of tracer coverage |
src/GridForge/Diagnostics |
Engine-agnostic diagnostic descriptors, topology geometry, and dirty adapter sessions |
src/GridForge/Support |
Cross-cutting query result groupings like GridVoxelSet |
src/GridForge/Utility |
Tracing and logging infrastructure |
The Main Runtime Loop
Most operations in the library follow the same broad path:
flowchart TD
Input[World-space input] --> World[GridWorld candidate lookup]
World --> Grid[VoxelGrid topology and storage]
Grid --> Voxel[Voxel state or scan-cell buckets]
Voxel --> Operation[Query or mutation]
Operation --> Events[Version and event updates]
Core Data Ownership
GridWorld owns
- active/inactive lifecycle for one world instance
- that world's optional ordinary-lookup cell size
- the active grid bucket
- normalized bounds-and-topology duplicate tracking
- the adaptive index used for coarse grid lookup
- world versioning and grid-level events
- a process-unique runtime world token
- world-local grid generations
- the lazily created occupant registration registry used by
GridOccupantManager - active-gated allocation of process-unique obstacle registrations
VoxelGrid owns
- one grid's snapped bounds and dimensions
- its per-grid topology metrics
- its dense or sparse physical voxel storage
- its scan-cell overlay for configured voxels
- the set of active scan cells
- neighboring grid relationships
- per-grid obstacle and occupancy summary state
- per-grid versioning
Voxel owns
- local and world-scoped identity
- cell-level occupancy state
- cell-level obstacle state
- attached partitions
- boundary awareness
- topology-aware neighbor query behavior
ScanCell owns
- a grid-local cell key
- occupant-plus-generation buckets grouped by voxel
- generation-aware tickets used for O(1) retrieval and stale-slot rejection
- fast "is there anything here?" state for scan-oriented queries
Why GridWorld Sits At The Top
GridForge is not architected as "a single process-wide world." It is architected as "one or more isolated worlds, each of which may own many grids."
That is why GridWorld sits above everything else:
- it maps normalized bounds-and-topology keys to reusable world-local grid slots
- it maintains an adaptive coarse index for candidate grids
- it links neighboring grids when overlap is valid
- it resolves world-space and world-scoped voxel identities back to active runtime objects
Registration And Construction Flow
GridConfiguration
-> GridWorld normalization and snapped bounds key
-> duplicate check
-> pooled VoxelGrid rent
-> VoxelGrid.Initialize(...)
-> topology-specific dimension calculation
-> dense or sparse physical voxel storage initialization
-> scan-cell storage for configured voxels
-> adaptive world-index registration
-> neighbor linking
-> world add notification
Topology Architecture
Grid topology is a per-grid strategy. GridConfiguration.TopologyKind selects
rectangular-prism or hex-prism cells, and GridConfiguration.TopologyMetrics
stores the deterministic cell geometry for that grid.
The topology layer owns:
- bounds normalization and snapping
- dimensions and topology-local index ranges
- world-position to
VoxelIndexprojection VoxelIndexto world-position projection- scan-cell key projection
- neighbor offsets and boundary ranges
Storage remains separate. Dense and sparse storage decide which physical voxels exist after topology has mapped world-space input to a local index or coverage range.
Hex-prism grids use axial XZ coordinates: VoxelIndex.x = q,
VoxelIndex.z = r, and VoxelIndex.y = layer. FlatTop and PointyTop change
only the fixed-point projection. Mixed rectangular/hex grids can live in one
GridWorld; direct mixed voxel bridging is exposed as a contact query over
world-space voxel footprint AABBs rather than as rectangular or hex direction
slots.
Query Architecture
GridForge uses two different query scales:
Coarse query scale
Handled through the world's adaptive top-level index.
Fine query scale
Handled locally through voxels and scan cells inside a VoxelGrid.
That split is one of the library's most important performance decisions.
Mutation Architecture
| Mutation Type | Main Entry Point | State Touched |
|---|---|---|
| Obstacles | GridObstacleManager |
Process-unique voxel obstacle tokens/counts, grid obstacle count, grid version, events |
| Occupants | GridOccupantManager |
Voxel occupant counts, generation-aware scan-cell buckets, active scan cells, events |
| Region blockers | Blocker / BoundsBlocker / AreaBlocker |
Traced coverage across one or more grids, obstacle application/removal |
| Partitions | Voxel.TryAddPartition(...) |
Typed metadata or behavior attached directly to a voxel |
Event And Version Model
GridForge uses both events and version numbers to express change.
Events are used for
- grid add/remove/reset notifications inside a world
- grid change notifications after meaningful mutations
- voxel obstacle and occupant notifications
- blocker apply/remove notifications
Version values are used for
- tracking world-level and grid-level mutation history
- helping dependent systems know when cached interpretations may be stale
- tagging voxel state with the grid version it was created or last synchronized against
Ordered committed changes
GridWorld.OnChangeCommitted publishes immutable, ordered post-mutation state.
Consumers can capture address-specific baselines, compose exact cross-grid
contacts, and traverse covered addresses with bounded value cursors. See
World Changes and Composition for the
snapshot protocol, revision checks, budgets, and cursor lifetimes.
Neighbor Architecture
Neighbor handling is split into two related but distinct problems:
VoxelGridtracks same-topology neighboring grids by topology-local neighbor slot, and each slot can contain more than one grid.Voxel.GetNeighborsInto(...)asks which physical voxels touch the source voxel, withVoxelNeighborScopeselecting source-grid, same-topology grid, mixed-topology grid, or all contacts.Voxel.TryGetNeighbor(...)exposes exact directed lookup throughRectangularDirectionandHexDirectionoverloads.- Rectangular full-neighbor lookup covers 26 directions. Hex full-neighbor
lookup covers 20 directions, with
Primary,Planar,Vertical, layer, and vertical-diagonal subsets exposed through the direction utilities. - Hex direction names describe axial offsets (
QPositive,RNegative, etc.) rather than world compass directions so pointy-top and flat-top grids share one unambiguous API. Voxel.GetRectangularNeighborsInto(...)andVoxel.GetHexNeighborsInto(...)fill caller-owned storage with direction-labeled same-topology results.
VoxelGrid.Neighbors remains a same-topology grid-slot accelerator, but public
contact discovery is resolved by VoxelNeighborResolver. Contact queries use
the world's adaptive index, derive a topology-aware candidate range per target
grid, and final-filter by fixed-point AABB overlap. This avoids ambiguous
direction slots, keeps sparse target grids configured-only, and reflects grid
load/unload or sparse mutation without per-voxel neighbor caches.
Coverage Architecture
GridTracer is the architectural bridge between world-space geometry and
cell-level data.
It turns:
- lines into voxel coverage
- bounds into voxel coverage
- bounds into scan-cell coverage
That same utility underpins blockers, custom coverage queries, and scan-region enumeration.
Rectangular coverage uses rectangular index ranges. Hex-prism line tracing uses axial/cube interpolation and deterministic rounding; hex bounds coverage uses a conservative candidate range followed by cell-center reach checks. Callers still use the same tracer APIs for both topologies.