Creating Cosmic Formation Animation
Cosmic Formation - 3D Voxel Animation Guide
This guide walks you through how to generate a looping 3D voxel animation of cosmic formation using SpatialStudio.
The script creates a mesmerizing galaxy birth scene with swirling stardust, forming stars, and cosmic gas clouds inside a cubic 3D space, then saves the animation to a .splv
file.
What this script does
- Creates a 3D scene of size 128×128×128
- Spawns a cosmic formation with:
- Swirling stardust particles in spiral arms
- Glowing star cores that pulse and grow
- Nebula gas clouds with color gradients
- Central gravitational core with intense brightness
- Animates the cosmic birth process for 10 seconds at 30 FPS
- Outputs the file
cosmic_formation.splv
that you can play in your viewer
How it works (simplified)
-
Voxel volume Each frame is a 3D grid filled with RGBA values (
SIZE × SIZE × SIZE × 4
). -
Spiral arms Stardust particles follow mathematical spiral patterns, rotating around a central core.
-
Star formation Individual stars grow from tiny points into glowing spheres with pulsing brightness.
-
Nebula clouds Colorful gas clouds use Perlin noise for organic, flowing shapes with purple, blue, and pink gradients.
-
Central core A bright gravitational center that influences particle motion and emits intense light.
-
Animation loop A normalized time variable
t
cycles from0 → 2π
, ensuring the cosmic dance loops smoothly. -
Encoding Frames are passed into
splv.Encoder
, which writes them into the.splv
video file.
Try it yourself
Install requirements first:
pip install spatialstudio numpy tqdm
Then copy this script into cosmic_formation.py
and run:
python cosmic_formation.py
Full Script
import numpy as np
from spatialstudio import splv
from tqdm import tqdm
# Scene setup
SIZE, FPS, SECONDS = 128, 30, 10
FRAMES = FPS * SECONDS
CENTER_X = CENTER_Y = CENTER_Z = SIZE // 2
OUT_PATH = "../outputs/cosmic_formation.splv"
# Cosmic settings
SPIRAL_ARMS = 3
STAR_COUNT = 150
DUST_PARTICLES = 800
CORE_RADIUS = 12
def add_voxel(volume, x, y, z, color, alpha=255):
if 0 <= x < SIZE and 0 <= y < SIZE and 0 <= z < SIZE:
volume[x, y, z, :3] = color
volume[x, y, z, 3] = alpha
def noise3d(x, y, z, scale=0.1):
"""Simple 3D noise function for nebula effects"""
return (np.sin(x * scale) * np.cos(y * scale) * np.sin(z * scale) +
np.sin(x * scale * 2.3) * np.cos(z * scale * 1.7)) * 0.5 + 0.5
def generate_central_core(volume, cx, cy, cz, t):
"""Generate the bright gravitational core"""
core_pulse = 1.0 + 0.3 * np.sin(t * 3.0)
core_color = (255, 200, 100)
for dx in range(-CORE_RADIUS, CORE_RADIUS+1):
for dy in range(-CORE_RADIUS, CORE_RADIUS+1):
for dz in range(-CORE_RADIUS, CORE_RADIUS+1):
dist = np.sqrt(dx*dx + dy*dy + dz*dz)
if dist <= CORE_RADIUS:
intensity = (1.0 - dist/CORE_RADIUS) * core_pulse
color = tuple(int(c * intensity) for c in core_color)
alpha = min(255, int(intensity * 255))
add_voxel(volume, cx+dx, cy+dy, cz+dz, color, alpha)
def generate_spiral_arms(volume, cx, cy, cz, t):
"""Generate rotating spiral arms with stardust"""
for arm in range(SPIRAL_ARMS):
arm_offset = (arm / SPIRAL_ARMS) * 2 * np.pi
for i in range(200):
# Spiral mathematics
radius = 5 + i * 0.3
angle = arm_offset + (i * 0.15) + (t * 0.5)
height_var = np.sin(i * 0.1 + t) * 8
# 3D spiral position
x = cx + int(radius * np.cos(angle))
y = cy + int(height_var)
z = cz + int(radius * np.sin(angle))
# Stardust color based on distance from core
distance_factor = min(1.0, radius / 40.0)
dust_colors = [
(100, 50, 200), # Purple (inner)
(50, 100, 255), # Blue (middle)
(200, 100, 255), # Pink (outer)
]
color_idx = int(distance_factor * (len(dust_colors) - 1))
color = dust_colors[color_idx]
# Add some randomness for natural look
if (i + int(t*10)) % 3 == 0:
add_voxel(volume, x, y, z, color, 180)
def generate_forming_stars(volume, cx, cy, cz, t):
"""Generate individual stars in formation"""
np.random.seed(42) # Consistent star positions
for star_id in range(STAR_COUNT):
# Random position around the galaxy
angle = np.random.random() * 2 * np.pi
radius = 15 + np.random.random() * 35
height = (np.random.random() - 0.5) * 20
# Star position
star_x = cx + int(radius * np.cos(angle + t * 0.2))
star_y = cy + int(height + np.sin(t * 1.5 + star_id) * 3)
star_z = cz + int(radius * np.sin(angle + t * 0.2))
# Star formation progress (some stars form faster)
formation_speed = 1.0 + (star_id % 3) * 0.5
star_age = (t * formation_speed + star_id) % (2 * np.pi)
star_size = max(1, int(3 * (np.sin(star_age) * 0.5 + 0.5)))
# Star colors based on type
star_types = [
(255, 255, 200), # Yellow dwarf
(200, 200, 255), # Blue giant
(255, 150, 100), # Red giant
(255, 255, 255), # White dwarf
]
star_color = star_types[star_id % len(star_types)]
# Generate star as small sphere
for dx in range(-star_size, star_size+1):
for dy in range(-star_size, star_size+1):
for dz in range(-star_size, star_size+1):
if dx*dx + dy*dy + dz*dz <= star_size*star_size:
brightness = 0.7 + 0.3 * np.sin(t * 2 + star_id)
color = tuple(int(c * brightness) for c in star_color)
add_voxel(volume, star_x+dx, star_y+dy, star_z+dz, color)
def generate_nebula_clouds(volume, cx, cy, cz, t):
"""Generate colorful nebula gas clouds"""
cloud_colors = [
(80, 20, 120), # Deep purple
(40, 80, 160), # Deep blue
(120, 40, 100), # Magenta
]
# Sample points throughout the space
for x in range(cx-50, cx+50, 3):
for y in range(cy-25, cy+25, 3):
for z in range(cz-50, cz+50, 3):
if 0 <= x < SIZE and 0 <= y < SIZE and 0 <= z < SIZE:
# Use 3D noise for organic cloud shapes
noise_val = noise3d(x + t*5, y, z + t*3, 0.05)
# Only draw where noise creates cloud density
if noise_val > 0.6:
intensity = (noise_val - 0.6) * 2.5
distance_from_center = np.sqrt((x-cx)**2 + (y-cy)**2 + (z-cz)**2)
# Clouds fade with distance
if distance_from_center < 60:
color_factor = distance_from_center / 60.0
color_idx = int(color_factor * (len(cloud_colors) - 1))
base_color = cloud_colors[color_idx]
color = tuple(int(c * intensity) for c in base_color)
alpha = min(255, int(intensity * 100))
add_voxel(volume, x, y, z, color, alpha)
def generate_cosmic_scene(volume, t):
"""Generate the complete cosmic formation scene"""
generate_nebula_clouds(volume, CENTER_X, CENTER_Y, CENTER_Z, t)
generate_spiral_arms(volume, CENTER_X, CENTER_Y, CENTER_Z, t)
generate_forming_stars(volume, CENTER_X, CENTER_Y, CENTER_Z, t)
generate_central_core(volume, CENTER_X, CENTER_Y, CENTER_Z, t)
# Initialize encoder
enc = splv.Encoder(SIZE, SIZE, SIZE, framerate=FPS, outputPath=OUT_PATH, motionVectors="off")
# Generate animation frames
for frame in tqdm(range(FRAMES), desc="Generating cosmic formation"):
volume = np.zeros((SIZE, SIZE, SIZE, 4), dtype=np.uint8)
t = (frame / FRAMES) * 2 * np.pi
generate_cosmic_scene(volume, t)
enc.encode(splv.Frame(volume, lrAxis="x", udAxis="y", fbAxis="z"))
enc.finish()
print(f"Created {OUT_PATH}")
Next steps
- Increase
STAR_COUNT
to create a denser galaxy - Modify
SPIRAL_ARMS
to change the galaxy structure (try 2 for a binary system) - Experiment with
cloud_colors
for different nebula types - Add
+ int(t*2)
to star positions to make the galaxy expand over time - Adjust
SECONDS
for longer cosmic evolution sequences