"Reel Shadows" Boid Animations

Inspiration

Turning and turning in the widening gyre
The falcon cannot hear the falconer…
Somewhere in sands of the desert… all about it
Reel shadows of the indignant desert birds.
— WB Yeats, "The Second Coming"

Recently two great videos were making the rounds. The first is Brian Maffit's "Projector Snow," which depicts the beautiful and abstract result of projecting The Lorax out a window into a snow storm.

"Projector Snow"

I really wanted to try that, but as it happens I have neither a projector, a high-speed camera to capture the results with, nor a snow storm. As a result when my mind reached the inevitable "I wannna try!!" state my only option was software.

As it happens I was also thinking about a software version of the second video, Neels Castillon's "A Bird Ballet."

"A Bird Ballet"

Bird flocking behaviors are old hat. I've been viewing and fiddling with these algorithms for graphics and modeling projects for years. They're perennial examples in lectures and talks. To my eye though none of the examples come close to the real thing. My mind was already cranking on how to make a flocking system which would be more like those seen in "Bird Ballet" but also rendered in an interesting way. That last part is where "Projector Snow" comes in.

What I needed to adapt "Projector Snow" was a particle system to "project" an image onto, and what I needed to adapt "Bird Ballet" was a pretty way of coloring particles. "Reel Shadows" is the result of combining the two.

System

"Reel Shadows" starts with Craig Reynolds's basic Boids algorithm. The boids/agents/particles in my system fly through a 3d box, which is bounded above and below but wraps left-right and top-bottom. In order to get more interesting behavior than I tend to see in Boids models I also added a vector field to represent wind in the environment.

Animatic

The camera POV for all of these animations is from the top of the environment looking down. The wind field is represented by the grid of blue lines in the video.

I also placed an image between the camera and the top of the environment. To color each particle I traced a ray from it's location back to the camera; the color of the pixel in the image that that ray intersected was used to color the particle.

The following shows what you get using a static image for the coloring process. (The music is Chris Zabriskie's "Prelude #13.")

"Reel Shadows #0," using a static image as background

Here's the image used:

There are some other small tweaks, like changing the eccentricity of the agents based on their velocity, but they're not worth explaining.

Results

For the final results, I replace the still image with a frame of a movie. My first attempt uses Valerie Barto's "Abstract Animation." The music is Sean Archibald's "Sea Poem."

"Reel Shadows #1"

My second version draws from Terje Sorgjerd's stunning "The Arctic Light," using Marika Takeuchi's song by the same name. I think this one turned out way better than the first.

"Reel Shadows #2"

I've got some other versions planned. I've played around with adding a predator to the environment, making the cohesion/alignment/separation coefficients dynamic, using each agent's previous location to mimic a bit of the look from "Projector Snow," and having multiple sub-populations of agents with differing affinities for each other. I've also tried a soft-focus look for the rendering, but I'm not satisfied with it yet.

When I get these issues worked out I'll post a few more renderings of the results as well as the code, and hopefully an in-browser version using Processing.JS.

Update

"Reel Shadows #3"
"Reel Shadows #3" incorporates a few of the enhancements I mentioned. The particles are rendered in a soft focus, which makes it less like Maffit's "Projector Snow" but is probably an improvement overall. I've also made the cohesion parameter vary during the course of the animation, causing the particles to sometimes want to cluster closer together and other times to want to spread out.

Code

You can grab the source code for this here. I've been iterating on this in my sketchbook a bit since I wrote up this page, so the results you'll get from that code won't exactly match what I described above.