280 lines
8.4 KiB
Python
280 lines
8.4 KiB
Python
from manim import *
|
|
import numpy as np
|
|
import random
|
|
|
|
class OSKVCommunity(Scene):
|
|
def construct(self):
|
|
# Set dark background
|
|
self.camera.background_color = "#0a0a0f"
|
|
|
|
# === PART 1: Particle Explosion Intro ===
|
|
particles = VGroup()
|
|
for _ in range(150):
|
|
dot = Dot(
|
|
point=np.array([0, 0, 0]),
|
|
radius=random.uniform(0.02, 0.08),
|
|
color=random.choice([BLUE, PURPLE, TEAL, WHITE, BLUE_B])
|
|
)
|
|
dot.set_opacity(random.uniform(0.3, 1.0))
|
|
particles.add(dot)
|
|
|
|
self.add(particles)
|
|
|
|
# Explode particles outward
|
|
animations = []
|
|
for dot in particles:
|
|
angle = random.uniform(0, TAU)
|
|
distance = random.uniform(3, 8)
|
|
end_pos = np.array([
|
|
distance * np.cos(angle),
|
|
distance * np.sin(angle),
|
|
0
|
|
])
|
|
animations.append(dot.animate.move_to(end_pos).set_opacity(0))
|
|
|
|
self.play(*animations, run_time=1.5, rate_func=rush_from)
|
|
self.remove(particles)
|
|
|
|
# === PART 2: Neural Network Visualization ===
|
|
# Create nodes in layers
|
|
layer_sizes = [4, 6, 8, 6, 4]
|
|
layers = []
|
|
all_nodes = VGroup()
|
|
|
|
for i, size in enumerate(layer_sizes):
|
|
layer = VGroup()
|
|
x_pos = (i - 2) * 2
|
|
for j in range(size):
|
|
y_pos = (j - (size - 1) / 2) * 0.8
|
|
node = Circle(radius=0.15, color=BLUE_C, fill_opacity=0.8)
|
|
node.move_to([x_pos, y_pos, 0])
|
|
node.set_stroke(WHITE, width=1)
|
|
layer.add(node)
|
|
layers.append(layer)
|
|
all_nodes.add(layer)
|
|
|
|
# Create connections
|
|
connections = VGroup()
|
|
for i in range(len(layers) - 1):
|
|
for node1 in layers[i]:
|
|
for node2 in layers[i + 1]:
|
|
line = Line(
|
|
node1.get_center(),
|
|
node2.get_center(),
|
|
stroke_width=0.5,
|
|
color=BLUE_E
|
|
)
|
|
line.set_opacity(0.3)
|
|
connections.add(line)
|
|
|
|
# Animate network appearing
|
|
self.play(
|
|
LaggedStart(*[GrowFromCenter(node) for layer in layers for node in layer], lag_ratio=0.02),
|
|
run_time=1.5
|
|
)
|
|
self.play(
|
|
LaggedStart(*[Create(line) for line in connections], lag_ratio=0.005),
|
|
run_time=1
|
|
)
|
|
|
|
# Pulse through network (data flow)
|
|
for _ in range(2):
|
|
pulses = []
|
|
for i in range(len(layers) - 1):
|
|
for node1 in layers[i]:
|
|
for node2 in layers[i + 1]:
|
|
pulse = Dot(
|
|
point=node1.get_center(),
|
|
radius=0.05,
|
|
color=TEAL
|
|
)
|
|
pulse.set_glow_factor(2)
|
|
pulses.append(pulse)
|
|
|
|
pulse_group = VGroup(*pulses[:50]) # Limit for performance
|
|
self.add(pulse_group)
|
|
|
|
anims = [
|
|
pulse.animate.move_to(
|
|
layers[(i % (len(layers)-1)) + 1][i % len(layers[(i % (len(layers)-1)) + 1])].get_center()
|
|
).set_opacity(0)
|
|
for i, pulse in enumerate(pulse_group)
|
|
]
|
|
self.play(*anims, run_time=0.8)
|
|
self.remove(pulse_group)
|
|
|
|
# Fade network
|
|
self.play(
|
|
FadeOut(all_nodes),
|
|
FadeOut(connections),
|
|
run_time=0.8
|
|
)
|
|
|
|
# === PART 3: Geometric Transformation ===
|
|
# Sacred geometry style
|
|
shapes = VGroup()
|
|
|
|
# Outer hexagon
|
|
hex1 = RegularPolygon(n=6, radius=2.5, color=PURPLE)
|
|
hex1.set_stroke(width=2)
|
|
|
|
# Inner hexagon (rotated)
|
|
hex2 = RegularPolygon(n=6, radius=1.8, color=BLUE)
|
|
hex2.rotate(PI/6)
|
|
hex2.set_stroke(width=2)
|
|
|
|
# Triangle
|
|
tri = RegularPolygon(n=3, radius=1.2, color=TEAL)
|
|
tri.set_stroke(width=2)
|
|
|
|
# Circle in center
|
|
circ = Circle(radius=0.6, color=WHITE)
|
|
circ.set_stroke(width=2)
|
|
|
|
shapes.add(hex1, hex2, tri, circ)
|
|
|
|
self.play(
|
|
LaggedStart(
|
|
Create(hex1),
|
|
Create(hex2),
|
|
Create(tri),
|
|
Create(circ),
|
|
lag_ratio=0.3
|
|
),
|
|
run_time=2
|
|
)
|
|
|
|
# Rotate and pulse
|
|
self.play(
|
|
Rotate(hex1, PI/3, about_point=ORIGIN),
|
|
Rotate(hex2, -PI/3, about_point=ORIGIN),
|
|
Rotate(tri, PI/2, about_point=ORIGIN),
|
|
circ.animate.scale(1.3),
|
|
run_time=1.5
|
|
)
|
|
|
|
# Transform into OSKV text
|
|
oskv_text = Text("OSKV", font_size=120, weight=BOLD)
|
|
oskv_text.set_color_by_gradient(BLUE, PURPLE, TEAL)
|
|
|
|
self.play(
|
|
ReplacementTransform(shapes, oskv_text),
|
|
run_time=1.5
|
|
)
|
|
|
|
# === PART 4: Text Effects ===
|
|
# Add glow effect (simulate with scaled copies)
|
|
glow = oskv_text.copy()
|
|
glow.set_opacity(0.3)
|
|
glow.set_stroke(BLUE, width=10, opacity=0.5)
|
|
self.add(glow)
|
|
self.bring_to_front(oskv_text)
|
|
|
|
# Subtitle
|
|
subtitle = Text("THE COMMUNITY", font_size=36)
|
|
subtitle.set_color(WHITE)
|
|
subtitle.set_opacity(0.8)
|
|
subtitle.next_to(oskv_text, DOWN, buff=0.5)
|
|
|
|
self.play(
|
|
FadeIn(subtitle, shift=UP * 0.3),
|
|
run_time=0.8
|
|
)
|
|
|
|
# Floating particles around text
|
|
ambient_particles = VGroup()
|
|
for _ in range(40):
|
|
p = Dot(
|
|
radius=random.uniform(0.02, 0.05),
|
|
color=random.choice([BLUE, PURPLE, TEAL, WHITE])
|
|
)
|
|
p.set_opacity(random.uniform(0.2, 0.6))
|
|
p.move_to([
|
|
random.uniform(-6, 6),
|
|
random.uniform(-3.5, 3.5),
|
|
0
|
|
])
|
|
ambient_particles.add(p)
|
|
|
|
self.play(
|
|
FadeIn(ambient_particles, run_time=0.5)
|
|
)
|
|
|
|
# Gentle floating animation
|
|
float_anims = []
|
|
for p in ambient_particles:
|
|
new_pos = p.get_center() + np.array([
|
|
random.uniform(-0.5, 0.5),
|
|
random.uniform(-0.5, 0.5),
|
|
0
|
|
])
|
|
float_anims.append(p.animate.move_to(new_pos))
|
|
|
|
self.play(*float_anims, run_time=2)
|
|
|
|
# Final pulse
|
|
self.play(
|
|
oskv_text.animate.scale(1.1),
|
|
glow.animate.scale(1.15).set_opacity(0.5),
|
|
rate_func=there_and_back,
|
|
run_time=0.8
|
|
)
|
|
|
|
# Hold
|
|
self.wait(1.5)
|
|
|
|
# Fade out
|
|
self.play(
|
|
FadeOut(oskv_text),
|
|
FadeOut(glow),
|
|
FadeOut(subtitle),
|
|
FadeOut(ambient_particles),
|
|
run_time=1
|
|
)
|
|
|
|
|
|
class OSKVIntro(Scene):
|
|
"""Alternative shorter intro animation"""
|
|
def construct(self):
|
|
self.camera.background_color = "#0a0a0f"
|
|
|
|
# Circular wave rings expanding
|
|
rings = VGroup()
|
|
for i in range(8):
|
|
ring = Circle(radius=0.1, color=BLUE)
|
|
ring.set_stroke(width=3 - i * 0.3, opacity=1 - i * 0.1)
|
|
rings.add(ring)
|
|
|
|
self.add(rings)
|
|
|
|
ring_anims = [
|
|
ring.animate.scale(30).set_opacity(0)
|
|
for ring in rings
|
|
]
|
|
|
|
self.play(
|
|
LaggedStart(*ring_anims, lag_ratio=0.15),
|
|
run_time=2
|
|
)
|
|
|
|
# OSKV appears from the center
|
|
text = Text("OSKV", font_size=144, weight=BOLD)
|
|
text.set_color_by_gradient(BLUE, PURPLE)
|
|
|
|
self.play(
|
|
GrowFromCenter(text),
|
|
run_time=1
|
|
)
|
|
|
|
# Underline swoosh
|
|
underline = Line(
|
|
start=text.get_left() + DOWN * 0.5 + LEFT * 0.5,
|
|
end=text.get_right() + DOWN * 0.5 + RIGHT * 0.5,
|
|
color=TEAL,
|
|
stroke_width=4
|
|
)
|
|
|
|
self.play(Create(underline), run_time=0.6)
|
|
|
|
self.wait(2)
|