Creating Spaceship Animation
Spaceship Animation Guide
This guide walks you through how to generate a looping 3D voxel animation of a spaceship using SpatialStudio.
The script creates a detailed spaceship that hovers, rotates, and emits engine trails 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
- Builds a detailed spaceship with:
- A metallic hull body
- Colorful engine thrusters
- Animated exhaust trails
- Blinking navigation lights
- Animates the ship hovering and rotating for 8 seconds at 30 FPS
- Outputs the file
spaceship.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
). -
Spaceship hull The main body is constructed using ellipsoid shapes with metallic gray coloring and surface details.
-
Engine thrusters Multiple engine blocks are positioned at the rear, each emitting colored exhaust particles.
-
Exhaust trails Dynamic particle systems create trailing fire effects that fade over distance.
-
Navigation lights Blinking red and green lights pulse at different intervals for realism.
-
Animation loop A normalized time variable
t
cycles from0 → 2π
, creating smooth hovering motion and rotation. -
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 spaceship.py
and run:
python spaceship.py
Full Script
import numpy as np
from spatialstudio import splv
from tqdm import tqdm
# Scene setup
SIZE, FPS, SECONDS = 128, 30, 8
FRAMES = FPS * SECONDS
CENTER_X = CENTER_Y = CENTER_Z = SIZE // 2
OUT_PATH = "../outputs/spaceship.splv"
# Spaceship settings
SHIP_LENGTH = 30
SHIP_WIDTH = 12
SHIP_HEIGHT = 8
ENGINE_COUNT = 4
def add_voxel(volume, x, y, z, color):
if 0 <= x < SIZE and 0 <= y < SIZE and 0 <= z < SIZE:
volume[x, y, z, :3] = color
volume[x, y, z, 3] = 255
def generate_hull(volume, cx, cy, cz, t):
hull_color = (160, 160, 180)
detail_color = (120, 120, 140)
# Main body - elongated ellipsoid
for dx in range(-SHIP_LENGTH//2, SHIP_LENGTH//2 + 1):
for dy in range(-SHIP_HEIGHT//2, SHIP_HEIGHT//2 + 1):
for dz in range(-SHIP_WIDTH//2, SHIP_WIDTH//2 + 1):
# Ellipsoid equation
dist = (dx*dx)/(SHIP_LENGTH*SHIP_LENGTH*0.25) + \
(dy*dy)/(SHIP_HEIGHT*SHIP_HEIGHT*0.25) + \
(dz*dz)/(SHIP_WIDTH*SHIP_WIDTH*0.25)
if dist <= 1.0:
# Add surface details
if abs(dx) % 8 == 0 or abs(dz) % 6 == 0:
color = detail_color
else:
color = hull_color
add_voxel(volume, cx+dx, cy+dy, cz+dz, color)
def generate_engines(volume, cx, cy, cz, t):
engine_color = (80, 80, 100)
engine_positions = [
(-2, -1), (-2, 1), (2, -1), (2, 1)
]
# Engine blocks at the rear
for i, (ey, ez) in enumerate(engine_positions):
for dx in range(3):
for dy in range(-1, 2):
for dz in range(-1, 2):
ex = cx - SHIP_LENGTH//2 - dx - 2
add_voxel(volume, ex, cy + ey + dy, cz + ez + dz, engine_color)
def generate_exhaust_trails(volume, cx, cy, cz, t):
trail_colors = [
(255, 100, 0), # Orange
(255, 200, 0), # Yellow
(255, 50, 50), # Red
(100, 150, 255) # Blue
]
engine_positions = [
(-2, -1), (-2, 1), (2, -1), (2, 1)
]
for i, (ey, ez) in enumerate(engine_positions):
base_color = trail_colors[i % len(trail_colors)]
# Create particle trail
for trail_len in range(15):
intensity = 1.0 - (trail_len / 15.0)
if intensity > 0.1:
# Random spread for particle effect
spread_y = int(np.sin(t * 3 + i + trail_len * 0.3) * 2)
spread_z = int(np.cos(t * 2.5 + i + trail_len * 0.2) * 2)
ex = cx - SHIP_LENGTH//2 - trail_len - 5
final_color = tuple(int(c * intensity) for c in base_color)
# Main trail
add_voxel(volume, ex, cy + ey, cz + ez, final_color)
# Particle spread
if trail_len > 3:
add_voxel(volume, ex, cy + ey + spread_y, cz + ez + spread_z,
tuple(int(c * intensity * 0.7) for c in base_color))
def generate_navigation_lights(volume, cx, cy, cz, t):
# Blinking navigation lights
red_blink = int(abs(np.sin(t * 4)) > 0.7)
green_blink = int(abs(np.sin(t * 3.5 + 1)) > 0.7)
if red_blink:
# Red light on port side
add_voxel(volume, cx + 5, cy, cz - SHIP_WIDTH//2 - 1, (255, 0, 0))
add_voxel(volume, cx + 4, cy, cz - SHIP_WIDTH//2 - 1, (255, 0, 0))
if green_blink:
# Green light on starboard side
add_voxel(volume, cx + 5, cy, cz + SHIP_WIDTH//2 + 1, (0, 255, 0))
add_voxel(volume, cx + 4, cy, cz + SHIP_WIDTH//2 + 1, (0, 255, 0))
def generate_cockpit(volume, cx, cy, cz, t):
cockpit_color = (50, 50, 80)
window_color = (100, 200, 255)
# Cockpit structure
for dx in range(SHIP_LENGTH//4):
for dy in range(-2, 3):
for dz in range(-3, 4):
if abs(dy) <= 1 and abs(dz) <= 2:
ex = cx + SHIP_LENGTH//2 - dx
add_voxel(volume, ex, cy + dy + 2, cz + dz, cockpit_color)
# Cockpit windows
for dx in range(3):
for dz in range(-1, 2):
ex = cx + SHIP_LENGTH//2 - dx
add_voxel(volume, ex, cy + 3, cz + dz, window_color)
def generate_spaceship(volume, cx, cy, cz, t):
# Apply gentle hovering motion
hover_y = int(3 * np.sin(t * 1.5))
# Apply slow rotation
rotation = t * 0.3
rot_x = int(2 * np.cos(rotation))
rot_z = int(2 * np.sin(rotation))
final_cx = cx + rot_x
final_cy = cy + hover_y
final_cz = cz + rot_z
generate_hull(volume, final_cx, final_cy, final_cz, t)
generate_engines(volume, final_cx, final_cy, final_cz, t)
generate_exhaust_trails(volume, final_cx, final_cy, final_cz, t)
generate_navigation_lights(volume, final_cx, final_cy, final_cz, t)
generate_cockpit(volume, final_cx, final_cy, final_cz, t)
def generate_scene(volume, t):
generate_spaceship(volume, CENTER_X, CENTER_Y, CENTER_Z, t)
enc = splv.Encoder(SIZE, SIZE, SIZE, framerate=FPS, outputPath=OUT_PATH, motionVectors="off")
for frame in tqdm(range(FRAMES), desc="Generating spaceship"):
volume = np.zeros((SIZE, SIZE, SIZE, 4), dtype=np.uint8)
t = (frame / FRAMES) * 2*np.pi
generate_scene(volume, t)
enc.encode(splv.Frame(volume, lrAxis="x", udAxis="y", fbAxis="z"))
enc.finish()
print(f"Created {OUT_PATH}")
Next steps
- Modify
SHIP_LENGTH
,SHIP_WIDTH
, andSHIP_HEIGHT
to create different ship designs. - Change
ENGINE_COUNT
and engine positions for different propulsion configurations. - Add more complex exhaust patterns by adjusting the trail generation logic.
- Experiment with different navigation light patterns and colors.
- Try adding weapon systems or cargo bays to the hull design.