#!/usr/bin/env python3 """ SURYA - Epic Manim Animation Das's debut album visualized in stunning 3D mathematics NOTE: For LaTeX equations, install MacTeX: brew install --cask mactex This version uses Text fallbacks for systems without LaTeX. """ from manim import * import numpy as np import random # Try to use LaTeX, fall back to Text try: test = MathTex(r"\phi") USE_LATEX = True except: USE_LATEX = False # ============================================================================ # COLOR PALETTE (matching the website) # ============================================================================ COLORS = { "intro": "#1a0a2e", # Deep purple "skin": "#f472b6", # Pink "u_saved_me": "#22d3ee", # Cyan "nothing": "#666666", # Grey "sweet_relief": "#a78bfa", # Purple "natures_call": "#5eead4", # Teal "dreamcatcher": "#c4b5fd", # Soft purple "idk": "#f472b6", # Dark pink "with_u": "#fbbf24", # GOLD - THE TURN! "poor_you": "#fb923c", # Orange "wait_4_u": "#818cf8", # Indigo "run_to_u": "#22d3ee", # Cyan "medications": "#ef4444", # Red "hollow": "#fbbf24", # Gold } DURATION = 25 # seconds per track # ============================================================================ # HELPER FUNCTIONS # ============================================================================ def create_title(text, color, corner=UL): """Create corner-positioned title that won't cover graphics.""" title = Text(text, font_size=28, color=color) title.to_corner(corner, buff=0.4) return title def create_subtitle(text, color): """Create bottom-edge subtitle for lyrics/quotes.""" sub = Text(text, font_size=18, color=color, opacity=0.7) sub.to_edge(DOWN, buff=0.2) return sub def create_equation(latex_str, text_str, font_size=24, color=WHITE): """Create equation - uses LaTeX if available, Text fallback otherwise.""" try: return MathTex(latex_str, font_size=font_size, color=color) except: return Text(text_str, font_size=font_size-4, color=color) def smooth_text_animation(scene, text, hold_time=2): """Fade in text, hold, fade out - smooth and subtle.""" scene.play(FadeIn(text, shift=UP*0.1), run_time=0.5) scene.wait(hold_time) scene.play(FadeOut(text, shift=UP*0.1), run_time=0.5) # ============================================================================ # TRACK 1: SKIN (INTRO) - 3D Morphing Parametric Surface # ============================================================================ class Track01Skin(ThreeDScene): def construct(self): self.set_camera_orientation(phi=70*DEGREES, theta=-45*DEGREES) self.camera.background_color = COLORS["intro"] # Title in corner title = create_title("01 · SKIN (INTRO)", COLORS["skin"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"S(u,v) = (\sin u \cos v, \sin u \sin v, \cos u + \sin 3v)", "S(u,v) = parametric surface", font_size=20, color=COLORS["skin"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=1) self.wait(1) self.play(FadeOut(equation), run_time=0.5) # Create morphing skin-like surface def skin_surface(u, v, t=0): x = np.sin(u) * np.cos(v) * (1 + 0.2*np.sin(3*u + t)) y = np.sin(u) * np.sin(v) * (1 + 0.2*np.cos(3*v + t)) z = np.cos(u) + 0.3*np.sin(3*v + 2*u + t) return np.array([x, y, z]) surface = Surface( lambda u, v: skin_surface(u, v, 0), u_range=[0, PI], v_range=[0, TAU], resolution=(40, 40), fill_opacity=0.8, ) surface.set_color_by_gradient(COLORS["skin"], COLORS["intro"], COLORS["skin"]) self.begin_ambient_camera_rotation(rate=0.15) self.play(Create(surface), run_time=3) # Morph the surface over time for t in np.linspace(0, 4*PI, 40): new_surface = Surface( lambda u, v, t=t: skin_surface(u, v, t), u_range=[0, PI], v_range=[0, TAU], resolution=(40, 40), fill_opacity=0.8, ) new_surface.set_color_by_gradient(COLORS["skin"], COLORS["intro"], COLORS["skin"]) self.play(Transform(surface, new_surface), run_time=0.5) self.play(FadeOut(title), FadeOut(surface), run_time=1) # ============================================================================ # TRACK 2: U SAVED ME - Particles Coalescing into Sacred Geometry # ============================================================================ class Track02USavedMe(ThreeDScene): def construct(self): self.set_camera_orientation(phi=75*DEGREES, theta=-30*DEGREES) self.camera.background_color = "#0a1628" title = create_title("02 · U SAVED ME", COLORS["u_saved_me"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"\text{Icosahedron: } \phi = \frac{1+\sqrt{5}}{2}", "φ = (1 + √5) / 2 ≈ 1.618", font_size=20, color=COLORS["u_saved_me"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create scattered particles particles = VGroup() target_positions = [] # Generate sacred geometry target points (icosahedron vertices + midpoints) phi = (1 + np.sqrt(5)) / 2 # Golden ratio icosa_verts = [ [0, 1, phi], [0, -1, phi], [0, 1, -phi], [0, -1, -phi], [1, phi, 0], [-1, phi, 0], [1, -phi, 0], [-1, -phi, 0], [phi, 0, 1], [-phi, 0, 1], [phi, 0, -1], [-phi, 0, -1] ] for v in icosa_verts: norm = np.linalg.norm(v) target_positions.append(np.array(v) / norm * 2.5) # Add midpoints for denser geometry for i, v1 in enumerate(icosa_verts): for v2 in icosa_verts[i+1:]: mid = (np.array(v1) + np.array(v2)) / 2 if np.linalg.norm(mid) > 0.5: norm = np.linalg.norm(mid) target_positions.append(mid / norm * 2.5) # Create particles at random positions for i, target in enumerate(target_positions[:60]): start_pos = np.array([ random.uniform(-6, 6), random.uniform(-6, 6), random.uniform(-6, 6) ]) particle = Dot3D(point=start_pos, radius=0.08, color=COLORS["u_saved_me"]) particles.add(particle) self.play(FadeIn(particles), run_time=1) self.begin_ambient_camera_rotation(rate=0.12) # Coalesce particles to sacred geometry positions animations = [] for i, (particle, target) in enumerate(zip(particles, target_positions[:60])): animations.append(particle.animate.move_to(target)) self.play(*animations, run_time=4, rate_func=smooth) # Draw connecting lines (edges of sacred geometry) lines = VGroup() for i, p1 in enumerate(particles): for p2 in particles[i+1:]: dist = np.linalg.norm(p1.get_center() - p2.get_center()) if dist < 2.2: line = Line3D(p1.get_center(), p2.get_center(), color=COLORS["u_saved_me"], stroke_width=1) line.set_opacity(0.5) lines.add(line) self.play(Create(lines), run_time=3) self.wait(10) # Pulse effect self.play( lines.animate.set_opacity(1), particles.animate.set_color(WHITE), run_time=1 ) self.play( lines.animate.set_opacity(0.5), particles.animate.set_color(COLORS["u_saved_me"]), run_time=1 ) self.play(FadeOut(title), FadeOut(particles), FadeOut(lines), run_time=1) # ============================================================================ # TRACK 3: NOTHING - 3D Voronoi-like Explosion into Void # ============================================================================ class Track03Nothing(ThreeDScene): def construct(self): self.set_camera_orientation(phi=70*DEGREES, theta=-45*DEGREES) self.camera.background_color = "#0a0a0a" title = create_title("03 · NOTHING", COLORS["nothing"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"\emptyset = \{x : x \neq x\}", "∅ = { } — the empty set", font_size=22, color=COLORS["nothing"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create a solid sphere that will shatter sphere = Sphere(radius=2, resolution=(30, 30)) sphere.set_color(COLORS["nothing"]) sphere.set_opacity(0.8) self.play(Create(sphere), run_time=2) self.wait(1) # Create fragments fragments = VGroup() for _ in range(60): center = np.array([ random.uniform(-1.8, 1.8), random.uniform(-1.8, 1.8), random.uniform(-1.8, 1.8) ]) if np.linalg.norm(center) < 2: size = random.uniform(0.15, 0.4) # Create simple 3D dots as fragments fragment = Dot3D(center, radius=size, color=COLORS["nothing"]) fragment.set_opacity(random.uniform(0.5, 0.9)) fragments.add(fragment) # Explosion effect self.play(FadeOut(sphere), FadeIn(fragments), run_time=0.5) self.begin_ambient_camera_rotation(rate=0.1) # Fragments drift outward into void drift_animations = [] for fragment in fragments: direction = fragment.get_center() if np.linalg.norm(direction) > 0.1: direction = direction / np.linalg.norm(direction) else: direction = np.array([random.uniform(-1,1), random.uniform(-1,1), random.uniform(-1,1)]) target = fragment.get_center() + direction * random.uniform(4, 8) drift_animations.append(fragment.animate.move_to(target).set_opacity(0.1)) self.play(*drift_animations, run_time=15, rate_func=linear) self.play(FadeOut(title), FadeOut(fragments), run_time=1) # ============================================================================ # TRACK 4: SWEET RELIEF - Ghost Spirals in 3D # ============================================================================ class Track04SweetRelief(ThreeDScene): def construct(self): self.set_camera_orientation(phi=75*DEGREES, theta=-60*DEGREES) self.camera.background_color = "#1a0a2e" title = create_title("04 · SWEET RELIEF", COLORS["sweet_relief"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"\gamma(t) = (r\cos t, r\sin t, ct)", "helix: (r·cos(t), r·sin(t), c·t)", font_size=22, color=COLORS["sweet_relief"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create multiple ghost spirals spirals = VGroup() for i in range(5): phase = i * TAU / 5 radius = 1.5 + i * 0.3 opacity = 0.8 - i * 0.12 spiral = ParametricFunction( lambda t, r=radius, p=phase: np.array([ r * np.cos(t + p), r * np.sin(t + p), t * 0.4 ]), t_range=[-4*PI, 4*PI], color=COLORS["sweet_relief"], stroke_width=3 - i*0.4, stroke_opacity=opacity ) spirals.add(spiral) self.begin_ambient_camera_rotation(rate=0.2) for spiral in spirals: self.play(Create(spiral), run_time=1.5) # Add ethereal particles floating around spirals particles = VGroup() for _ in range(100): t = random.uniform(-4*PI, 4*PI) r = random.uniform(0.5, 3) theta = random.uniform(0, TAU) pos = np.array([r*np.cos(theta), r*np.sin(theta), t*0.4]) particle = Dot3D(pos, radius=0.03, color=COLORS["sweet_relief"]) particle.set_opacity(random.uniform(0.3, 0.7)) particles.add(particle) self.play(FadeIn(particles), run_time=2) # Gentle floating animation self.wait(12) self.play(FadeOut(title), FadeOut(spirals), FadeOut(particles), run_time=1) # ============================================================================ # TRACK 5: TIPTOE - 3D Lissajous Curves # ============================================================================ class Track05Tiptoe(ThreeDScene): def construct(self): self.set_camera_orientation(phi=60*DEGREES, theta=-45*DEGREES) self.camera.background_color = "#0f172a" title = create_title("05 · TIPTOE", "#60a5fa") self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"(x,y,z) = (A\sin at, B\sin bt, C\sin ct)", "Lissajous: (A·sin(at), B·sin(bt), C·sin(ct))", font_size=20, color="#60a5fa" ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create 3D Lissajous curves with different frequency ratios curves = VGroup() ratios = [(3, 2, 5), (5, 4, 3), (7, 6, 5), (4, 3, 7)] colors = ["#60a5fa", "#818cf8", "#a78bfa", "#c4b5fd"] for (a, b, c), color in zip(ratios, colors): curve = ParametricFunction( lambda t, a=a, b=b, c=c: np.array([ 2.5 * np.sin(a * t + PI/4), 2.5 * np.sin(b * t), 2.5 * np.sin(c * t) ]), t_range=[0, TAU], color=color, stroke_width=2.5 ) curves.add(curve) self.begin_ambient_camera_rotation(rate=0.15) for curve in curves: self.play(Create(curve), run_time=3) # Gentle pulsing self.play(curves.animate.set_stroke(width=4), run_time=1) self.play(curves.animate.set_stroke(width=2.5), run_time=1) self.wait(10) self.play(FadeOut(title), FadeOut(curves), run_time=1) # ============================================================================ # TRACK 6: NATURE'S CALL - 3D Fractal Tree # ============================================================================ class Track06NaturesCall(ThreeDScene): def construct(self): self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES, zoom=0.8) self.camera.background_color = "#052e16" title = create_title("06 · NATURE'S CALL", COLORS["natures_call"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"F \to F[+F]F[-F]F", "L-System: F → F[+F]F[-F]F", font_size=20, color=COLORS["natures_call"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Build 3D fractal tree branches = VGroup() leaves = VGroup() def add_branch(start, direction, length, depth, branches_group, leaves_group): if depth == 0 or length < 0.1: # Add leaf leaf = Dot3D(start, radius=0.08, color="#22c55e") leaf.set_opacity(0.8) leaves_group.add(leaf) return end = start + direction * length branch = Line3D(start, end, color=COLORS["natures_call"], stroke_width=max(1, depth*0.8)) branches_group.add(branch) # Create child branches for angle in [PI/5, -PI/5, PI/6, -PI/6]: if random.random() > 0.4: # Rotate direction rot_matrix = np.array([ [np.cos(angle), -np.sin(angle), 0], [np.sin(angle), np.cos(angle), 0], [0, 0, 1] ]) new_dir = rot_matrix @ direction new_dir[2] += 0.3 # Tendency to grow up new_dir = new_dir / np.linalg.norm(new_dir) add_branch(end, new_dir, length * 0.7, depth - 1, branches_group, leaves_group) # Start tree from bottom start = np.array([0, 0, -3]) direction = np.array([0, 0, 1]) add_branch(start, direction, 1.5, 5, branches, leaves) self.begin_ambient_camera_rotation(rate=0.1) # Grow branches progressively batch_size = max(1, len(branches)//10) for i in range(0, len(branches), batch_size): batch = branches[i:i+batch_size] self.play(Create(batch), run_time=0.8) # Bloom leaves self.play(FadeIn(leaves, scale=0.5), run_time=3) self.wait(8) self.play(FadeOut(title), FadeOut(branches), FadeOut(leaves), run_time=1) # ============================================================================ # TRACK 7: DREAMCATCHER (INTERLUDE) - Sacred Geometry Web # ============================================================================ class Track07Dreamcatcher(ThreeDScene): def construct(self): self.set_camera_orientation(phi=80*DEGREES, theta=-45*DEGREES) self.camera.background_color = "#1e1b4b" title = create_title("07 · DREAMCATCHER", COLORS["dreamcatcher"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"\phi = \frac{1 + \sqrt{5}}{2}", "φ = (1 + √5) / 2 ≈ 1.618", font_size=24, color=COLORS["dreamcatcher"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create dreamcatcher structure - concentric rings with web rings = VGroup() web_lines = VGroup() # Outer rings for i, r in enumerate([3, 2.5, 2, 1.5, 1]): ring = Circle(radius=r, color=COLORS["dreamcatcher"], stroke_width=2-i*0.3) ring.rotate(PI/2, axis=RIGHT) # Make it face camera rings.add(ring) # Web pattern (radial lines) for angle in np.linspace(0, TAU, 12, endpoint=False): line = Line3D( np.array([0, 0, 0]), np.array([3*np.cos(angle), 0, 3*np.sin(angle)]), color=COLORS["dreamcatcher"], stroke_width=1 ) web_lines.add(line) # Spiral web spiral = ParametricFunction( lambda t: np.array([ (0.3 + t*0.4) * np.cos(t*3), 0, (0.3 + t*0.4) * np.sin(t*3) ]), t_range=[0, 7], color=COLORS["dreamcatcher"], stroke_width=1.5 ) self.begin_ambient_camera_rotation(rate=0.25) self.play(Create(rings), run_time=3) self.play(Create(web_lines), run_time=2) self.play(Create(spiral), run_time=3) # Add glowing center center_glow = Dot3D(ORIGIN, radius=0.15, color=WHITE) self.play(FadeIn(center_glow, scale=0.5), run_time=1) # Pulse self.play(center_glow.animate.scale(1.5).set_color(COLORS["dreamcatcher"]), run_time=1) self.play(center_glow.animate.scale(1/1.5).set_color(WHITE), run_time=1) self.wait(10) self.play(FadeOut(title), FadeOut(rings), FadeOut(web_lines), FadeOut(spiral), FadeOut(center_glow), run_time=1) # ============================================================================ # TRACK 8: IDK - 3D Lorenz Attractor # ============================================================================ class Track08IDK(ThreeDScene): def construct(self): self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES, zoom=0.6) self.camera.background_color = "#1f0a2e" title = create_title("08 · IDK", COLORS["idk"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"\dot{x} = \sigma(y-x), \dot{y} = x(\rho-z)-y", "Lorenz: dx/dt = σ(y-x), dy/dt = x(ρ-z)-y", font_size=16, color=COLORS["idk"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(2) self.play(FadeOut(equation), run_time=0.5) # Generate Lorenz attractor points sigma, rho, beta = 10, 28, 8/3 dt = 0.005 def lorenz_step(x, y, z): dx = sigma * (y - x) * dt dy = (x * (rho - z) - y) * dt dz = (x * y - beta * z) * dt return x + dx, y + dy, z + dz # Generate trajectory x, y, z = 0.1, 0, 0 points = [] for _ in range(8000): x, y, z = lorenz_step(x, y, z) points.append([x * 0.12, y * 0.12, (z - 25) * 0.12]) # Create curve from points attractor = VMobject() attractor.set_points_smoothly([np.array(p) for p in points[::4]]) attractor.set_stroke(color=COLORS["idk"], width=1.5, opacity=0.9) self.begin_ambient_camera_rotation(rate=0.15) self.play(Create(attractor), run_time=12, rate_func=linear) # Add trailing particle particle = Dot3D(np.array(points[-1]), radius=0.1, color=WHITE) self.play(FadeIn(particle), run_time=0.5) # Animate particle along last part of trajectory for i in range(-100, -1, 5): self.play(particle.animate.move_to(np.array(points[i])), run_time=0.1) self.wait(5) self.play(FadeOut(title), FadeOut(attractor), FadeOut(particle), run_time=1) # ============================================================================ # TRACK 9: WITH U - THE TURN! Two Souls Orbiting + Stars # ============================================================================ class Track09WithU(ThreeDScene): def construct(self): self.set_camera_orientation(phi=70*DEGREES, theta=-60*DEGREES) self.camera.background_color = "#0c0a09" title = create_title("09 · WITH U", COLORS["with_u"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"F = G\frac{m_1 m_2}{r^2}", "F = G · m₁m₂ / r²", font_size=26, color=COLORS["with_u"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create two souls (glowing spheres) soul1 = Sphere(radius=0.3, resolution=(20, 20)) soul1.set_color(COLORS["with_u"]) soul1.set_opacity(0.9) soul2 = Sphere(radius=0.25, resolution=(20, 20)) soul2.set_color("#fcd34d") # Slightly different gold soul2.set_opacity(0.9) # Position at opposite sides soul1.move_to([2, 0, 0]) soul2.move_to([-2, 0, 0]) self.play(FadeIn(soul1, scale=0.5), FadeIn(soul2, scale=0.5), run_time=2) # Orbital trails trail1 = VMobject(stroke_color=COLORS["with_u"], stroke_width=2, stroke_opacity=0.6) trail2 = VMobject(stroke_color="#fcd34d", stroke_width=2, stroke_opacity=0.6) self.add(trail1, trail2) self.begin_ambient_camera_rotation(rate=0.1) # Animate orbital dance orbit_time = 10 steps = 150 for i in range(steps): t = i / steps * orbit_time angle = t * 1.5 # Elliptical orbits with slight vertical motion r1 = 2 + 0.3*np.sin(angle*2) r2 = 2 + 0.3*np.sin(angle*2 + PI) pos1 = np.array([r1*np.cos(angle), r1*np.sin(angle), 0.5*np.sin(angle*3)]) pos2 = np.array([r2*np.cos(angle + PI), r2*np.sin(angle + PI), 0.5*np.sin(angle*3 + PI)]) self.play( soul1.animate.move_to(pos1), soul2.animate.move_to(pos2), run_time=orbit_time/steps, rate_func=linear ) # Update trails if len(trail1.points) > 0: trail1.add_line_to(pos1) trail2.add_line_to(pos2) else: trail1.start_new_path(pos1) trail2.start_new_path(pos2) # EPIC MOMENT - Stars appear! stars = VGroup() for _ in range(200): star_pos = np.array([ random.uniform(-8, 8), random.uniform(-8, 8), random.uniform(-5, 5) ]) star = Dot3D(star_pos, radius=0.03, color=WHITE) star.set_opacity(random.uniform(0.3, 1.0)) stars.add(star) self.play(FadeIn(stars, lag_ratio=0.02), run_time=3) # Souls come together self.play( soul1.animate.move_to([0.3, 0, 0]), soul2.animate.move_to([-0.3, 0, 0]), run_time=2 ) # Glow brighter together self.play( soul1.animate.scale(1.3).set_color(WHITE), soul2.animate.scale(1.3).set_color(WHITE), stars.animate.set_opacity(0.5), run_time=1.5 ) self.wait(2) self.play(FadeOut(title), FadeOut(soul1), FadeOut(soul2), FadeOut(trail1), FadeOut(trail2), FadeOut(stars), run_time=1.5) # ============================================================================ # TRACK 10: POOR YOU POOR ME - Drifting Objects in Orange Glow # ============================================================================ class Track10PoorYou(ThreeDScene): def construct(self): self.set_camera_orientation(phi=75*DEGREES, theta=-50*DEGREES) self.camera.background_color = "#1c1917" title = create_title("10 · POOR YOU POOR ME", COLORS["poor_you"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"\vec{v}(t) = \vec{v}_0 e^{-\lambda t}", "v(t) = v₀ · e^(-λt) → 0", font_size=22, color=COLORS["poor_you"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create drifting geometric objects objects = VGroup() # Various shapes drifting apart for i in range(8): angle = i * TAU / 8 pos = np.array([1.5*np.cos(angle), 1.5*np.sin(angle), random.uniform(-1, 1)]) if i % 4 == 0: shape = Sphere(radius=0.3, resolution=(10, 10)) elif i % 4 == 1: shape = Dot3D(pos, radius=0.25) elif i % 4 == 2: shape = Sphere(radius=0.35, resolution=(8, 8)) else: shape = Dot3D(pos, radius=0.2) shape.set_color(COLORS["poor_you"]) shape.set_opacity(0.8) shape.move_to(pos) objects.add(shape) # Add some smaller fragments for _ in range(25): frag = Dot3D( point=np.array([random.uniform(-3, 3), random.uniform(-3, 3), random.uniform(-2, 2)]), radius=random.uniform(0.05, 0.15), color=COLORS["poor_you"] ) frag.set_opacity(random.uniform(0.4, 0.8)) objects.add(frag) self.play(FadeIn(objects), run_time=2) self.begin_ambient_camera_rotation(rate=0.08) # Bittersweet drifting apart drift_animations = [] for obj in objects: direction = obj.get_center() if np.linalg.norm(direction) > 0.1: direction = direction / np.linalg.norm(direction) else: direction = np.array([random.uniform(-1,1), random.uniform(-1,1), random.uniform(-1,1)]) target = obj.get_center() + direction * random.uniform(1, 3) drift_animations.append( obj.animate.move_to(target).set_opacity(obj.get_fill_opacity() * 0.5) ) self.play(*drift_animations, run_time=15, rate_func=smooth) self.wait(3) self.play(FadeOut(title), FadeOut(objects), run_time=1) # ============================================================================ # TRACK 11: WAIT 4 U - Concentric Pulsing Spheres # ============================================================================ class Track11Wait4U(ThreeDScene): def construct(self): self.set_camera_orientation(phi=70*DEGREES, theta=-45*DEGREES) self.camera.background_color = "#0f172a" title = create_title("11 · WAIT 4 U", COLORS["wait_4_u"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"r(t) = r_0 + A\sin(\omega t)", "r(t) = r₀ + A·sin(ωt)", font_size=22, color=COLORS["wait_4_u"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create concentric spheres spheres = VGroup() base_radii = [0.5, 1, 1.5, 2, 2.5, 3] for i, r in enumerate(base_radii): sphere = Sphere(radius=r, resolution=(20, 20)) sphere.set_color(COLORS["wait_4_u"]) sphere.set_opacity(0.2 - i*0.025) sphere.set_stroke(color=COLORS["wait_4_u"], width=1, opacity=0.5) spheres.add(sphere) self.play(Create(spheres), run_time=3) self.begin_ambient_camera_rotation(rate=0.12) # Pulsing animation - waves emanating outward for cycle in range(8): pulse_animations = [] for i, (sphere, base_r) in enumerate(zip(spheres, base_radii)): phase = i * 0.2 new_r = base_r * (1 + 0.15 * np.sin(cycle * PI/2 + phase)) new_sphere = Sphere(radius=new_r, resolution=(20, 20)) new_sphere.set_color(COLORS["wait_4_u"]) new_sphere.set_opacity(0.2 - i*0.025) pulse_animations.append(Transform(sphere, new_sphere)) self.play(*pulse_animations, run_time=1.5) self.wait(5) self.play(FadeOut(title), FadeOut(spheres), run_time=1) # ============================================================================ # TRACK 12: RUN TO U - Speed Lines + 3D Collision # ============================================================================ class Track12RunToU(ThreeDScene): def construct(self): self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES) self.camera.background_color = "#082f49" title = create_title("12 · RUN TO U", COLORS["run_to_u"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"p_1 + p_2 = p_{final}", "p₁ + p₂ = p_final (momentum)", font_size=22, color=COLORS["run_to_u"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Create two objects rushing toward each other obj1 = Sphere(radius=0.4, resolution=(15, 15)) obj1.set_color(COLORS["run_to_u"]) obj1.move_to([-5, 0, 0]) obj2 = Sphere(radius=0.35, resolution=(15, 15)) obj2.set_color("#67e8f9") obj2.move_to([5, 0, 0]) # Speed lines speed_lines = VGroup() for _ in range(30): y = random.uniform(-3, 3) z = random.uniform(-2, 2) line = Line3D([-6, y, z], [6, y, z], color=COLORS["run_to_u"], stroke_width=1) line.set_opacity(random.uniform(0.2, 0.6)) speed_lines.add(line) self.play(FadeIn(speed_lines), run_time=1) self.play(FadeIn(obj1), FadeIn(obj2), run_time=1) self.begin_ambient_camera_rotation(rate=0.15) # Rush toward each other with increasing speed self.play( obj1.animate.move_to([-2, 0, 0]), obj2.animate.move_to([2, 0, 0]), run_time=3, rate_func=rate_functions.ease_in_quad ) self.play( obj1.animate.move_to([0, 0, 0]), obj2.animate.move_to([0, 0, 0]), run_time=1.5, rate_func=rate_functions.ease_in_expo ) # Collision burst! burst_particles = [] for _ in range(50): direction = np.array([random.uniform(-1, 1), random.uniform(-1, 1), random.uniform(-1, 1)]) direction = direction / np.linalg.norm(direction) particle = Dot3D(ORIGIN, radius=0.1, color=WHITE) burst_particles.append((particle, direction)) burst_group = VGroup(*[p for p, d in burst_particles]) self.play( FadeOut(obj1), FadeOut(obj2), FadeIn(burst_group, scale=0.5), run_time=0.3 ) # Expand burst burst_anims = [] for particle, direction in burst_particles: target = direction * random.uniform(2, 5) burst_anims.append(particle.animate.move_to(target).set_opacity(0)) self.play(*burst_anims, run_time=3) # New combined entity emerges combined = Sphere(radius=0.6, resolution=(25, 25)) combined.set_color_by_gradient(COLORS["run_to_u"], "#67e8f9") self.play(FadeIn(combined, scale=0.3), run_time=2) # Gentle rotation self.wait(8) self.play(FadeOut(title), FadeOut(combined), FadeOut(speed_lines), FadeOut(burst_group), run_time=1) # ============================================================================ # TRACK 13: MEDICATIONS - Chaos Attractor with Red Pulsing # ============================================================================ class Track13Medications(ThreeDScene): def construct(self): self.set_camera_orientation(phi=75*DEGREES, theta=-45*DEGREES, zoom=0.7) self.camera.background_color = "#1c0a0a" title = create_title("13 · MEDICATIONS", COLORS["medications"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"\frac{dx}{dt} = a(y-x)", "Chen attractor: dx/dt = a(y-x)", font_size=18, color=COLORS["medications"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Generate Chen attractor (another chaotic system) a, b, c = 35, 3, 28 dt = 0.002 def chen_step(x, y, z): dx = a * (y - x) * dt dy = ((c - a) * x - x * z + c * y) * dt dz = (x * y - b * z) * dt return x + dx, y + dy, z + dz x, y, z = 0.1, 0.1, 0.1 points = [] for _ in range(10000): x, y, z = chen_step(x, y, z) points.append([x * 0.08, y * 0.08, z * 0.08]) attractor = VMobject() attractor.set_points_smoothly([np.array(p) for p in points[::5]]) attractor.set_stroke(color=COLORS["medications"], width=1.2, opacity=0.8) self.begin_ambient_camera_rotation(rate=0.18) self.play(Create(attractor), run_time=8, rate_func=linear) # Red pulsing effect for _ in range(6): self.play( attractor.animate.set_stroke(color="#ff6b6b", opacity=1), run_time=0.5 ) self.play( attractor.animate.set_stroke(color=COLORS["medications"], opacity=0.8), run_time=0.5 ) self.wait(5) self.play(FadeOut(title), FadeOut(attractor), run_time=1) # ============================================================================ # TRACK 14: HOLLOW - Golden Spiral to Moon, Epic Finale # ============================================================================ class Track14Hollow(ThreeDScene): def construct(self): self.set_camera_orientation(phi=70*DEGREES, theta=-45*DEGREES, zoom=0.7) self.camera.background_color = "#1a0a2e" title = create_title("14 · HOLLOW", COLORS["hollow"]) self.add_fixed_in_frame_mobjects(title) self.play(FadeIn(title, shift=RIGHT*0.2), run_time=0.8) # Equation equation = create_equation( r"r = a \cdot \phi^{\theta/90°}", "Golden spiral: r = a · φ^(θ/90°)", font_size=22, color=COLORS["hollow"] ) equation.to_corner(DR, buff=0.5) self.add_fixed_in_frame_mobjects(equation) self.play(FadeIn(equation), run_time=0.8) self.wait(1.5) self.play(FadeOut(equation), run_time=0.5) # Golden spiral phi = (1 + np.sqrt(5)) / 2 spiral = ParametricFunction( lambda t: np.array([ 0.1 * phi**(t / (PI/2)) * np.cos(t), 0.1 * phi**(t / (PI/2)) * np.sin(t), t * 0.05 ]), t_range=[0, 6*PI], color=COLORS["hollow"], stroke_width=3 ) self.begin_ambient_camera_rotation(rate=0.1) self.play(Create(spiral), run_time=5) # Moon appears in distance moon = Sphere(radius=1.2, resolution=(30, 30)) moon.set_color("#fef3c7") moon.set_opacity(0.9) moon.move_to([6, 4, 3]) self.play(FadeIn(moon, scale=0.5), run_time=2) # Stars appear stars = VGroup() for _ in range(150): star_pos = np.array([ random.uniform(-10, 10), random.uniform(-10, 10), random.uniform(-5, 8) ]) star = Dot3D(star_pos, radius=0.03, color=WHITE) star.set_opacity(random.uniform(0.2, 0.8)) stars.add(star) self.play(FadeIn(stars, lag_ratio=0.01), run_time=3) # Epic camera pullback self.stop_ambient_camera_rotation() self.move_camera( phi=60 * DEGREES, theta=-60 * DEGREES, frame_center=ORIGIN, zoom=0.5, run_time=8, rate_func=smooth ) # Final glow self.play( moon.animate.set_color(COLORS["hollow"]), spiral.animate.set_stroke(color=WHITE, width=4), run_time=2 ) # Fade to completion self.wait(2) all_objects = VGroup(spiral, moon, stars) self.play(FadeOut(title), FadeOut(all_objects), run_time=2) # ============================================================================ # COMBINED MEGA SCENE - All Tracks in Sequence # ============================================================================ class SuryaEpic(ThreeDScene): """ Master scene combining all tracks. For full render, use individual track classes and combine with ffmpeg. This serves as a preview/test scene. """ def construct(self): self.camera.background_color = "#1a0a2e" # Intro title album_title = Text("S U R Y A", font_size=72, color=COLORS["hollow"]) artist = Text("Das", font_size=36, color=WHITE) artist.next_to(album_title, DOWN, buff=0.5) self.add_fixed_in_frame_mobjects(album_title, artist) self.play(FadeIn(album_title, shift=UP*0.5), run_time=2) self.play(FadeIn(artist), run_time=1) self.wait(2) self.play(FadeOut(album_title), FadeOut(artist), run_time=1) # Note: For full animation, render each track separately and combine # This is just a preview intro preview = Text( "Render individual tracks with:\nmanim -pqh surya_epic.py Track01Skin", font_size=20, color=WHITE ) self.add_fixed_in_frame_mobjects(preview) self.play(FadeIn(preview), run_time=1) self.wait(3)