Viewer3D — real-time 3D warehouse SCADA, ~30k pallets in vanilla three.js (no framework)

Hi everyone! :waving_hand:

I’d like to share Viewer3D, a real-time 3D SCADA visualization for warehouse / factory automation layouts — roller & chain conveyors, racking, twin-column stacker cranes, ring-shuttles, AGVs and forklifts. It renders a live warehouse floor and animates the full pallet lifecycle: pallets flow along a conveyor graph, a shuttle hands them off to a stacker crane, the crane puts them away into storage cells and retrieves them back out onto the outfeed lines.

:link: Live demo: Viewer 3D - Scada3D

(toggle 2D/3D and the light/dark theme from the top-right; nav-cube to orbit; E for edit mode)

What’s interesting (to me, anyway)

It’s built with plain three.js (r184) and vanilla ES modules — no React / R3F, no TypeScript, no bundler in development. The browser loads the modules natively; three.js comes straight from the jsdelivr CDN via an import map. All geometry is procedural — no Blender, no imported models — every mesh is generated in code from real warehouse dimensions (mm).

The whole thing is engineered to scale to tens of thousands of stock pallets and ~1,000 conveyor modules at 60 fps. On the full scene above it sits around ~90 fps with ~670 draw calls / ~2.6M triangles.

Tech / approach:

  • Custom minimal ECS drives the simulation systems (conveyor transport, crane put-away & retrieval, shuttle transfer, cradle lifts, owner-follow), with memoized queries so most frames are cache hits.
  • Draw-call reduction is the core strategy: InstancedMesh pools for repeated pallets / conveyor modules (one draw call per pool, instances stay raycast-pickable), static composites merged into single meshes with baked vertex colors, and edge outlines batched into one LineSegments per opacity group.
  • Render-on-demand + FPS cap: the RAF loop skips the render entirely when nothing moved, so an idle scene drops the GPU to ~0.
  • Smooth 2D ⇄ 3D camera: orthographic ↔ perspective via an element-wise projection-matrix morph (instead of a hard camera swap that pops), plus nav-cube rotations and fly-to/home tweens.
  • In-browser edit mode: move/rotate/resize/retype equipment, marquee multi-select with AutoCAD window/crossing semantics, magnet-snap conveyor connections, and layout save.
  • Backend is ASP.NET Core serving static files only — all logic is on the frontend.

The pallet movement you see is currently simulated; next step is feeding live positions from the backend via SignalR.

Happy to answer questions — especially about the instancing / draw-call batching or the 2D⇄3D projection morph. Feedback very welcome! :folded_hands:

8 Likes

It’s really smooth. I look forward to you sharing more details.:grinning_face:

It works in Chrome; but in Firefox, only the loading screen appears (no error messages).

1 Like

Very nice. Great look to it.

I did some conveyor belt stuff recently for fun, using the InstanceCurve modifier.. you might find it useful or fun to look at:

https://manthrax.github.io/InstanceCurve/index.html

1 Like