Files
smoothlife/plans/08_spherical_backend.md
Federico Pasqua 51cff7b0f3 Add detailed phase plans for foundational macrosteps
- Macrostep 00: Model contract and retained historical options.
- Macrostep 01: Project foundation and configuration, including schema, presets, CLI, and CI setup.
- Macrostep 02: Mathematical core implementation and deterministic oracles.
- Macrostep 03: CPU-based planar simulation engine, FFT backend, and headless runner.

Provides exhaustive objectives, phase breakdowns, validation policies, and deliverables for each macrostep.
2026-07-14 16:50:54 +02:00

154 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Macrostep 08 — Spherical backend
## Objective
Implement SmoothLife on a closed sphere with a tested corrected default and one coherent retained `SphereModel::Legacy`, backed by CPU oracles, GPU simulation, and a modern raylib renderer.
## Dependencies
Macrosteps 0006 complete. Macrostep 07 is not technically required, but execute in index order for a single team.
## Phase 8.1 — Cube-sphere geometry model
### Substep 8.1.1 — Face frames and directions
Define six typed face frames with a single orientation table. For each face-cell center:
```text
direction = normalize(normal + tan(uπ/4)*axis_u + tan(vπ/4)*axis_v)
```
Use configurable `K`, with legacy `K=128` and internal `R=K/2`. Store direction, area, face, and coordinates in CPU structures; upload immutable geometry once.
### Substep 8.1.2 — Cell areas
Compute each spherical quadrilateral area from two spherical triangles or a proven equivalent. Test:
- every area finite/positive;
- face symmetry;
- total area approaches `4πR²` within a recorded discretization tolerance.
### Substep 8.1.3 — Seam mapping
Implement `SphereModel` as one local enum:
- `Corrected` (default): direction-based projection across every edge and corner; materialize and snapshot-test the mapping.
- `Legacy`: original 24 side-gutter transforms and invalid corner gutters as one inseparable part of the historical sphere model.
Do not expose independent seam/normalization compatibility toggles. Neither model samples and renders to the same atlas; both build a distinct initialized padded sampling atlas from current state.
## Phase 8.2 — Spherical neighborhood oracle
### Substep 8.2.1 — Radius conversion
Freeze and implement:
```text
ri_planar = ra/3
widths = 1
r_geo = R*acos(clamp(1-r_planar²/(2R²),-1,1))
cap_area(r) = 2πR²*(1-cos(r/R))
legacy search bound = ceil(2ra)
corrected search bound = complete nonzero softened support
```
Report invalid chord radii instead of producing NaN.
### Substep 8.2.2 — Direct neighborhood
For each active cell:
1. read center direction `a`;
2. visit candidates from the padded atlas/mapping;
3. compute `distance=R*acos(clamp(dot(a,b),-1,1))`;
4. multiply candidate state by candidate spherical cell area;
5. accumulate softened disk/ring weights;
6. normalize according to the selected complete sphere model:
- `Corrected`: divide each numerator by the per-center sum of the same `cell_area*kernel_weight` terms actually visited;
- `Legacy`: divide disk by `2πR²(1-cos(ri/R))` and ring by `2πR²[(1-cos(ra/R))-(1-cos(ri/R))]`, regardless of softened boundaries or masked corner samples.
The CPU implementation may be slow and use reduced `K` for exhaustive tests; clarity and seam correctness are primary. Constant-field uniformity is required for `Corrected`; historical deviations near legacy masked corners are expected fixtures.
### Substep 8.2.3 — Dynamics
Both sphere models support only:
- discrete replacement `clamp(S)`;
- fixed smooth update `clamp(A+0.1*(2S-1))`.
Do not expose base relaxation, configurable `dt`, FFT, AB3, or RK4. Future experimental sphere dynamics require a separately named model rather than extending `Legacy`.
## Phase 8.3 — Deterministic initialization
Always clear all active and gutter storage. Implement seeded sphere splats with explicit reset versus overlay operations. Provide face-coded, constant, impulse, and great-circle test initializers. Never preserve undefined initial texture contents.
## Phase 8.4 — GPU direct solver
### Substep 8.4.1 — Atlas resources
Use separate current, padded-sampling, and next `R32F` targets plus immutable direction/area data. Fill gutters via explicit passes or CPU-generated mapping, then run one direct neighborhood pass over active tiles and swap.
### Substep 8.4.2 — Stencil strategy
Start with a bounded GLSL loop specialized/cached by face size and maximum radius. Precompute valid offset metadata where it reduces `sqrt`, branch, or mapping cost without changing semantics. Recompile only on geometry changes, not rule edits.
### Substep 8.4.3 — Parity
First compare each CPU model to Macrostep 00's independent source-frozen `M/N/S/next` fixtures at centers, edges, and masked corners for both update modes. Then compare GPU to its validated CPU model. Initial one-step max-error target is `≤1e-3`; CPU/GPU agreement alone is insufficient.
## Phase 8.5 — Sphere presentation
Generate one indexed cube-sphere mesh with independent UVs per face. Add:
- an explicit `Corrected`/`Legacy` sphere-model selector with a concise semantic comparison;
- transactional model switching: construct the complete seam map, normalization data, padded atlas, and shader resources before commit; preserve active-face state and generation when `K` is unchanged; retain the previous model on failure; never share model-specific caches;
- orbit/arcball camera and time-based autorotation;
- grid overlay;
- all shared palettes;
- optional two-sided legacy red/blue styling;
- active atlas, padded atlas, direction, area, seam, and geodesic-distance views;
- face labels and edge-orientation debug mode.
Keep rendering geometry separate from simulation resolution so mesh tessellation can change without altering state.
## Phase 8.6 — Verification and performance
### Geometry/seam tests
- all 24 directed edge mappings and corner transitions;
- cross-edge-and-back round trip;
- shared-edge direction equality;
- rotational consistency under cube symmetries;
- total area and constant-field neighborhoods;
- no `acos` NaN.
### Resource tests
- no texture feedback;
- all gutters explicitly initialized;
- framebuffer completeness after rebuild;
- repeated `Corrected↔Legacy` switching agrees with a freshly constructed destination model, preserves state/generation, and never mixes seam or normalization caches;
- failed switches preserve the previous working model;
- rule edits do not rebuild geometry.
### Performance target
On the designated GPU, `K=128`, `ra=10` should target p95 step time below 33 ms for both models. If either fails, ship a lower interactive default while keeping `SphereModel::Legacy` selectable and document the measured cost (roughly 165 million candidate iterations per step before optimizations).
## Deliverables
- CPU oracles for `SphereModel::{Corrected,Legacy}`.
- One coherent retained legacy sphere model, not independent compatibility flags.
- GPU sphere backend and raylib sphere renderer.
- Sphere-specific inspection and seam diagnostic tools.
## Exit gate
- Face orientation, area, edge, and corner tests pass.
- Both CPU models match independent source-frozen end-to-end fixtures for both update modes.
- Constant state produces uniform neighborhoods for `Corrected`; `Legacy` analytic/masked-corner deviations match committed fixtures.
- CPU/GPU one-step parity passes at centers, edges, and corners for both models.
- Transactional model-switch lifecycle tests pass without mixed caches or state loss.
- Default sphere preset is rotatable, inspectable, and deterministic.
- No undefined atlas contents, feedback loop, or unclamped `acos` remains.