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

2.4 KiB

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.