Creating Beehive Animation
3D Voxel Animation: Beehive
This guide walks you through how to generate a looping 3D voxel animation of a beehive using SpatialStudio.
The script creates a realistic beehive with buzzing bees that fly around it in organic patterns, then saves the animation to a .splv
file.
What this script does
- Creates a 3D scene of size 128×128×128
- Builds a hexagonal beehive structure with:
- Layered honeycomb texture
- Natural brown and amber coloring
- Detailed entrance hole
- Spawns 12 animated bees that:
- Buzz around the hive in figure-8 patterns
- Have yellow and black striped bodies
- Move with realistic wing flutter
- Animates the scene for 10 seconds at 30 FPS
- Outputs the file
beehive.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
). -
Beehive structure The hive is built using layered ovals that get smaller toward the top, creating a natural dome shape.
-
Honeycomb texture Hexagonal patterns are added to the surface using sine wave calculations for realistic texture.
-
Flying bees Each bee follows a unique orbital path around the hive with slight randomization for natural movement.
-
Bee bodies Bees are drawn as small ellipsoids with alternating yellow and black stripes.
-
Animation loop A normalized time variable
t
cycles from0 → 2π
, ensuring all motion 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 beehive.py
and run:
python beehive.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/beehive.splv"
# Beehive settings
HIVE_HEIGHT = 35
HIVE_BASE_RADIUS = 20
BEE_COUNT = 12
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_beehive(volume, cx, cy, cz, t):
# Main hive colors
hive_brown = (101, 67, 33)
hive_amber = (191, 148, 63)
dark_brown = (62, 39, 35)
# Build hive layers from bottom to top
for layer in range(HIVE_HEIGHT):
progress = layer / HIVE_HEIGHT
# Hive gets narrower toward top
layer_radius = int(HIVE_BASE_RADIUS * (1.0 - progress * 0.7))
y_pos = cy - HIVE_HEIGHT//2 + layer
# Create oval cross-section for each layer
for angle in np.linspace(0, 2*np.pi, layer_radius * 6):
for r in range(layer_radius):
x_offset = int(r * np.cos(angle))
z_offset = int(r * 0.8 * np.sin(angle)) # Slightly flattened
x, y, z = cx + x_offset, y_pos, cz + z_offset
# Honeycomb texture using sine waves
texture = np.sin(x * 0.4) * np.sin(z * 0.4) * np.sin(y * 0.3)
# Choose color based on texture and position
if texture > 0.3:
color = hive_amber
elif texture < -0.3:
color = dark_brown
else:
color = hive_brown
# Add some brightness variation
brightness = 0.8 + 0.4 * (0.5 + 0.5 * np.sin(t + x*0.1 + z*0.1))
final_color = tuple(int(c * brightness) for c in color)
add_voxel(volume, x, y, z, final_color)
# Create entrance hole
entrance_y = cy - 5
for dx in range(-4, 5):
for dz in range(-3, 4):
if dx*dx + dz*dz <= 12:
for depth in range(8):
add_voxel(volume, cx + dx - depth, entrance_y + dx//2, cz + dz, (0,0,0))
def generate_bee(volume, x, y, z, t, bee_id):
# Bee colors
bee_yellow = (255, 215, 0)
bee_black = (20, 20, 20)
wing_color = (200, 200, 255)
# Bee body (small ellipsoid)
body_length = 4
for i in range(-body_length, body_length + 1):
for j in range(-2, 3):
for k in range(-2, 3):
if i*i/16 + j*j/4 + k*k/4 <= 1:
# Alternating stripes
if abs(i) % 3 == 0:
color = bee_black
else:
color = bee_yellow
add_voxel(volume, x + i, y + j, z + k, color)
# Animated wings
wing_flutter = np.sin(t * 15 + bee_id) * 0.5
wing_positions = [
(2, 1, -3 + int(wing_flutter)), (2, 1, 3 - int(wing_flutter)),
(-2, 1, -3 + int(wing_flutter)), (-2, 1, 3 - int(wing_flutter))
]
for wx, wy, wz in wing_positions:
add_voxel(volume, x + wx, y + wy, z + wz, wing_color)
def generate_flying_bees(volume, cx, cy, cz, t):
for bee_id in range(BEE_COUNT):
# Each bee follows a unique orbital pattern
base_angle = (bee_id / BEE_COUNT) * 2 * np.pi
# Figure-8 pattern with some randomization
orbit_radius = 25 + 15 * np.sin(bee_id * 0.7)
speed = 1.0 + 0.5 * np.sin(bee_id * 1.3)
# Main orbital motion
angle = base_angle + t * speed
x_orbit = orbit_radius * np.cos(angle)
z_orbit = orbit_radius * np.sin(angle)
# Figure-8 vertical motion
y_orbit = 10 * np.sin(2 * angle + bee_id)
# Add some buzzing randomness
buzz_x = 3 * np.sin(t * 8 + bee_id * 2.1)
buzz_y = 2 * np.cos(t * 12 + bee_id * 1.7)
buzz_z = 3 * np.cos(t * 10 + bee_id * 2.3)
# Final bee position
bee_x = int(cx + x_orbit + buzz_x)
bee_y = int(cy + y_orbit + buzz_y)
bee_z = int(cz + z_orbit + buzz_z)
generate_bee(volume, bee_x, bee_y, bee_z, t, bee_id)
def generate_environment(volume, cx, cy, cz, t):
# Add some flowers around the base
flower_colors = [(255, 100, 150), (150, 100, 255), (255, 255, 100)]
for i in range(8):
angle = (i / 8) * 2 * np.pi
flower_distance = 40 + 10 * np.sin(i * 0.8)
fx = int(cx + flower_distance * np.cos(angle))
fz = int(cz + flower_distance * np.sin(angle))
fy = cy - HIVE_HEIGHT//2 - 5
# Simple flower - just a small cluster
color = flower_colors[i % len(flower_colors)]
for dx in range(-2, 3):
for dz in range(-2, 3):
if dx*dx + dz*dz <= 4:
add_voxel(volume, fx + dx, fy, fz + dz, color)
# Stem
for stem in range(1, 4):
add_voxel(volume, fx, fy - stem, fz, (34, 139, 34))
def generate_scene(volume, t):
generate_beehive(volume, CENTER_X, CENTER_Y, CENTER_Z, t)
generate_flying_bees(volume, CENTER_X, CENTER_Y, CENTER_Z, t)
generate_environment(volume, CENTER_X, CENTER_Y, CENTER_Z, t)
# Initialize encoder
enc = splv.Encoder(SIZE, SIZE, SIZE, framerate=FPS, outputPath=OUT_PATH, motionVectors="off")
# Generate all frames
for frame in tqdm(range(FRAMES), desc="Generating beehive"):
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
- Increase
BEE_COUNT
to create a busier hive scene - Modify
HIVE_HEIGHT
andHIVE_BASE_RADIUS
for different hive shapes - Add more flowers by changing the flower generation loop
- Experiment with bee flight patterns by adjusting the orbital calculations
- Try different honeycomb textures by modifying the sine wave parameters