Why Three.js instead of WASM?

Scenaven deliberately renders with Three.js + WebGL in the browser, while VTK runs on mesh-api. That is different from WASM-first viewers such as Vu-Verse, which compile a native desktop stack (VTK, Qt/QML) into WebAssembly so the full pipeline can run inside the tab.

Two ways to put simulation on the web

Approach How it works Examples
WASM / native port Ship VTK (or similar) as WebAssembly; parse and filter in the browser Vu-Verse, Pyodide VTK experiments
Hybrid server + WebGL VTK on the server; stream surfaces + metadata; WebGL for presentation Scenaven
WebAssembly WebAssembly
Three.js Three.js
VTK (server) VTK (server)
OpenUSD stream OpenUSD stream

Why Scenaven chose Three.js

1. Simulation data belongs on the server

Volumetric VTK and VTKHDF files are often gigabytes. Loading the full grid into WASM memory:

  • Blows past typical browser tab limits
  • Duplicates storage (server cache + client heap)
  • Makes first paint slow while WASM initializes and parses

Scenaven keeps the canonical VTK session on mesh-api and sends only renderable surface geometry plus field arrays aligned to that surface. The browser visualizes; it does not re-host the simulation.

2. One VTK stack, not two

WASM viewers either embed a second VTK build in the client or reimplement filters. Scenaven already runs VTK in Python for:

  • Upload conversion
  • Clip, warp, extract compile
  • Timeline bake
  • Python REPL analytics

A Three.js client reuses that stack. Clip in the sidebar and clip in Python hit the same session mesh — no drift between “what you see” and “what you compute.”

3. Smaller, faster client bundle

WebAssembly VTK ports ship large binaries (often tens of MB) plus worker threads and filesystem shims. The Scenaven embed is a presentation skin: Three.js, USD scene metadata, and UI controls. It loads quickly in iframes (Dash, portals, cloud shell) and updates without redeploying native WASM artifacts.

4. Embeddability and ops parity

Three.js fits the viewer-ui / mesh-api split:

  • viewer-ui — static embed, same Docker image everywhere
  • mesh-api — compute boundary (cloud GCS or on-prem volume)

WASM-heavy clients tend to couple compute and UI in one fat binary, which is harder to proxy, scale, and secure per tenant.

5. Python analytics without Pyodide

Vu-Verse-style workflows often want NumPy/VTK scripting. Scenaven provides that through a server REPL on the active session — not a second Python runtime in WASM. That avoids duplicating mesh-api, keeps volume access server-side, and matches how cloud SaaS scales (see ADR: server-side Python REPL).

What Three.js is responsible for

Three.js is the right tool for the presentation layer:

  • Camera, orbit, pan, zoom
  • Scalar colormaps and legends
  • Display styles (surface, wireframe, points)
  • Picking, probes, rubber-band extract UI
  • Time scrubbing UI (geometry fetched per frame)

These are GPU-friendly, interactive, and do not need VTK in the tab.

What stays off the client (on purpose)

Task Why not WASM in the browser
Full volume parse Memory and startup cost
Clip / warp on volumetric source Needs canonical VTK dataset
Heavy time-step bake CPU-bound; belongs on mesh-api
User Python scripts Security, quotas, session SSOT

When WASM-first makes sense

WASM/native ports are a valid choice when:

  • Datasets are small enough to fit comfortably in client memory
  • You need offline-only workflows with no server
  • You are migrating an existing desktop app verbatim

Scenaven targets engineering-scale simulation with cloud and on-prem Docker — so the hybrid model wins.

The pipeline in practice

VTK/HDF enters mesh-api → filters compile on the server → OpenUSD packages the scene contract → Three.js renders the stream. You get Vu-Verse-class inspection UX without shipping VTK inside every browser tab.

Related topics