Three.js Tracking Shot: Parent Camera to Moving Mesh

Creating a dynamic tracking shot in Three.js is highly efficient when you leverage the 3D scene graph by parenting a PerspectiveCamera directly to a moving mesh. This article explains how to establish this parent-child relationship so the camera automatically inherits the position, rotation, and scale of the target object. By using this native Three.js behavior, you eliminate the need to manually calculate and update the camera’s coordinates in your animation loop, resulting in a smooth, cinematic follow-cam effect.

Understanding the Scene Graph Parent-Child Relationship

In Three.js, every object (including meshes and cameras) inherits from Object3D. When you add one Object3D as a child of another, the child enters the local coordinate system of the parent.

By default, a camera is added directly to the Scene. However, if you add the PerspectiveCamera as a child of a moving Mesh, any translation or rotation applied to the mesh automatically applies to the camera.

Step-by-Step Implementation

1. Create the Mesh and the Camera

First, instantiate your moving mesh and the perspective camera.

import * as THREE from 'three';

// Create the scene
const scene = new THREE.Scene();

// Create the target mesh (e.g., a car or player character)
const geometry = new THREE.BoxGeometry(2, 1, 4);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const playerMesh = new THREE.Mesh(geometry, material);
scene.add(playerMesh);

// Create the PerspectiveCamera
const camera = new THREE.PerspectiveCamera(
  75, 
  window.innerWidth / window.innerHeight, 
  0.1, 
  1000
);

2. Parent the Camera to the Mesh

Instead of adding the camera to the scene, add it directly to the playerMesh.

// Add the camera as a child of the mesh
playerMesh.add(camera);

3. Position the Camera in Local Space

Because the camera is now a child of the mesh, its position property defines its offset relative to the mesh’s center, rather than the center of the world.

To place the camera behind and slightly above the mesh to create a classic third-person tracking perspective:

// Position the camera 5 units behind (Z) and 3 units up (Y) relative to the mesh
camera.position.set(0, 3, -5);

// Point the camera to look at the center of its parent mesh
camera.lookAt(playerMesh.position);

Note: Because the camera’s local coordinate system is now relative to the parent, camera.lookAt(0, 0, 0) also works to point the camera directly at the center of the parent mesh.

4. Move the Mesh in the Animation Loop

In your render loop, apply movement or rotation to the mesh. The camera will automatically track with it without any additional camera updates.

const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);

function animate() {
  requestAnimationFrame(animate);

  // Move the mesh forward along its local Z-axis
  playerMesh.translateZ(0.1);

  // Rotate the mesh to see the camera follow the turn
  playerMesh.rotation.y += 0.01;

  renderer.render(scene, camera);
}

animate();

Key Considerations