Spatial
Typhon's spatial layer gives any component field a declarative
[SpatialIndex], and one index answers it: the per-cell cluster broadphase, standing on a sparse cell grid per realm and serving AABB/Radius/Ray/Frustum/kNN queries for every archetype.[SpatialIndex]contributes field metadata (offset, shape, mode, category) and allocates no storage segment of its own. On top of the same grid, a tiered-simulation system lets game code assign per-cell simulation frequency, sleep idle clusters, and parallelize neighbor-touching systems safely β so a large world spends its CPU budget where the player actually is.
π¬ Recommended: read in-depth-overview/07-spatial.md (Chapter 07: Spatial) first to understand the overall design and concepts behind this category, before diving into the specific features below.
Public Features
| Feature | Summary | Status | Level |
|---|---|---|---|
| What Spatial Costs You | The four cost centres, why cluster tightness governs query cost, and how to choose a cell size β read before declaring a second spatial archetype | β Implemented | π’ Start Here |
| Spatial Architecture Overview | One spatial index, two levels: the grid locates a cell, the cell's cluster broadphase answers the query. Which feature to read next | β Implemented | π΅ Core |
| Field Attribute & Schema Integration | Declare a component field as spatially indexed via [SpatialIndex], validated against schema rules at registration time |
β Implemented | π΅ Core |
| Β Β β³ Storage-Mode Compatibility (SingleVersion / Versioned) | The same [SpatialIndex] field works on both storage modes β only when the cluster bound and the cell index catch up differs |
β Implemented | π΅ Core |
| Spatial Query API (AABB / Radius / Ray / Frustum) | Public fluent EcsQuery predicates WhereNearby/WhereInAABB/WhereRay/WhereFrustum, resolved as a cell walk then a per-cluster narrowphase |
β Implemented | π΅ Core |
| Realms β Several Worlds in One Engine | Isolated worlds (planets, interiors, space, instanced dungeons) in one engine: each realm owns its grid and cell size, is queried alone, and sleeps or runs divided when nobody watches it | β Implemented | π£ Advanced |
| Spatial Grid Configuration & Tier Control | Per-realm grid sizing (realm 0 by default) plus the per-cell SimTier control surface for multi-resolution simulation |
β Implemented | π΅ Core |
| Tuning the Spatial Grid | Every SpatialGridConfig parameter with the symptom that says to change it, the hysteresis/relocation/repair escalation, and starting recipes per world shape |
β Implemented | π£ Advanced |
| Reading Spatial Telemetry | Each migration counter paired with the parameter it tunes, plus worked readings for a world that is throttling, starving or evicting | β Implemented | π£ Advanced |
| Static / Dynamic Separation (part of Per-Cell Cluster Index Internals) | Every cell keeps two halves β a tick-fence-exempt static one and a dynamic one refreshed each fence β and a query unions them | β Implemented | π£ Advanced |
| Cluster-Bound Motion Hysteresis | A cluster's bound covers up to 64 entities, so most movement changes nothing; only a move that pushes it outward costs a per-axis widen plus a fence recompute | β Implemented | π£ Advanced |
| Category Filtering | Bitmask pruning skips whole clusters before geometry tests via [SpatialIndex(Category = ...)] + ClusterSpatialQuery<TArch> |
β Implemented | π£ Advanced |
| Spatially-Coherent Entity Clustering | Every entity in a cluster shares one grid cell, so spatial bookkeeping is per-cluster, not per-entity | β Implemented | π£ Advanced |
| Tiered Simulation Dispatch | One simulation tier per spatial cell, four dispatch frequencies, zero per-entity distance checks | β Implemented | π£ Advanced |
| Checkerboard Dispatch | Opt-in two-phase Red/Black cluster partitioning for systems that write across cell boundaries, dispatched as one DAG node with two internal phases | β Implemented | π£ Advanced |
Internal Features
Engine machinery below this line backs the public features above but is never directly instantiated or called by application code β kept here for engine contributors.
| Feature | Summary | Status |
|---|---|---|
| Per-Cell Cluster Index Internals | Node layout, fanout and the lock protocol of the R-Tree a cell half holds once its density crosses the promotion threshold β most cells stay well below it and scan a linear list instead | β Implemented |
| Trigger Volumes (Enter / Leave / Stay) | Region occupancy diffed against the per-cell cluster index each cycle to emit Enter/Leave/Stay events at a configurable per-region frequency, reached through dbe.SpatialTriggers<T>() |
β Implemented |
| Cluster Spatial Queries | Per-cell broadphase + per-entity narrowphase AABB/Radius queries for cluster-eligible archetypes; raw enumerator needs an engine-internal EpochGuard scope, app code reaches the same path via the public EcsQuery predicates above |
π§ Partial |
| Cluster Dormancy (Sleep / Wake) | Clusters with no component writes for N ticks sleep and skip dispatch entirely, waking within one tick of being touched; no public configuration API yet | β Implemented |