# 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 ```python 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. ```python # 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 ```python 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 ```python # 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 ```python sphere = Sphere( radius=2, resolution=(20, 20), # (u_resolution, v_resolution) color=BLUE ) sphere.set_opacity(0.7) ``` ### Cube ```python cube = Cube( side_length=2, color=GREEN, fill_opacity=0.8 ) ``` ### Surface ```python # 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 ```python torus = Torus( r1=2, # Major radius r2=0.5, # Minor radius color=YELLOW ) ``` ### Cylinder ```python cylinder = Cylinder( height=3, radius=1, color=RED ) ``` ### 3D Lines and Shapes ```python # 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 ```python 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 ```python 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 ```python 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 ```python # 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 ```python # 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 ```python # 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. ```python 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 ```python # 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 ```python # 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 ```python 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 ```python # 360-degree rotation self.play( frame.animate.increment_theta(360*DEGREES), run_time=10, rate_func=linear ) ``` ### Creating a floor plane ```python 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 ```python # 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() ```