API Reference
SceneCreator is a single class that wraps a Three.js scene, camera, renderer and orbit controls, with helpers for loading, lighting, animation, physics and picking. Every configuration method returns this, so calls chain.
import { SceneCreator } from "3d-scene-creator";
import * as THREE from "three";
const scene = new SceneCreator(container)
.addLighting()
.addControls()
.addSkybox("/panorama.jpg");
three is a peer dependency (install it yourself). cannon-es (MIT) powers the physics API and is imported on demand, so bundlers code-split it: apps that never call enablePhysics() don't load it.๐๏ธ Constructor
Create a scene. If a container is given, the renderer is attached and the render loop starts immediately.
๐ฆ Loading models
Load a model and add it to the scene. Uses THREE.ObjectLoader by default; pass any loader (e.g. GLTFLoader) to override.
Load a glTF/GLB and return a fresh clone of its scene, not added to the graph. Each URL is fetched and parsed once and cached, so repeated calls are cheap. Ideal for instancing static props. Position it and add it yourself, then call applyShadows().
Object3D.clone(), which does not duplicate skeletons. For animated/rigged models use loadAnimatedModel instead.Load a rigged glTF, add it to the scene, apply shadows, build an AnimationMixer and wire it into the render loop. Returns a handle to control playback. The render loop keeps drawing while a clip plays.
const robot = await scene.loadAnimatedModel("/robot.glb", { autoplay: "Idle" });
robot.play("Walking"); // cross-fade to a looping clip
robot.play("Wave", { loop: false }); // play once, hold last frame
robot.stop(); // fade the current clip out
๐ก Lighting & scene
Add a ready-to-use rig: a hemisphere fill, a shadow-casting key light, an opposite fill light, soft shadows and ACES Filmic tone mapping. Every part is configurable and has sensible defaults. Adds lights without clearing existing ones, so call it once per scene.
Flag every mesh currently in the scene as a shadow caster and/or receiver. Call it after adding your meshes (and after addLighting() with shadows on).
Add a 360ยฐ background. Pass a panoramic image URL, or omit it and pass a solid color.
๐ฎ Controls & camera
Attach OrbitControls with damping and sensible limits. Any OrbitControls property can be overridden, including autoRotate, enableZoom, enablePan and the distance/angle limits.
Animate the camera (and optionally the orbit target) to a new position over ~3 seconds. Controls are disabled during the move and restored when it finishes.
Animate the camera back to its initial position and target.
๐ฌ Animation
Property tweens are powered by tween.js (MIT) and target objects by their name.
Tween every mesh material color under the named object toward a target color.
Tween the named object's position toward a target vector.
Tween the named object's material opacity (materials are set transparent automatically).
Register (or unregister) an AnimationMixer so it is advanced automatically every frame. The render loop keeps drawing while any mixer is registered. loadAnimatedModel() does this for you.
๐งฒ Physics
Optional rigid-body simulation powered by cannon-es (MIT). Enable it once, then link meshes to bodies; the world is stepped and synced every frame.
Load cannon-es on demand and create the CANNON.World with the given gravity and default contact material. This is async: await it before adding bodies. No-op if physics is already enabled.
await scene.enablePhysics({ gravity: [0, -12, 0], restitution: 0.4 });
scene.addGround();
const body = scene.addBody(mesh, { mass: 1, shape: "box" });
Give a mesh a rigid body and keep the two in sync each frame. The collision shape is derived from the mesh's bounding box (or sphere) and its scale. Requires enablePhysics() first.
Add a static, infinite horizontal ground plane.
Remove a body from the world and stop syncing its mesh.
scene.physicsWorld for constraints, custom materials and collision events.๐ฏ Picking
Raycast-based interaction with click-vs-drag discrimination, so orbiting never fires a stray click. Tune the threshold (pixels) via scene.clickDragThreshold (default 6).
Enable pointer picking and register callbacks. Hover fires with the object or null; click and right-click fire with the picked object.
Disable picking and detach its listeners.
Return the currently hovered/selected object, or null.
Programmatically raycast at normalized device coordinates (each in the range -1 to 1) and return the closest hit.
โก Rendering & lifecycle
The loop is render-on-demand: a frame is drawn only when the camera moves, a tween/mixer/physics body is active, or an additional render function is set.
Start or stop the requestAnimationFrame loop. The loop starts automatically when a container is attached.
Register a callback run every frame (e.g. for custom per-frame logic). Setting it also keeps the loop rendering continuously.
Append the canvas to a container, size it, and start the render loop. Called for you when a container is passed to the constructor.
Stop rendering, clear tweens, mixers and physics, dispose the renderer and remove the canvas. Call it when you are done to avoid leaks.
๐ง Properties
SceneCreator is a thin layer: the raw Three.js objects stay accessible for anything the helpers don't cover.
scene.scene.add(...).addControls().enablePhysics().๐ Types
false to omit.false to omit.A subset of OrbitControls properties (enableDamping, dampingFactor, minDistance, maxDistance, maxPolarAngle, enableZoom, enablePan, rotateSpeed, ...) plus any extra key, all assigned onto the controls instance.
false for none). Default: first clip