An interactive browser laboratory that connects a sliced Micro-Benchy exposure path to deterministic reaction–diffusion polymerization and development.
- Parameter-driven Micro-Benchy slicing with layer, hatch, contour, scan-speed, power, and motion controls
- Versioned deep links from an illuminated 2PP resin in OpticalSetup, with compatible pulsed-laser parameters and a uniquely traced objective NA validated and prefilled before a run
- A timestamped Three.js exposure view with layer inspection
- One authoritative adaptive 3D Rust/WebAssembly resin simulation running inside a TypeScript Web Worker, never on the browser main thread
- Fixed-step fields for photoinitiator, oxygen, radical activity, conversion, developer, and remaining mass
- Development based on computed transport, conversion-dependent resistance, and remaining material
- Deterministic A/B replay for any changed model parameter
- Runtime diagnostics that identify the solver, grid, timestep, simulated model time, update rate, checksum, and Wasm memory use
The 3D viewport and the Reaction Lens are two views of the same numerical volume. The lens is an XY section at the layer selected by the shared section slider; it is not a second simulation. React and Three.js cannot mutate the authoritative chemistry state, and there is no decorative fallback if WebAssembly initialization fails.
flowchart TD
UI["React controls"] <--> W["TypeScript Web Worker"]
V["Three.js visualization"] <--> W
W <--> R["Rust/Wasm 3D resin volume"]
- React owns controls, interaction, run state, and the diagnostics display.
- Three.js owns visualization only.
- The Web Worker initializes Wasm, validates the snapshot contract, schedules simulation batches, handles messages, quantizes render inputs, and transfers JavaScript-owned buffers to the main thread.
- Rust owns the volume parameters, authoritative scan trajectory, numerical state, adaptive reaction/diffusion integration, development, deterministic checksum, and diagnostics.
The whole-Benchy view uses the official CreativeTools geometry and a dense, adaptive three-dimensional resin volume owned by Rust/Wasm. The worker loads a deterministic occupancy asset, selects a memory tier, schedules the scan, and copies compact render snapshots; TypeScript does not evolve chemistry.
The main render snapshot packs position, conversion, oxygen, radicals, and remaining mass for a bounded set of target and surrounding-resin voxels. A separate reusable slice buffer packs normalized oxygen, raw radical activity, conversion, remaining mass, and target occupancy for one complete XY grid plane. Both buffers are copied before transfer, so rendering never receives a mutable view of Wasm simulation memory.
Prerequisites:
- Node.js
>=22.13.0 - Rust
1.88.0, as pinned byrust-toolchain.toml - the
wasm32-unknown-unknownRust target wasm-pack 0.13.1- Linux with
flock,curl, and GNUtimeout
Install the pinned Rust toolchain and Wasm build tool:
rustup toolchain install 1.88.0 \
--profile minimal \
--component rustfmt \
--component clippy \
--target wasm32-unknown-unknown
cargo install wasm-pack --version 0.13.1 --lockedInstall JavaScript dependencies and start the development server:
npm run install:ci
npm run devnpm run dev first builds the browser-targeted Wasm package, then starts Vite
and Vinext. Generated Wasm bindings, Cargo targets, dependencies, build
artifacts, Wrangler state, and the Vinext font cache are excluded from Git.
Build the browser Wasm package directly:
npm run build:wasmCreate and validate a production build:
npm run build
npm run validate:artifact
npm run startThe production build compiles Rust to Wasm before Vinext. Artifact validation
requires an emitted .wasm file with the WebAssembly magic bytes, preventing a
JavaScript-only build from being mistaken for this milestone.
Run the complete validation suite:
npm run lint
npm run typecheck
npm run lint:rust
npm testFocused commands:
npm run test:rust
npm run parity
npm run test:wasm-worker
npm run test:production-worker- Rust tests cover deterministic replay, render-batch independence, parameter validation, diffusion-only and reaction-only behavior, oxygen recovery, radical decay, conversion monotonicity, development stability, and snapshot dimensions and ordering.
- The focused Wasm test builds the Node-targeted package and verifies the authoritative 3D volume, deterministic replay, and XY slice dimensions inside a worker thread.
- The production-worker test loads the browser-targeted bundle emitted by the production build, initializes its emitted Wasm asset off the main thread, exercises the initialization queue, validates transferred snapshot buffers, and checks the status and error message protocol.
npm run parityexercises the preserved native reference model against representative checkpoints captured by the temporary pre-migration TypeScript harness. Neither reference implementation is exported to the browser or retained in the production Wasm API.
The parity reference covers no exposure, stationary exposure, a moving scan, oxygen depletion and recovery, radical decay, conversion accumulation, development, reset, and replay. Representative pre-migration checkpoints include:
- stationary-exposure oxygen recovering from
0.019824after exposure to0.030758,0.153388, and0.497273after 60, 300, and 1200 dark steps; - radical activity reaching a maximum of
1.031305and decaying to numerical zero after 800 dark steps; and - mean remaining mass decreasing monotonically through development from
1.000000to0.987210,0.610093,0.233650, and0.007874.
Small f32/engine rounding differences are expected. Large or qualitative
field divergence is a parity failure.
For performance comparisons, benchmark identical release builds, parameters, exposure histories, and warm-up counts. Report both solver updates per second and cell-updates per second; do not compare the Web Worker batch cadence with a single-threaded development-mode JavaScript loop.
The Reaction Lens panel shows:
- the authoritative XY plane and physical Z position selected by the layer slider
- local target-cell oxygen, radical, conversion, and gel statistics
- adaptive 3D grid dimensions and quality tier
- volume updates per second, volume-owned memory, total Wasm memory, and replay checksum
The oxygen, radical, conversion, and remaining-mass selector is global: it changes both the 3D viewport and Reaction Lens. The section-cut toggle applies the selected Z plane to the Three.js specimen, while the slider requests the matching complete XY chemistry plane directly from Rust/Wasm.
Controls remain unavailable while Wasm initializes. A load or initialization failure produces a persistent, visible error and rejects queued commands; the application does not silently substitute fake chemistry.
This is an educational continuum model, not a calibrated prediction for a commercial photoresist.
- The bundled 3DBenchy is voxelized offline; arbitrary uploaded STL execution is not implemented yet.
- The seed is explicit replay metadata, but the preserved model currently has no stochastic term; equal inputs are deterministic without injected noise.
- Time is nondimensional, and parameters are not fitted to a particular resin.
- The whole-volume optical kernel is a circular-polarization vectorial Debye
integral normalized to fixed specimen power, with adaptively volume-averaged
two-photon
I²weights cached for under-resolved focal cells. An adjustable photoinitiator peak applies a normalized Gaussian spectral response with a fixed 160 nm FWHM; it is not a fitted material spectrum. Thermal effects, shrinkage, stress, and experimentally calibrated development kinetics remain outside scope. - Developer ingress uses deterministic distance from bath-accessible specimen surfaces rather than a fluid-flow or moving-interface solve.
The recommended next milestone is validated arbitrary-mesh import and experimental calibration against a named resin/process dataset.
app/page.tsx— search-facing field-guide homepage and laboratory entry pointapp/lab/page.tsx— interactive laboratory routeapp/lab-interface.tsx— slicer state, timeline, controls, and diagnosticsapp/guides/— scientific terminology, model-space, and parameter guidesapp/lab-viewport.tsx— client-only Three.js viewportapp/simulation.worker.ts— Wasm initialization, authoritative volume scheduling, selected-plane extraction, and immutable snapshot transferrust/reaction-lens/src/whole_volume.rs— dense 3D resin, vectorial PSF, scan timing, exposure chemistry, threshold conversion, and developmentrust/reaction-lens/— authoritative 3D volume core, native parity reference, and Rust testsscripts/build-wasm.sh— pinned browser and Node Wasm buildsworker/index.ts— deployable Cloudflare Worker entrytests/— worker initialization, build-artifact, and rendered-output checks
This software is licensed under the
WOFI Software License 1.0. It is registered as an Implementation of
the WOFI Idea
Browser-based two-photon lithography process simulator.
The repository-specific Idea and Implementation lineage is recorded in
wofi.json.
The deployed application carries the same artifacts at
/LICENSE.txt and
/wofi.json.
Pushes to main are deployed automatically to the existing Hetzner VPS. The
server polls GitHub approximately every three minutes, builds and tests the
exact revision, switches releases atomically, and rolls back if the local
health check fails. The server must have the pinned Rust toolchain, Wasm target,
and wasm-pack version installed before deployment. See
ops/hetzner/README.md.