Skip to content

WASM lib addons / web demo - #186

Open
vespakoen wants to merge 8 commits into
aewallin:masterfrom
vespakoen:feat/wasm-lib-addons
Open

vespakoen wants to merge 8 commits into
aewallin:masterfrom
vespakoen:feat/wasm-lib-addons

Conversation

@vespakoen

@vespakoen vespakoen commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

vibe coded with chatgpt astra xhigh

DEMO: https://github.com/aewallin/opencamlib/actions/runs/39053516922/artifacts/12108573749

This follows PR #184, using cc0a45d as the baseline. It addresses native-object lifetime and repeated-run issues across the bindings, adds optional WebAssembly threading and adaptive-waterline batching, and provides a browser demo with reproducible builds and opt-in GitHub Pages deployment.

Core correctness and ownership

  • Give operations, composite cutters, and appended path spans explicit ownership. Share immutable triangle snapshots between spatial indexes to avoid unnecessary copies while keeping indexed geometry alive.
  • Make repeated path drop-cutter and waterline runs replace their previous results. Respect the minimum Z in adaptive path sampling and support line/arc paths consistently across the bindings.
  • Validate operation parameters and parse STL files transactionally. Invalid, non-finite, or degenerate geometry raises an error without leaving a partially populated surface.

WebAssembly threading and wrapper simplification

Add an optional pthread backend for independent point, fiber, and span work. Thread counts are bounded by the available worker pool; worker failures are propagated after started workers have been joined. Adaptive waterline batches midpoint fibers across both sampling directions, then restores their ordering before contour assembly. The serial path retains its recursive traversal. Parallel refinement retains intermediate fibers and therefore uses more temporary memory.

The JavaScript API keeps automatic startup handling: callers can construct an operation and call its methods before the WASM runtime is ready. Each operation waits on one initialization promise. Native calls are synchronous, so promise callback ordering preserves invocation order without maintaining a separate chain after every call.

Input replacement shares one cleanup path for surfaces, cutters, and paths. dispose() is idempotent, waits for previously requested calls, and rejects subsequent use. WASM objects require explicit disposal; native Node wrappers also support cleanup through GC. Runtime initialization failures propagate consistently to every call. Invalid parameter calls reject without preventing later valid calls.

The promise API does not itself move computation off the calling thread. The demo runs the engine in a Web Worker so the viewer remains responsive in both serial and threaded modes.

Browser demo

  • Generate one HTML file embedding the Tux STL and both WASM runtimes; load pinned Three.js and addons from a CDN. Users can upload ASCII/binary STLs locally or return to Tux.
  • Expose uniform/adaptive drop-cutter and waterline algorithms, cutter presets, sampling presets, and thread selection. Fine sampling defaults to 0.05 mm sample spacing and 0.005 mm minimum spacing; uploads preserve user-selected sampling values.
  • Set Start Z to the uploaded model's top and provide Model top / Top minus step shortcuts. Accept positive safe integers for waterline level counts, with a finite resulting Z range. Make dimension buttons increment by 0.1 mm while allowing finer typed values.
  • Show a loading overlay, elapsed time, cancellation, per-level waterline timings, toolpath statistics, and cutter-tip X/Y/Z during playback. Render the cutter's full tip-to-top length and include it in camera fitting. Export separate path segments as JSON.
  • Reject waterline configurations whose cutter cannot reach the model top from the lowest requested Z. Short cutters can miss upper surface contacts and produce false interior contours; the demo reports the required length rather than silently changing the cutter. This is a conservative UI precondition, not a fix to the underlying finite-cutter algorithm or a tool-holder collision check.

Sampling presets control sampling density, not a guaranteed machining tolerance. Accuracy also depends on the STL, cutter geometry, pass spacing, step down, and machining setup.

Build, CI, and publishing

Compile the core once per configuration and share it between bindings and tests. Add debug, release, OpenMP, sanitizer, and serial/threaded demo presets. Demo builds enable Release optimization, interprocedural optimization, and native WASM exceptions; threading and native exceptions remain opt-in for general library builds.

CI builds and tests the demo, uploads its generated HTML and screenshots, compares ordered toolpaths across backends, and exercises both WASM exception modes. Browser tests generate their STL fixtures and do not depend on private files. Generated HTML, binaries, caches, logs, and screenshots stay out of source control.

An opt-in Pages job publishes the tested HTML artifact after the core and binding/browser checks pass on the default branch. Enable GitHub Actions as the Pages source and set the repository variable OCL_PUBLISH_DEMO=true. Pull requests, tags, and other branches do not deploy. The artifact contains only the generated index.html.

The demo selects its threaded runtime when COOP/COEP isolation headers are available. GitHub Pages uses the serial fallback because it does not supply those headers; the included local server enables threading. Both modes keep calculations in a background worker.

Compatibility

C++ consumers must rebuild because operation ownership, spatial-index storage, and class layouts change. Operations are noncopyable. Path supports deep copying and owns spans added through append; directly inserted span pointers remain caller-owned. Invalid inputs now raise exceptions. Native ASCII STL parsing preserves double precision instead of rounding through float32.

The wrapper simplification preserves the existing public promise-based operation API. Native WASM exceptions used by the demo require a supporting browser/runtime.

Validation

Completed locally on macOS arm64:

  • Debug, Release/OpenMP, and ASan/UBSan CTest suites: 9/9 each.
  • Serial and threaded WASM demo builds: 2/2 CTests each, including actual concurrency and serial/parallel geometry equivalence.
  • All 12 ordered-path fixtures match across C++, Python, Node, serial WASM, and threaded WASM.
  • Wrapper regressions pass for calls and disposal before startup, ordering after startup, invalid-parameter recovery, and repeated initialization failures.
  • All four algorithms pass browser package checks on both the page and a dedicated Web Worker with four threads.
  • Demo browser regression passes for threaded, serial, and file:// loading; uploads; presets; cancellation; exports; Z controls; full cutter geometry; and desktop/mobile layouts. A Pages-style /opencamlib/ URL without isolation headers loads successfully and produces the same ordered coordinates as the threaded build.
  • Repeated HTML packaging with identical inputs produces byte-identical output. TypeScript builds, JS/Python syntax checks, workflow YAML parsing, and Git whitespace checks pass.
  • An independent CMake consumer builds and runs against the installed C++ library. This host has older headers under /usr/local/include; the consumer uses CMAKE_NO_SYSTEM_FROM_IMPORTED=ON to prioritize the selected installation.

The updated CI workflow and Pages deployment have not yet run remotely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant