synvael/docs/adr/0008-split-coordinate-entity-positions.md

27 lines
2.4 KiB
Markdown

# 0008. Split-coordinate entity positions
- **Status:** Accepted
- **Date:** 2026-07-07
## Context
In a procedurally generated voxel world, an entity's position cannot be robustly represented by a single global single-precision floating-point vector (`f32` or `Vec3`). At large distances from the origin, the spacing between representable floating-point numbers increases, leading to spatial jitter, physics instability, and rendering artifacts.
While double-precision floats (`f64`) postpone this issue, they double the data size and are not uniformly or natively supported on GPUs, which expect `f32` vertices and transforms. The engine requires a spatial representation that maintains sub-millimeter precision universally across a theoretically unbounded world, without coupling the simulation state directly to GPU limitations or paying the cost of `f64` everywhere.
## Decision
The engine uses a split-coordinate representation for entity positions, encapsulated by the `EntityPos` type. An entity's absolute position is defined by two discrete components:
1. A `chunk` anchor (`ChunkPos`): The integer coordinates of the chunk containing the entity.
2. A `local` offset (`Vec3`): A single-precision floating-point vector describing the entity's exact position relative to the chunk's minimum corner.
When an entity moves, the movement is applied to the `local` offset. A normalization step (`EntityPos::renormalize`) then carries any overflow beyond the chunk boundaries into the integer `chunk` anchor, ensuring the `local` offset always remains strictly within the bounding box of a single chunk (`[0.0, CHUNK_SIZE)`).
## Consequences
- **Uniform Precision:** Entities maintain exact `f32` precision regardless of how far they travel from the world origin, as the active floating-point magnitude is strictly bounded by the size of a single chunk.
- **Rendering Stability:** The renderer can compute relative matrices by defining the camera's current chunk as the origin. This allows the GPU to process all vertex data and transforms in standard `f32` without any spatial jitter.
- **Math Complexity:** Code manipulating spatial positions (like physics integration and distance checks) becomes more complex. It is no longer possible to simply subtract two global vectors; logic must handle both the chunk offset and the local offset simultaneously.
- **Serialization:** `EntityPos` serializes as a compound struct, ensuring save files do not lose coordinate precision for distant entities.