Three.js Cheatsheet

Meshes and Groups

Use this Three.js reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Mesh

const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

// Multiple materials per geometry (one per group)
const mesh = new THREE.Mesh(geometry, [mat0, mat1, mat2]);

// Geometry groups map faces to material indices
geo.addGroup(start, count, materialIndex);

Object3D — The Base Class

Every visible and invisible object (Mesh, Group, Light, Camera, Bone…) extends Object3D.

Position, Rotation, Scale

// Position
mesh.position.set(x, y, z);
mesh.position.x = 1;
mesh.position.copy(otherMesh.position);
mesh.position.add(new THREE.Vector3(0, 1, 0));

// Rotation (Euler, radians, default order 'XYZ')
mesh.rotation.set(rx, ry, rz);
mesh.rotation.y = Math.PI / 4;
mesh.rotation.reorder('YXZ');   // change application order

// Quaternion (alternative to Euler — no gimbal lock)
mesh.quaternion.setFromEuler(new THREE.Euler(rx, ry, rz));
mesh.quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
mesh.quaternion.slerp(targetQuat, 0.1); // smooth interpolation

// Scale
mesh.scale.set(2, 2, 2);
mesh.scale.multiplyScalar(0.5);

Hierarchy & Scene Graph

parent.add(child);          // add child; child inherits parent transform
parent.remove(child);       // detach child
child.removeFromParent();   // detach self (r133+)

mesh.parent;                // direct parent (null if root)
mesh.children;              // array of direct children

// Traverse entire subtree
mesh.traverse((node) => {
  if (node.isMesh) node.castShadow = true;
});

// Traverse only visible nodes
mesh.traverseVisible((node) => { /* ... */ });

// Find descendants
mesh.getObjectByName('Wheel_FL');
mesh.getObjectByProperty('type', 'PointLight');

World vs Local Transforms

// Get world position (accounts for all parent transforms)
const worldPos = new THREE.Vector3();
mesh.getWorldPosition(worldPos);

const worldQuat = new THREE.Quaternion();
mesh.getWorldQuaternion(worldQuat);

const worldScale = new THREE.Vector3();
mesh.getWorldScale(worldScale);

const worldDir = new THREE.Vector3();
mesh.getWorldDirection(worldDir);   // -Z direction in world space

// Convert between spaces
const localPt  = mesh.worldToLocal(worldPoint.clone());
const worldPt  = mesh.localToWorld(localPoint.clone());

lookAt

mesh.lookAt(new THREE.Vector3(0, 0, 0));  // point +Z toward target
mesh.lookAt(targetMesh.position);

// lookAt uses world coordinates; call after setting position

Matrix

mesh.updateMatrix();           // recompute local matrix from position/rotation/scale
mesh.updateMatrixWorld(true);  // recompute world matrix recursively
mesh.matrix;                   // local transform Matrix4
mesh.matrixWorld;              // world transform Matrix4

// Lock auto-update if you set matrix manually
mesh.matrixAutoUpdate = false;
mesh.matrix.compose(position, quaternion, scale);
mesh.matrix.decompose(position, quaternion, scale);

Identity and Naming

mesh.name   = 'PlayerBody';
mesh.uuid;                     // auto-generated unique ID
mesh.userData = { hp: 100 };   // arbitrary data storage, not used by Three.js
mesh.visible = false;
mesh.renderOrder = 1;          // higher = drawn later (useful for transparency sort)
mesh.layers.set(1);            // visibility layer (default 0)
camera.layers.enable(1);       // camera must see the same layer

Groups

const group = new THREE.Group();
group.add(meshA);
group.add(meshB);
scene.add(group);

// Transform entire group together
group.position.set(5, 0, 0);
group.rotation.y = Math.PI;
group.scale.setScalar(2);

// Groups are Object3D — all methods apply
group.traverse((child) => { /* ... */ });

Pivot Offset Pattern

// Rotate around an arbitrary pivot by nesting
const pivot = new THREE.Group();
pivot.position.set(pivotX, pivotY, pivotZ);
pivot.add(mesh);
mesh.position.set(-pivotX, -pivotY, -pivotZ); // offset so pivot is at pivot point
scene.add(pivot);
pivot.rotation.y += 0.01; // orbits around the pivot

Instanced Mesh

Use InstancedMesh to render thousands of identical geometry+material pairs in a single draw call.

const count = 10000;
const iMesh = new THREE.InstancedMesh(geometry, material, count);
iMesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage); // if updated per frame

const dummy = new THREE.Object3D();
for (let i = 0; i < count; i++) {
  dummy.position.set(
    (Math.random() - 0.5) * 20,
    (Math.random() - 0.5) * 20,
    (Math.random() - 0.5) * 20
  );
  dummy.rotation.set(
    Math.random() * Math.PI,
    Math.random() * Math.PI,
    0
  );
  dummy.scale.setScalar(Math.random() * 0.5 + 0.5);
  dummy.updateMatrix();
  iMesh.setMatrixAt(i, dummy.matrix);
}
iMesh.instanceMatrix.needsUpdate = true;
scene.add(iMesh);

// Per-instance color
iMesh.setColorAt(i, new THREE.Color(Math.random(), Math.random(), Math.random()));
iMesh.instanceColor.needsUpdate = true;

// Update one instance later
dummy.position.y = 5;
dummy.updateMatrix();
iMesh.setMatrixAt(targetIndex, dummy.matrix);
iMesh.instanceMatrix.needsUpdate = true;

// Raycasting works automatically
// Reduce visible count without rebuilding
iMesh.count = 500;

Lines and Points

// Line (two points)
const geo = new THREE.BufferGeometry().setFromPoints([
  new THREE.Vector3(0, 0, 0),
  new THREE.Vector3(1, 1, 0),
]);
const line = new THREE.Line(geo, new THREE.LineBasicMaterial({ color: 0xffffff }));

// LineLoop — closed
const loop = new THREE.LineLoop(geo, mat);

// LineSegments — pairs of points (no join)
const segs = new THREE.LineSegments(geo, mat);

// Points / particles
const points = new THREE.Points(geo, new THREE.PointsMaterial({ size: 0.05 }));

Shadows

// Renderer
renderer.shadowMap.enabled = true;
renderer.shadowMap.type    = THREE.PCFSoftShadowMap;

// Light
dirLight.castShadow              = true;
dirLight.shadow.mapSize.width    = 2048;
dirLight.shadow.mapSize.height   = 2048;
dirLight.shadow.camera.near      = 0.5;
dirLight.shadow.camera.far       = 50;
dirLight.shadow.camera.left      = -10;  // ortho frustum for directional
dirLight.shadow.camera.right     = 10;
dirLight.shadow.camera.top       = 10;
dirLight.shadow.camera.bottom    = -10;
dirLight.shadow.bias             = -0.001;  // fixes shadow acne
dirLight.shadow.normalBias       = 0.02;    // alternative to bias

// Objects
mesh.castShadow    = true;   // casts a shadow
mesh.receiveShadow = true;   // receives shadows from others
ground.receiveShadow = true;

// Shadow camera helper (debug)
scene.add(new THREE.CameraHelper(dirLight.shadow.camera));

Useful Object3D Methods Reference

MethodDescription
.add(...objects)Attach children
.remove(...objects)Detach children
.removeFromParent()Detach from parent
.clear()Remove all children
.clone(recursive)Deep copy
.copy(source, recursive)Copy properties from source
.lookAt(v)Orient +Z toward world point
.traverse(cb)Visit all descendants
.traverseVisible(cb)Visit only visible descendants
.getObjectById(id)Find descendant by id
.getObjectByName(name)Find descendant by name
.getWorldPosition(v)Write world position to v
.getWorldQuaternion(q)Write world quaternion to q
.getWorldScale(v)Write world scale to v
.getWorldDirection(v)Write world -Z direction to v
.localToWorld(v)Transform point local→world (mutates v)
.worldToLocal(v)Transform point world→local (mutates v)
.applyMatrix4(m)Apply a Matrix4 transform
.applyQuaternion(q)Rotate by quaternion
.translateOnAxis(axis, dist)Translate along a local axis
.rotateOnAxis(axis, angle)Rotate around a local axis
.rotateOnWorldAxis(axis, angle)Rotate around a world axis

Cloning and Disposal

// Clone a mesh (geometry and material are shared by default)
const clone = mesh.clone();
// Deep clone with independent geometry/material
const deepClone = mesh.clone();
deepClone.geometry = mesh.geometry.clone();
deepClone.material = mesh.material.clone();

// Dispose
function disposeMesh(mesh) {
  mesh.geometry.dispose();
  if (Array.isArray(mesh.material)) {
    mesh.material.forEach(m => m.dispose());
  } else {
    mesh.material.dispose();
  }
  scene.remove(mesh);
}