spatialstudio encoding basics and techniques

in the previous tutorial, you successfully created your first spatial - a simple red cube moving through 3d space. now it's time to unlock the full potential of spatialstudio by exploring its powerful api in greater depth.

building on your foundation

you now have example.splv from our previous tutorial - a basic but complete spatial video. today, we'll create something far more intricate and learn the techniques professional developers use to craft compelling voxel content.

understanding the frame object

the frame object is the heart of spatialstudio. think of each frame as a 3d canvas where you paint voxels to create a single moment in your 4d video. understanding how to manipulate frames efficiently is crucial for creating complex spatial content.

frame fundamentals

a frame represents a single 3d voxel snapshot with defined width, height, and depth dimensions. it's your building block for creating spatial videos:

from spatialstudio import splv

# Create a frame with specific dimensions
w, h, d = 128, 128, 128
frame = splv.Frame(w, h, d)

essential frame methods

let's explore the most important methods for manipulating voxels within frames:

individual voxel control

# Set a single voxel at coordinates (x, y, z)
frame.set_voxel(64, 64, 64, voxel=(255, 128, 0))  # Orange voxel

# Get the color of a voxel at specific coordinates  
color = frame.get_voxel(64, 64, 64)
print(f"Voxel color: {color}")  # Returns (255, 128, 0)

region filling (the powerhouse method)

the fill method is your primary tool for creating larger voxel structures:

# Fill a rectangular region with voxels
frame.fill(xMin, yMin, zMin, xMax, yMax, zMax, voxel=(r, g, b))

# Example: Create a blue wall
frame.fill(10, 50, 10, 15, 80, 40, voxel=(0, 100, 255))

multi-object scene creation

let's put these methods to work by creating a frame with multiple colored objects:

# Create a complex scene in a single frame
frame = splv.Frame(128, 128, 128)

# Add a red floor
frame.fill(0, 0, 0, 128, 5, 128, voxel=(150, 50, 50))

# Add a blue pillar
frame.fill(30, 5, 30, 40, 60, 40, voxel=(50, 50, 200))

# Add a green cube floating above
frame.fill(70, 40, 70, 90, 60, 90, voxel=(50, 200, 50))

# Add individual yellow accent voxels
for i in range(0, 128, 16):
    frame.set_voxel(i, 65, 64, voxel=(255, 255, 0))

creating a complex custom animation

now let's create a sophisticated spatial that demonstrates advanced techniques. we'll build an animation featuring two objects with different movement patterns and color evolution:

complex_animation.py
from spatialstudio import splv
import math

# Set up our voxel space
w = h = d = 128
enc = splv.Encoder(w, h, d, framerate=30.0, outputPath="complex_animation.splv")

# Generate 150 frames (5 seconds at 30fps)
for frame_num in range(150):
    # Create a new frame
    f = splv.Frame(w, h, d)
    
    # Calculate animation progress (0.0 to 1.0)
    progress = frame_num / 149.0
    
    # Animated red cube - moves in a sine wave pattern
    red_x = int(20 + 60 * progress)  # Move horizontally
    red_y = int(40 + 20 * math.sin(progress * math.pi * 4))  # Sine wave vertically
    red_z = int(30 + 30 * math.sin(progress * math.pi * 2))  # Different sine wave in Z
    
    # Color shifts from bright red to dark red over time
    red_intensity = int(255 - 100 * progress)
    f.fill(red_x, red_y, red_z, red_x + 15, red_y + 15, red_z + 15, 
           voxel=(red_intensity, 0, 0))
    
    # Animated blue cube - moves in opposite direction with rotation effect
    blue_x = int(88 - 60 * progress)  # Move in opposite direction
    blue_y = int(60 + 15 * math.cos(progress * math.pi * 6))  # Cosine wave
    blue_z = int(50 + 40 * math.cos(progress * math.pi * 3))  # Different frequency
    
    # Color evolves from blue to cyan
    blue_green = int(100 * progress)
    f.fill(blue_x, blue_y, blue_z, blue_x + 12, blue_y + 12, blue_z + 12,
           voxel=(0, blue_green, 255))
    
    # Add a static green base that grows over time
    base_height = int(5 + 15 * progress)
    f.fill(50, 0, 50, 78, base_height, 78, voxel=(0, 150, 0))
    
    # Add sparkle effect - random yellow voxels
    if frame_num % 5 == 0:  # Every 5th frame
        for _ in range(8):
            spark_x = int(20 + 88 * (frame_num * 0.1) % 1.0)
            spark_y = int(80 + 20 * math.sin(frame_num * 0.3))
            spark_z = int(20 + 88 * (frame_num * 0.07) % 1.0)
            f.set_voxel(spark_x, spark_y, spark_z, voxel=(255, 255, 100))
    
    # Encode this frame
    enc.encode(f)

# Finalize the animation
enc.finish()
print("Complex animation saved as 'complex_animation.splv'")

understanding this advanced example

this example demonstrates several sophisticated techniques:

1. mathematical movement patterns

  • using math.sin() and math.cos() to create smooth, natural-looking motion
  • different frequencies create varied movement patterns for visual interest

2. color evolution over time

  • colors change gradually using the progress variable
  • creates dynamic visual effects as the animation plays

3. multiple object coordination

  • two cubes move independently with different patterns
  • a static base that grows over time provides visual anchoring

introduction to advanced encoding options

the encoder class offers powerful configuration options beyond the basic parameters we've used. while the defaults work well for most projects, understanding these options gives you professional-level control:

basic encoder configuration

# Standard encoder setup
enc = splv.Encoder(
    width=128, 
    height=128, 
    depth=128,
    framerate=30.0,
    outputPath="output.splv"
)

advanced encoder parameters

# Advanced encoder with optional parameters
enc = splv.Encoder(
    width=128, height=128, depth=128,
    framerate=30.0,
    outputPath="advanced_output.splv",
    # Advanced compression settings
    gopSize=30,           # Group of Pictures size for compression
    motionVectors=True,   # Enable motion vector compression
    vqMaxCentroids=256,   # Vector quantization settings
)

key advanced parameters:

  • gopsize: controls compression efficiency vs. seek performance
  • motionvectors: enable for better compression of moving objects
  • vqmaxcentroids: higher values = better quality, larger file size

your creative results

after running the complex animation script, you now have complex_animation.splv - a sophisticated 5-second spatial featuring:

  • two cubes moving in mathematically-driven patterns
  • evolving colors that change over time
  • a growing base structure
  • sparkling particle effects
  • smooth 30fps animation with 150 total frames

best practices recap

from today's exploration, here are key techniques to remember:

  1. use fill() for efficiency - it's much faster than setting individual voxels for large structures
  2. plan your coordinate system - think through your 3d space before animating
  3. leverage mathematical functions - sin(), cos(), and other math functions create natural motion
  4. consider performance - larger voxel spaces and longer animations require more processing time
  5. experiment with color evolution - gradual color changes add professional polish

what's next?

you've now mastered the fundamentals of creating sophisticated spatial content with spatialstudio! you can generate complex voxel animations with multiple objects, advanced movement patterns, and visual effects.

in our next tutorial, "viewing spatials on the web with spatialjs", we'll shift gears and learn how to display your amazing voxel creations on the web. you'll discover how to embed spatial players in websites, control playback through javascript, and share your 4d voxel videos with the world through interactive web experiences.