- 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.
5.9 KiB
Macrostep 04 — Raylib visualization workbench
Objective
Deliver the first useful interactive product: a portable, resize-safe raylib laboratory that runs the CPU backend and makes the rule, kernels, neighborhoods, and update logic visible.
Dependencies
Macrosteps 00–03 complete.
Phase 4.1 — Application lifecycle and scheduler
Substep 4.1.1 — Raylib ownership
Initialize and own raylib on the main thread. Keep handles out of the mathematical core. Establish explicit startup, running, backend-rebuild, and shutdown states so partial resource failures do not corrupt the model.
Substep 4.1.2 — Decoupled timing
Implement:
- render FPS independent of a fixed updates-per-second simulation clock;
- pause, single-step, reset, and an explicit finite
advance N stepscommand that is not tied to rendering; - bounded catch-up to avoid a spiral of death;
- headless benchmarking outside the render loop rather than an uncapped frame-driven mode;
- model
dtindependent of wall-clock tick duration.
Animations and camera movement are time-based, not frame-count-based.
Substep 4.1.3 — Unified action map
Map keyboard, mouse, and UI widgets to one Action enum. Retain practical legacy aliases (p, c, x/y, parameter pairs, preset cycling), but do not encode behavior directly in key handlers. Add a searchable/help overlay.
Phase 4.2 — Shared presentation primitives
Substep 4.2.1 — Scalar texture uploader
Convert CPU scalar fields to reusable raylib textures without allocating every frame. Start with a portable normalized or packed upload path; retain original f32 values in the model. Make filtering (nearest default, optional linear) explicit.
Substep 4.2.2 — Palettes
Implement named versions of all seven legacy palettes in one shared Rust/GLSL definition:
- phase hue on black;
- white on black;
- black on white;
- value rainbow;
- brown/green;
- gold/brown;
- phase-shifted value rainbow.
Sanitize palette inputs and show a legend/range. Palette phase changes in units per second.
Substep 4.2.3 — Cameras
- 2-D uses a coherent
Camera2D, cursor-centered wheel zoom, drag pan, reset, and fit-to-view. - 1-D and 3-D placeholders use their own presentation state; do not overload simulation coordinates.
- Window resize changes presentation only, never simulation shape or state.
Phase 4.3 — Model and logic views
Substep 4.3.1 — Live state
Render the selected field at correct aspect ratio with periodic coordinate indicators. Display generation, update rate, render FPS, shape, seed, preset, dynamics, integrator, and backend.
Substep 4.3.2 — Read-only inspection
Provide a tab/grid selector for:
A,M,N,S, derivative/increment, and proposed next state;- raw/normalized disk and ring kernels;
- rule surface
S(N,M)with labeled axes and current(N,M)probe; - radial kernel profile and numeric value-under-cursor.
Inspection never modifies state. Keep c as an optional “next primary view” shortcut.
Substep 4.3.3 — Compare layout
Support at least a two-pane mode, for example A | S, M | N, or kernel | radial profile. All panes refer to the same committed generation and show stale-generation warnings if an async backend is introduced later.
Phase 4.4 — Configuration UI
Build a collapsible raylib-native panel (or a deliberately selected raygui binding after a compatibility spike) with sections:
- run/preset/variant;
- domain and initializer;
- rule intervals and curves;
- dynamics/integrator/timestep and RK4 relaxation reference when applicable;
- kernel geometry;
- backend, FFT algorithm, and performance;
- view/palette/camera;
- capture and diagnostics.
Classify edits visibly:
- Hot: presentation and pointwise rule edits; apply immediately.
- Warm: kernel geometry/timestep/integrator; rebuild caches and invalidate integration history as specified.
- Cold: shape, topology, variant, or backend; require transactional recreate/apply.
Provide sliders plus precise numeric entry. Show validation inline; never silently clamp model parameters to UI ranges.
Phase 4.5 — Presets, sessions, and capture
Substep 4.5.1 — Preset browser
Filter by variant/dimension/tags, show provenance and notes, and indicate modified (“dirty”) parameters. Applying a preset is transactional and logs the resulting run descriptor.
Substep 4.5.2 — Persistence
Persist user preferences separately from model presets. Add “save as user preset,” not append-to-bundled-file behavior. Save enough precision for exact round trips.
Substep 4.5.3 — Exports
Provide:
- viewport PNG, optionally with HUD;
- native field image with active palette;
- restart-state export (field plus metadata, numerical history resets on load);
- exact continuation checkpoint with integrator/variant history;
- metadata sidecar containing run descriptor and generation.
Use collision-safe timestamp/sequence names in the platform pictures/data directory.
Phase 4.6 — Robustness and UX tests
- Resize/minimize/fullscreen/high-DPI smoke tests.
- Launch from arbitrary working directories.
- Repeated valid/invalid warm and cold edits.
- Pause and single-step accuracy.
- Screenshot/state export while paused and running.
- Keyboard focus does not alter parameters while numeric input is active.
- Visible fallback if texture/shader creation fails.
Deliverables
- Portable raylib application using the CPU planar backend.
- Discoverable controls, inspectors, preset browser, and exports.
- Stable action, camera, palette, and presentation abstractions for later variants.
Exit gate
- A user can launch, choose a preset, reset with a seed, run/pause/step, edit parameters, and inspect every base pipeline channel.
- Headless and interactive CPU runs produce identical model states for equal commands.
- Resize and fullscreen never reset simulation.
- No inspection mode destroys or advances state.
- The application works outside the repository and reports failures visibly.