- 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.
7.0 KiB
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 00–06 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:
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:
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:
- read center direction
a; - visit candidates from the padded atlas/mapping;
- compute
distance=R*acos(clamp(dot(a,b),-1,1)); - multiply candidate state by candidate spherical cell area;
- accumulate softened disk/ring weights;
- normalize according to the selected complete sphere model:
Corrected: divide each numerator by the per-center sum of the samecell_area*kernel_weightterms actually visited;Legacy: divide disk by2πR²(1-cos(ri/R))and ring by2π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/Legacysphere-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
Kis 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
acosNaN.
Resource tests
- no texture feedback;
- all gutters explicitly initialized;
- framebuffer completeness after rebuild;
- repeated
Corrected↔Legacyswitching 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;Legacyanalytic/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
acosremains.