# ADR 0039: Inline Height-Grid Terrain Foundation

## Status

Accepted

## Context

Terrain sculpting, material painting, physics placement, recovery, and prefab workflows need one
stable owner for height data. Generated meshes and colliders cannot be authoritative because they
are runtime artifacts, while introducing an external binary heightmap before editing semantics exist
would add file-move, revision, import, and multi-document transaction complexity prematurely.

## Decision

`TerrainDesc` schema v1 stores a bounded square grid of normalized finite `f32` heights directly in
the authored scene component. It also stores sample spacing, height scale, chunk quad size, an
optional shared base Material/Material Instance reference, collider generation, and shadow flags.

Hydration deterministically partitions grid quads into generated children. Boundary samples are
duplicated between neighboring render chunks so each chunk has complete normals and independent
triangle geometry. Chunk meshes/colliders are never `LevelObject` entities and are therefore absent
from saved scenes, recovery documents, prefabs, and history snapshots.

Resolution changes are explicit destructive flat-grid replacements in the foundation inspector.
Sculpt tools mutate the existing grid through grouped history transactions. A future external
heightmap representation requires an explicit schema migration and authored-file ownership ADR; it
must not silently rewrite an inline terrain during normal load.

## Consequences

- Scene, prefab, undo, recovery, collaboration, and validation use one exact terrain document.
- V1 grids are bounded to 1025×1025 samples to prevent accidental unbounded scene payloads.
- Large production terrains may eventually need tiled external storage and streaming.
- Foundation chunks remain raster-only in Solari until terrain layer materials have an exact Surface
  evaluator in `#24`; explicit exclusion is preferred to a black or mismatched ray-traced proxy.
- Layer weights and sculpt strokes extend this descriptor contract in `#23`/`#24`; generated chunks
  remain disposable regardless of the editing representation.
