All skills
adithya-s-k avatar

/manimgl-best-practices

@2375ac0
by Adithya S Kadithya-s-k/manim_skill1.1k stars
94

Trigger when: (1) User mentions "manimgl" or "ManimGL" or "3b1b manim", (2) Code contains `from manimlib import *`, (3) User runs `manimgl` CLI commands, (4) Working with InteractiveScene, self.frame, self.embed(), ShowCreation(), or ManimGL-specific patterns. Best practices for ManimGL (Grant Sanderson's 3Blue1Brown version) - OpenGL-based animation engine with interactive development. Covers InteractiveScene, Tex with t2c, camera frame control, interactive mode (-se flag), 3D rendering, and checkpoint_paste() workflow. NOT for Manim Community Edition (which uses `manim` imports and `manim` CLI).

Use this Skill: https://skilld.dev/gh/adithya-s-k/manim_skill/manimgl-best-practices

This session only. Nothing lands on disk.

rules3d.md

≈2.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

3D in ManimGL

ManimGL has powerful 3D capabilities with a flexible camera system. Unlike ManimCE, ManimGL doesn't require a special ThreeDScene class.

Basic 3D Setup

Creating 3D Objects

from manimlib import *

class Basic3DScene(Scene):
    def construct(self):
        # Get camera frame
        frame = self.camera.frame

        # Set 3D orientation
        frame.reorient(20, 70)  # theta, phi in degrees

        # Create 3D objects
        sphere = Sphere(radius=2)
        sphere.set_color(BLUE, opacity=0.7)

        self.add(sphere)

Camera Frame Control

frame.reorient()

The reorient() method is the primary way to control 3D camera orientation.

# frame.reorient(theta, phi, gamma=0, center=ORIGIN, height=8)

# Front view
frame.reorient(0, 0)

# Isometric view
frame.reorient(20, 70)

# Top-down view
frame.reorient(0, 90)

# Side view
frame.reorient(90, 90)

Animating Camera Movement

class AnimatedCamera(Scene):
    def construct(self):
        frame = self.camera.frame

        # Create object
        cube = Cube()
        self.add(cube)

        # Animate camera rotation
        self.play(frame.animate.reorient(30, 60))
        self.wait()

        # Continuous rotation
        frame.add_updater(lambda m, dt: m.increment_theta(0.2 * dt))
        self.wait(10)

Frame Methods

# Set Euler angles
frame.set_euler_angles(theta=30*DEGREES, phi=70*DEGREES)

# Increment angles (useful for rotation)
frame.increment_theta(10*DEGREES)
frame.increment_phi(5*DEGREES)
frame.increment_gamma(2*DEGREES)

# Get current angles
theta = frame.get_theta()
phi = frame.get_phi()

3D Geometric Primitives

Sphere

sphere = Sphere(
    radius=2,
    resolution=(20, 20),  # (u_resolution, v_resolution)
    color=BLUE
)
sphere.set_opacity(0.7)

Cube

cube = Cube(
    side_length=2,
    color=GREEN,
    fill_opacity=0.8
)

Surface

# Parametric surface
surface = Surface(
    lambda u, v: np.array([u, v, u**2 + v**2]),
    u_range=(-2, 2),
    v_range=(-2, 2),
    resolution=(20, 20)
)

Torus

torus = Torus(
    r1=2,  # Major radius
    r2=0.5,  # Minor radius
    color=YELLOW
)

Cylinder

cylinder = Cylinder(
    height=3,
    radius=1,
    color=RED
)

3D Lines and Shapes

# 3D Line
line = Line3D(
    start=[-2, -2, -2],
    end=[2, 2, 2],
    color=WHITE,
    width=0.05
)

# 3D Disk
disk = Disk3D(radius=1.5, color=PURPLE)

# 3D Square
square = Square3D(side_length=2, color=ORANGE)

Textured Surfaces

Adding Textures to 3D Objects

class TexturedSphere(Scene):
    def construct(self):
        frame = self.camera.frame
        frame.reorient(20, 70)

        # Create sphere with texture
        sphere = Sphere(radius=2)

        # Apply texture from URL or local file
        textured_sphere = TexturedSurface(
            surface=sphere,
            # Can use URL or local path
            image_file="path/to/texture.jpg"
        )

        self.add(textured_sphere)

        # Rotate camera
        self.play(frame.animate.increment_theta(360*DEGREES), run_time=10)

Earth Example

earth = Sphere(radius=2, resolution=(40, 40))
textured_earth = TexturedSurface(
    earth,
    "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Whole_world_-_land_and_oceans.jpg/1280px-Whole_world_-_land_and_oceans.jpg"
)

3D Axes

ThreeDAxes

axes = ThreeDAxes(
    x_range=(-5, 5, 1),
    y_range=(-5, 5, 1),
    z_range=(-5, 5, 1),
    width=10,
    height=10,
    depth=10
)
axes.add_coordinate_labels(font_size=20)

NumberPlane in 3D

# XY plane
xy_plane = NumberPlane(
    x_range=(-5, 5),
    y_range=(-5, 5)
)

# XZ plane (horizontal floor)
xz_plane = NumberPlane(
    x_range=(-5, 5),
    y_range=(-5, 5)
)
xz_plane.rotate(90*DEGREES, axis=RIGHT)

Parametric Surfaces

Creating Custom Surfaces

# Paraboloid
paraboloid = Surface(
    lambda u, v: np.array([
        u,
        v,
        u**2 + v**2
    ]),
    u_range=(-2, 2),
    v_range=(-2, 2),
    resolution=(30, 30),
    color=BLUE
)

# Wave surface
wave = Surface(
    lambda u, v: np.array([
        u,
        v,
        np.sin(u) * np.cos(v)
    ]),
    u_range=(-PI, PI),
    v_range=(-PI, PI),
    resolution=(40, 40)
)

Surface Mesh

# Create surface
surface = Sphere(radius=2)

# Add mesh overlay
mesh = SurfaceMesh(surface)
mesh.set_stroke(BLUE, width=1, opacity=0.5)

self.add(surface, mesh)

Fixing Objects in Frame

fix_in_frame()

Keep 2D elements (like labels) fixed while camera rotates.

class FixedLabels(Scene):
    def construct(self):
        frame = self.camera.frame
        frame.reorient(20, 70)

        # 3D object that rotates with camera
        cube = Cube()
        self.add(cube)

        # 2D title that stays fixed
        title = Text("3D Cube", font_size=60)
        title.to_edge(UP)
        title.fix_in_frame()  # Stays in screen space
        self.add(title)

        # Rotate camera
        self.play(frame.animate.reorient(50, 80), run_time=3)

Lighting

Light Source

# Access light source
light = self.camera.light_source

# Move light
light.move_to([10, 10, 10])

# Animate light movement
self.play(light.animate.move_to([0, 0, 10]), run_time=2)

Gloss and Shadow

# Add gloss to objects
sphere = Sphere(radius=2)
sphere.set_gloss(0.8)  # 0 to 1

# Add shadow
sphere.set_shadow(0.5)  # 0 to 1

Complex 3D Scene Example

class Complex3DScene(Scene):
    def construct(self):
        frame = self.camera.frame
        frame.reorient(20, 75)

        # Create axes
        axes = ThreeDAxes(
            x_range=(-3, 3),
            y_range=(-3, 3),
            z_range=(-3, 3)
        )

        # Create parametric surface
        surface = Surface(
            lambda u, v: np.array([
                u,
                v,
                np.sin(np.sqrt(u**2 + v**2))
            ]),
            u_range=(-3, 3),
            v_range=(-3, 3),
            resolution=(30, 30),
            color=BLUE
        )
        surface.set_opacity(0.7)

        # Add mesh
        mesh = SurfaceMesh(surface)
        mesh.set_stroke(WHITE, 0.5, opacity=0.3)

        # Add title (fixed in frame)
        title = Text("Sinc Function Surface", font_size=48)
        title.to_edge(UP)
        title.fix_in_frame()
        title.set_backstroke(BLACK, 5)

        # Build scene
        self.add(axes, surface, mesh, title)
        self.wait()

        # Rotate camera smoothly
        self.play(
            frame.animate.reorient(45, 70),
            run_time=3
        )
        self.wait()

        # Add continuous rotation
        frame.add_updater(lambda m, dt: m.increment_theta(20 * dt))
        self.wait(10)

Interactive 3D Controls

When running with manimgl, you can interact with 3D scenes:

  • Press d + move mouse: Rotate camera
  • Press z + scroll: Zoom in/out
  • Press r: Reset camera to default position
  • Press q: Exit interaction mode

Best Practices

  1. Use reorient(): Cleaner than setting Euler angles manually
  2. fix_in_frame() for labels: Keep UI elements readable
  3. Appropriate resolution: Higher resolution for final renders, lower for development
  4. Opacity for depth: Set opacity < 1 to see through surfaces
  5. Lighting matters: Adjust light source position for better visualization
  6. Continuous rotation: Use updaters for smooth camera rotation
  7. Frame rate considerations: 3D scenes may need lower frame rates during development

Common Patterns

Rotating camera around object

# 360-degree rotation
self.play(
    frame.animate.increment_theta(360*DEGREES),
    run_time=10,
    rate_func=linear
)

Creating a floor plane

floor = NumberPlane(
    x_range=(-10, 10),
    y_range=(-10, 10),
    background_line_style={"stroke_color": GREY, "stroke_width": 1}
)
floor.rotate(90*DEGREES, RIGHT)
floor.shift(2*DOWN)

Multiple viewpoints

# Show from different angles
angles = [(0, 0), (20, 70), (45, 45), (90, 90)]

for theta, phi in angles:
    self.play(frame.animate.reorient(theta, phi))
    self.wait()

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill is an educational resource for the ManimGL mathematical animation library, providing best practices and functional examples. All code patterns, including CLI boilerplate and external asset references, are standard and safe for the intended use cases.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    1/107 files flagged

  • ZeroLeaks5mo

    1 finding · Score: 86/100

Signed by skilld at 2375ac0. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 8 months ago

README badge

README badge for adithya-s-k/manim_skill/manimgl-best-practices