Skip to main content

3D Scenes

3D scene examples with camera controls, lighting, and surfaces.

Fixed In Frame Mobject Test

Demonstrates how to pin 2D text to the screen while the 3D camera is rotated, using addFixedInFrameMobjects. The text stays in the upper-left corner as a HUD overlay on top of ThreeDAxes.

Source Code
import { Text, ThreeDAxes, ThreeDScene, UL } from 'manim-web';

const scene = new ThreeDScene(document.getElementById('container'), {
width: 800,
height: 450,
backgroundColor: '#000000',
phi: 75 * (Math.PI / 180),
theta: -45 * (Math.PI / 180),
distance: 20,
fov: 30,
});

const axes = new ThreeDAxes({
xRange: [-6, 6, 1],
yRange: [-5, 5, 1],
zRange: [-4, 4, 1],
axisColor: '#ffffff',
tipLength: 0.3,
tipRadius: 0.12,
shaftRadius: 0.008,
});
const text3d = new Text({ text: 'This is a 3D text' });
scene.addFixedInFrameMobjects(text3d);
text3d.toCorner(UL);
scene.add(axes);
await scene.wait(999999);

Learn More: ThreeDScene · ThreeDAxes · Text


Three D Light Source Position

Shows a parametric sphere with checkerboard colors (RED_D, RED_E) on ThreeDAxes with custom point light positioning. Demonstrates Surface3D checkerboardColors and the Lighting system.

Source Code
import { ThreeDAxes, ThreeDScene, Surface3D, RED_D, RED_E } from 'manim-web';

const scene = new ThreeDScene(document.getElementById('container'), {
width: 800,
height: 450,
backgroundColor: '#000000',
phi: 75 * (Math.PI / 180),
theta: 30 * (Math.PI / 180),
distance: 20,
fov: 30,
});

const axes = new ThreeDAxes({
xRange: [-5, 5, 1],
yRange: [-5, 5, 1],
zRange: [-5, 5, 1],
axisColor: '#ffffff',
tipLength: 0.2,
tipRadius: 0.08,
shaftRadius: 0.01,
});

// Checkerboard sphere matching Python Manim's Surface(..., checkerboard_colors=[RED_D, RED_E])
const sphere = new Surface3D({
func: (u: number, v: number) => [
1.5 * Math.cos(u) * Math.cos(v),
1.5 * Math.cos(u) * Math.sin(v),
1.5 * Math.sin(u),
],
uRange: [-Math.PI / 2, Math.PI / 2],
vRange: [0, 2 * Math.PI],
uResolution: 15,
vResolution: 32,
checkerboardColors: [RED_D, RED_E],
});

// Light from above to match Python Manim's default top-lit appearance
scene.lighting.removeAll();
scene.lighting.addAmbient({ intensity: 0.3 });
scene.lighting.addPoint({ position: [0, 5, 0], intensity: 2.5, decay: 0 });

scene.add(axes);
scene.add(sphere);

await scene.wait(999999);

Learn More: ThreeDScene · ThreeDAxes · Surface3D · Lighting


Three D Surface Plot

Renders a 3D Gaussian surface plot on ThreeDAxes with checkerboard coloring (ORANGE, BLUE). The parametric surface maps (u,v) to a bell-shaped Gaussian peak, scaled by 2 and displayed with semi-transparent faces.

Source Code
import { ThreeDAxes, ThreeDScene, Surface3D, ORANGE, BLUE } from 'manim-web';

const scene = new ThreeDScene(document.getElementById('container'), {
width: 800,
height: 450,
backgroundColor: '#000000',
phi: 75 * (Math.PI / 180),
theta: -30 * (Math.PI / 180),
distance: 20,
fov: 30,
});

const sigma = 0.4;
const mu = [0.0, 0.0];

// Gaussian surface: parametric function mapping (u,v) to 3D point
// Surface3D func returns [x, y, z] used directly as THREE.js coordinates.
// Manim Z-up -> THREE.js Y-up: return [manimX, manimZ, -manimY]
const gaussSurface = new Surface3D({
func: (u: number, v: number) => {
const x = u;
const y = v;
const dx = x - mu[0];
const dy = y - mu[1];
const d = Math.sqrt(dx * dx + dy * dy);
const z = Math.exp(-(d * d) / (2.0 * sigma * sigma));
// Manim coords (x, y, z) -> THREE.js coords (x, z, -y)
return [x, z, -y];
},
uRange: [-2, 2],
vRange: [-2, 2],
uResolution: 24,
vResolution: 24,
checkerboardColors: [ORANGE, BLUE],
opacity: 0.85,
});

// Scale by 2 about origin (matches Python: gauss_plane.scale(2, about_point=ORIGIN))
gaussSurface.scale(2);

const axes = new ThreeDAxes({
xRange: [-6, 6, 1],
yRange: [-5, 5, 1],
zRange: [-4, 4, 1],
axisColor: '#ffffff',
tipLength: 0.3,
tipRadius: 0.12,
shaftRadius: 0.008,
});

scene.add(axes);
scene.add(gaussSurface);
await scene.wait(999999);

Learn More: ThreeDScene · ThreeDAxes · Surface3D


Three D Camera Rotation

Demonstrates ambient camera rotation around 3D axes with a circle, then animates the camera back to its original orientation. Shows beginAmbientCameraRotation, stopAmbientCameraRotation, and moveCamera methods.

Source Code
import { Circle, ThreeDAxes, ThreeDScene } from 'manim-web';

const scene = new ThreeDScene(document.getElementById('container'), {
width: 800,
height: 450,
backgroundColor: '#000000',
phi: 75 * (Math.PI / 180),
theta: 30 * (Math.PI / 180),
distance: 20,
fov: 30,
});

const axes = new ThreeDAxes({
xRange: [-6, 6, 1],
yRange: [-5, 5, 1],
zRange: [-4, 4, 1],
axisColor: '#ffffff',
tipLength: 0.3,
tipRadius: 0.12,
shaftRadius: 0.008,
});

const circle = new Circle({ radius: 1, color: '#FC6255' });
// Circle points are in Manim x-y plane but VMobject renders them
// directly in THREE.js coords. Rotate -90° around X to lay flat
// on the ground plane (THREE.js x-z = Manim x-y).
circle.rotation.x = -Math.PI / 2;

scene.add(circle, axes);

// Begin ambient camera rotation (theta rotates at 0.1 rad/s)
scene.beginAmbientCameraRotation(0.1);
await scene.wait(3);

// Stop rotation and animate camera back to original orientation
scene.stopAmbientCameraRotation();
await scene.moveCamera({
phi: 75 * (Math.PI / 180),
theta: 30 * (Math.PI / 180),
duration: 1,
});
await scene.wait(1);

// Reset camera orientation for replay
scene.setCameraOrientation(75 * (Math.PI / 180), 30 * (Math.PI / 180));

Learn More: ThreeDScene · ThreeDAxes · Circle


Three D Camera Illusion Rotation

Demonstrates the 3D illusion camera rotation that wobbles the camera by oscillating phi sinusoidally while rotating theta continuously. Creates a convincing 3D parallax effect around ThreeDAxes with a circle.

Source Code
import { Circle, ThreeDAxes, ThreeDScene } from 'manim-web';

const scene = new ThreeDScene(document.getElementById('container'), {
width: 800,
height: 450,
backgroundColor: '#000000',
phi: 75 * (Math.PI / 180),
theta: 30 * (Math.PI / 180),
distance: 20,
fov: 30,
});

const axes = new ThreeDAxes({
xRange: [-6, 6, 1],
yRange: [-5, 5, 1],
zRange: [-4, 4, 1],
axisColor: '#ffffff',
tipLength: 0.3,
tipRadius: 0.12,
shaftRadius: 0.008,
});

const circle = new Circle({ radius: 1, color: '#FC6255' });
// Circle points are in Manim x-y plane but VMobject renders them
// directly in THREE.js coords. Rotate -90° around X to lay flat
// on the ground plane (THREE.js x-z = Manim x-y).
circle.rotation.x = -Math.PI / 2;

scene.add(circle, axes);

// Begin 3D illusion camera rotation (theta rotates at 2 rad/s,
// phi oscillates sinusoidally for a wobbling 3D effect)
scene.begin3DIllusionCameraRotation(2);
await scene.wait(Math.PI / 2);

// Stop illusion rotation
scene.stop3DIllusionCameraRotation();

// Reset camera orientation for replay
scene.setCameraOrientation(75 * (Math.PI / 180), 30 * (Math.PI / 180));

Learn More: ThreeDScene · ThreeDAxes · Circle