fancy-3d-three
@particle-academy/fancy-3d-three
three.js adapter for fancy-3d — WebGL renderer + the React components (Stage, Monitor, Card3D) that mount onto a three.js Scene. Mirrors fancy-3d-babylon, three.js underneath.
$
npm install @particle-academy/fancy-3d-threeAuthoring surface
Humans compose it
Controlled value + onChange, JSON-friendly props, terse defaults — so people (and agents) build it fast.
Inhabited surface
Agents drive it over MCP
A bridge in @particle-academy/agent-integrations exposes typed tools — agents read and mutate state through stable handles, never DOM scraping.
scene_add_nodescene_movescene_paint
Why
Immersive 3D engines almost always abandon everything the DOM is good at — real text, accessibility, event handling, the React components you already wrote — the moment you cross into WebGL.
fancy-3d refuses that trade: it treats React surfaces and 3D scenes as peers, and its engine-agnostic core (Scene types + a CanvasEngine interface + a DOM/CSS-3D renderer) carries no WebGL dependency at all. This package is the three.js adapter that lets the same Scene JSON render through a full WebGL renderer — the same data that paints on DOM or Babylon. That keeps it a proper Human+ surface: a <Monitor> renders live, interactive React onto a 3D screen (not a rasterized texture), while agents drive the scene through the scene_* MCP bridge in agent-integrations — engine-agnostic, so neither human nor agent is rewriting anything to switch renderers.What
The exported surface mirrors the Babylon adapter so engines are swappable, not rebuilt. From
@particle-academy/fancy-3d-three/engine you get threeEngine, a CanvasEngine whose EngineHandle.root is the live THREE.Scene. From @particle-academy/fancy-3d-three/react come the declarative components <Stage> (owns the WebGLRenderer + OrbitControls camera + render loop) and <Monitor> (projects a bezel mesh's corners to screen space each frame and maps a DOM overlay onto the 3D quad via a CSS matrix3d homography), plus the useStage() hook. The package root exports the imperative createThreeAdapter for painting a JSON Scene to textured planes, the sceneBounds helper, the primitive builders (createCard3D, createMonitor, createSign, createPanel, createCurvedPanel, createSphere, createBillboard, createCylinder, …), and the layout helpers placeOnGrid, placeOnWall, placeOnArc (aliased placeOnCylinder), placeOnPath, and placeOnSphere — each mutating obj.position / obj.rotation in place. Every primitive, layout, and component name matches fancy-3d-babylon, so a scene authored for one renders recognizably on the other and the two never depend on each other. three is a peer dependency — only consumers actually building 3D scenes install it, so the core stays lightweight for everyone else. The full primitive and option reference lives in the three.js documentation.How
Install the three packages together:
npm install @particle-academy/fancy-3d @particle-academy/fancy-3d-three three — none pull in the others. Mount the engine onto the core's <Canvas>: import { Canvas } from "@particle-academy/fancy-3d"; import { threeEngine } from "@particle-academy/fancy-3d-three/engine"; then render <Canvas engine={threeEngine} style={{ height: 480 }} />. For live React on a 3D screen, the smallest scene is a <Stage> wrapping a <Monitor>: <Stage style={{ height: 520 }}><Monitor position={[0, 1.6, 0]} width={4} height={2.4}><Card>…real react-fancy…</Card></Monitor></Stage> — the <Monitor> takes position, width/height, and an optional rotationY. To wrap a JSON Scene onto a curved wall, build meshes with the adapter and place them with a layout helper: const bounds = sceneBounds(scene) then for each node placeOnArc(node, rendered, bounds, { radius: 6 }) (swap in placeOnGrid, placeOnSphere, or placeOnPath for other arrangements). Browse the three.js examples for scene inspiration you can reproduce through the same engine-agnostic API.Components
4 components · click any tile for a full demo, source, and install snippet.
