Skip to main content

What is a Scene?

A Scene is the fundamental building block of ManimVTK. It’s a container for your animation that manages:
  • Mobjects (visual objects)
  • Animations (movements and transformations)
  • Camera (viewpoint and perspective)
  • Rendering (video output and VTK export)
Every ManimVTK animation starts with a scene class.

Basic Scene Structure

from manimvtk import *

class MyScene(Scene):
    def construct(self):
        # Your animation code goes here
        pass
Key components:
  1. Import: from manimvtk import *
  2. Class definition: Inherit from Scene
  3. construct() method: Where you build your animation

The construct() Method

The construct() method is where all your animation logic lives:
class SimpleAnimation(Scene):
    def construct(self):
        # Create objects
        circle = Circle(radius=1, color=BLUE)
        
        # Add to scene
        self.add(circle)
        
        # Animate
        self.play(circle.animate.scale(2))
        
        # Wait
        self.wait()
The construct() method is called automatically when you render the scene

Scene Types

ManimVTK provides several scene types for different use cases:
  • Scene
  • ThreeDScene
  • MovingCameraScene
  • ZoomedScene
Basic 2D scene - Default scene type
class Basic2D(Scene):
    def construct(self):
        square = Square()
        self.play(Create(square))
Use for:
  • 2D animations
  • Graphs and plots
  • Educational diagrams

Adding Objects to a Scene

Using add()

Instantly add objects without animation:
class AddExample(Scene):
    def construct(self):
        circle = Circle()
        square = Square()
        
        # Add instantly (no animation)
        self.add(circle, square)
        self.wait()

Using play()

Add objects with animation:
class PlayExample(Scene):
    def construct(self):
        circle = Circle()
        
        # Add with creation animation
        self.play(Create(circle))
        self.wait()

Adding Multiple Objects

class MultipleObjects(Scene):
    def construct(self):
        # Create a group
        shapes = VGroup(
            Circle(),
            Square(),
            Triangle()
        ).arrange(RIGHT, buff=1)
        
        # Add all at once
        self.play(Create(shapes))
        self.wait()

Scene Methods

Animation Control

Play one or more animations:
self.play(Create(circle))
self.play(Transform(square, circle))

# Multiple animations simultaneously
self.play(
    Create(circle),
    FadeIn(text)
)
Pause the animation:
self.wait()  # Wait 1 second (default)
self.wait(2)  # Wait 2 seconds
self.wait(0.5)  # Wait 0.5 seconds
Add objects without animation:
self.add(circle)
self.add(square, triangle)  # Multiple objects
Remove objects from scene:
self.remove(circle)
self.remove(square, triangle)

Camera Control (ThreeDScene)

Set the initial camera position:
self.set_camera_orientation(
    phi=60 * DEGREES,    # Vertical angle
    theta=30 * DEGREES,  # Horizontal angle
    distance=8           # Distance from origin
)
Start continuous camera rotation:
self.begin_ambient_camera_rotation(rate=0.1)
self.wait(5)  # Rotate for 5 seconds
self.stop_ambient_camera_rotation()
Animate camera movement:
self.move_camera(
    phi=75 * DEGREES,
    theta=45 * DEGREES,
    run_time=2
)

Scene Lifecycle

Understanding the order of operations:
class LifecycleExample(Scene):
    def construct(self):
        # 1. Object creation
        circle = Circle()
        
        # 2. Add to scene (instant)
        self.add(circle)
        
        # 3. Animations
        self.play(circle.animate.scale(2))
        
        # 4. Wait/pause
        self.wait()
        
        # 5. More animations
        self.play(FadeOut(circle))
        
        # 6. Scene ends (automatic rendering)
Rendering process:
  1. construct() method executes
  2. Animations are recorded
  3. Frames are generated
  4. Video is encoded
  5. VTK export (if requested)

Configuration

In Scene Class

class ConfiguredScene(Scene):
    def construct(self):
        # Access config
        print(f"Frame rate: {config.frame_rate}")
        print(f"Resolution: {config.pixel_width}x{config.pixel_height}")
        
        # Your animation
        circle = Circle()
        self.play(Create(circle))

Via Command Line

# Set quality
manimvtk -qh scene.py MyScene  # High quality

# Set frame rate
manimvtk -r 60 scene.py MyScene  # 60 fps

# Set resolution
manimvtk --resolution 1920,1080 scene.py MyScene

Via Config File

Create manim.cfg:
[CLI]
quality = high
frame_rate = 60
background_color = BLACK

Common Patterns

Simple Animation

class SimplePattern(Scene):
    def construct(self):
        # Create → Animate → Remove
        obj = Circle()
        self.play(Create(obj))
        self.play(obj.animate.shift(RIGHT))
        self.play(FadeOut(obj))

Sequential Animations

class Sequential(Scene):
    def construct(self):
        objs = VGroup(*[Circle() for _ in range(3)])
        objs.arrange(RIGHT, buff=1)
        
        # Animate one by one
        for obj in objs:
            self.play(Create(obj))
        self.wait()

Simultaneous Animations

class Simultaneous(Scene):
    def construct(self):
        c1 = Circle().shift(LEFT)
        c2 = Circle().shift(RIGHT)
        
        # Both at the same time
        self.play(
            Create(c1),
            Create(c2)
        )

Build Up and Transform

class BuildAndTransform(Scene):
    def construct(self):
        # Build up
        circle = Circle()
        self.play(Create(circle))
        
        # Transform
        square = Square()
        self.play(Transform(circle, square))
        
        # Continue with transformed object
        self.play(circle.animate.rotate(PI/4))

Best Practices

Break complex scenes into helper methods:
class OrganizedScene(Scene):
    def construct(self):
        self.intro()
        self.main_content()
        self.outro()
    
    def intro(self):
        title = Text("Introduction")
        self.play(Write(title))
        self.wait()
        self.play(FadeOut(title))
    
    def main_content(self):
        # Main animation logic
        pass
    
    def outro(self):
        # Closing
        pass
# Good
class QuadraticFunction(Scene):
    pass

# Avoid
class Test1(Scene):
    pass
Give viewers time to process:
self.play(Create(important_diagram))
self.wait(2)  # Let viewers see it
self.play(FadeOut(important_diagram))
# Efficient
circle = Circle()
self.play(Create(circle))
self.play(circle.animate.shift(RIGHT))

# Less efficient
circle1 = Circle()
self.play(Create(circle1))
circle2 = circle1.copy().shift(RIGHT)
self.play(Transform(circle1, circle2))

Debugging Scenes

class DebugScene(Scene):
    def construct(self):
        circle = Circle()
        
        # Debug output
        print(f"Circle center: {circle.get_center()}")
        print(f"Circle color: {circle.get_color()}")
        
        self.add(circle)

Preview Frames

# Save last frame only (fast)
manimvtk -s scene.py MyScene

# Save all frames
manimvtk --save_sections scene.py MyScene

Use Lower Quality for Testing

# Fast preview
manimvtk -ql scene.py MyScene

# Final render
manimvtk -qh scene.py MyScene

Next Steps