3D Graphics in Manim
Create 3D visualizations with ThreeDScene.
ThreeDScene Basics
from manim import *
class Basic3D(ThreeDScene):
def construct(self):
# Set camera angle
self.set_camera_orientation(phi=75 * DEGREES, theta=-45 * DEGREES)
# Add 3D axes
axes = ThreeDAxes()
self.add(axes)Camera Orientation
class CameraOrientation(ThreeDScene):
def construct(self):
axes = ThreeDAxes()
# phi: angle from z-axis (0 = top view, 90 = side view)
# theta: rotation around z-axis
# gamma: roll angle
self.set_camera_orientation(
phi=75 * DEGREES,
theta=-45 * DEGREES,
gamma=0
)
self.add(axes)Animated Camera Movement
class AnimatedCamera(ThreeDScene):
def construct(self):
axes = ThreeDAxes()
self.add(axes)
self.set_camera_orientation(phi=75*DEGREES, theta=0)
# Animate camera movement
self.move_camera(phi=45*DEGREES, theta=90*DEGREES, run_time=3)Continuous Camera Rotation
class RotatingCamera(ThreeDScene):
def construct(self):
axes = ThreeDAxes()
self.add(axes)
self.set_camera_orientation(phi=75*DEGREES, theta=0)
# Start ambient rotation
self.begin_ambient_camera_rotation(rate=0.2)
self.wait(5)
self.stop_ambient_camera_rotation()3D Primitives
Sphere
class SphereExample(ThreeDScene):
def construct(self):
sphere = Sphere(radius=1, resolution=(20, 20))
sphere.set_color(BLUE)
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(sphere)Cube / Prism
class CubeExample(ThreeDScene):
def construct(self):
cube = Cube(side_length=2, fill_opacity=0.8)
cube.set_color(RED)
# Rectangular prism
prism = Prism(dimensions=[3, 1, 2])
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(cube)Cylinder / Cone
class CylinderCone(ThreeDScene):
def construct(self):
cylinder = Cylinder(radius=1, height=2, fill_opacity=0.8)
cone = Cone(base_radius=1, height=2, fill_opacity=0.8)
cylinder.shift(LEFT * 2)
cone.shift(RIGHT * 2)
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(cylinder, cone)Torus
class TorusExample(ThreeDScene):
def construct(self):
torus = Torus(major_radius=2, minor_radius=0.5)
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(torus)3D Axes
class ThreeDAxesExample(ThreeDScene):
def construct(self):
axes = ThreeDAxes(
x_range=[-4, 4, 1],
y_range=[-4, 4, 1],
z_range=[-4, 4, 1],
x_length=8,
y_length=8,
z_length=6,
)
# Add axis labels
x_label = axes.get_x_axis_label("x")
y_label = axes.get_y_axis_label("y")
z_label = axes.get_z_axis_label("z")
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(axes, x_label, y_label, z_label)Surface Plots
class SurfacePlot(ThreeDScene):
def construct(self):
axes = ThreeDAxes(x_range=[-3, 3], y_range=[-3, 3], z_range=[-2, 2])
# Function z = f(x, y)
surface = axes.plot_surface(
lambda u, v: np.sin(u) * np.cos(v),
u_range=[-3, 3],
v_range=[-3, 3],
resolution=(30, 30),
colorscale=[BLUE, GREEN, YELLOW, RED],
)
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(axes, surface)Surface Class (standalone)
class SurfaceExample(ThreeDScene):
def construct(self):
def param_func(u, v):
x = u
y = v
z = np.sin(np.sqrt(u**2 + v**2))
return np.array([x, y, z])
surface = Surface(
param_func,
u_range=[-3, 3],
v_range=[-3, 3],
resolution=(30, 30),
fill_opacity=0.8,
)
surface.set_color_by_gradient(BLUE, GREEN)
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(surface)3D Parametric Curves
class ParametricCurve3D(ThreeDScene):
def construct(self):
# Helix
curve = ParametricFunction(
lambda t: np.array([
np.cos(t),
np.sin(t),
t * 0.2
]),
t_range=[-4*PI, 4*PI],
color=YELLOW
)
curve.set_shade_in_3d(True)
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(ThreeDAxes(), curve)Shading in 3D
class Shading3D(ThreeDScene):
def construct(self):
sphere = Sphere()
# Enable shading for realistic lighting
sphere.set_shade_in_3d(True)
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(sphere)Arrow3D and Line3D
class Vectors3D(ThreeDScene):
def construct(self):
axes = ThreeDAxes()
arrow = Arrow3D(ORIGIN, [2, 1, 2], color=RED)
line = Line3D(ORIGIN, [-2, 1, 1], color=BLUE)
self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES)
self.add(axes, arrow, line)Best Practices
- Always set camera orientation - Default view may not show 3D well
- Use set_shade_in_3d for realism - Adds depth perception
- Use ambient camera rotation sparingly - Can be disorienting
- Match resolution to detail needed - Higher res = slower render
- Use colorscale for surfaces - Shows elevation/value changes