Rapunzel, Rapunzel, let down your.. verlet physics simulation?

Recently I was commissioned to create motion graphics for Northwest Childrens Theater to be used in a production of Rapunzel. The set features a large projection screen for scene-setting rather than having physical set pieces (the play is a pop-rock musical and most of the set resembles a stadium concert stage). Among the challenges of creating dynamic animated content, a major aspect of the show is to display Rapunzel's hair as it's deployed from the tower window. http://vimeo.com/35366140

The script calls for the hair to be let out and pulled back up many times so I didn't want to use a single animation as it would become quite repetitive after seeing it for the second or third time. Like the rest of the motion content in the play I decided it'd have to be a dynamic system rather than a pre-rendered video.  Using processing, I hacked out several tests before I had what I wanted.  Once I was happy with the motion I integrated the resulting code into the larger eclipse project that I had been working on for the rest of the performance.  Here's a little review of where I started and the progression from concept to final implementation.

Before writing code I spent a few minutes drawing out what I was aiming for.  My rough idea was to position a bunch of image segments along a bezier curve.  By adjusting the offset of each segment along the curve I could then animate the hair to make it look like it was being lowered from the window.

Planning!

Before writing code I spent a few minutes drawing out what I was aiming for. My rough idea was to position a bunch of image segments along a bezier curve. By adjusting the offset of each segment along the curve I could then animate the hair to make it look like it was being lowered from the window.

concept sketching

Test 1 : Segmented bezier spline

The first test was to get a series of connected nodes moving along a bezier spline. This would later become the basis for drawing a series of hair segments aligned along the path.

bezier segments

Test 2: Images aligned along a bezier spline

Next, I added some code to draw images at each point in the segmented path. The angle of each image is calculated via atan2 using the coordinates of the target point and the neighboring point. The results worked well but started to look funny when the curve was more extreme since the joints between each image became very obvious.

images on bezier

Test 3: Drawing a single textured mesh

The previous technique worked when motionless but when animated it looked sort of like links in a chain rather than a contiguous braid of hair. I also wanted to be able to use a single image of hair rather than ask the illustrator, Caitlin Hamilton, to draw a bunch of individual segments. This turned out to be easier than I thought since I already had the code done to figure out the angles of each segment. Vertices are positioned perpendicularly on each side of a segment and the mesh is drawn from end to end as a single quad strip.

At this point I felt like I was getting close to finished, but the motion of the hair really didn't feel right. I added some random movement to the bezier control points so the hair would appear to sway, but the extending motion along the path had an unnatural and sort of creepy look to it. This lead to something I thought of in my initial brain storming, but had dismissed as overkill.

bezier mesh

Test 4: Verlet physics simulation!

The last test was more of a complete re-do than an iterative development. Rather than use a bezier curve, I decided to go for an actual physics simulation of linked nodes. Thanks to toxiclibs this was a fairly simple task, and fortunately I was able to use a bunch of the existing code to calculate segment angles and build the textured mesh for rendering. As soon as I saw it in motion it was obviously the superior solution.

This final test worked great and I quickly set about integrating it into the performance tool. The deploy/retract animation is achieved by raising and lowering the top end point of the verlet particle string. There are also some invisible constraints which guide the particles making it look like they’re moving out and over the window sill (shown as red shapes in the above screen shots). It sure seemed like overkill when I though of this but I’m really glad I gave it a try. The results are exactly what I was shooting for in the beginning, and after lots of testing I’m fairly sure the physics won’t glitch out and ruin the show.  

verlet particle chain

data over time

First, a little history: When I was in my teens my friends and I used to play around on our computers with a program called "deluxe paint animation" which was, at the time, was a quite powerful graphics and animation tool for the PC.  Not only did it provide basic painting capabilities but it also included some cutting edge animation tools like motion tweening, morphing, and so on.  All of this ran at 320x200 pixels with an eyeball popping 256 color fixed palette.

delux paint animation

The other day while cleaning out a closet my brother came across an old floppy disk which, according to the label, held part of an animation project made by one of our close friends.  As amazing as it was to find the disk, the file was corrupt and couldn't be read; all attempts to view the now 20 year old animation failed.  It was part one of a science fiction saga titled "Porth" that our friend Cory had made (when he was fifteen) by stretching the animation tool to the absolute limits. In addition to being an interesting technical challenge, it was worth putting some effort into saving this file for nostalgia alone.

porth floppy

Many years ago I wrote a Pascal library to decode PCX images, and I had a hunch that the ANM format might use a similar run-length encoding scheme.  Upon recieving the corrupted file from my brother I set about scouring the internet for details of the ANM file format which Delux Paint Animation used for storing animated sequences.

After digging through some long abandoned forums and various geocities-styled nooks of the web, I came across some crusty old C source that claimed to decode ANM files. I'm not fluent in C but I figured it was at least a place to start.  It was clear that my assumption about the encoding method was correct.  After a couple hours of head scratching I managed to decipher the code enough to figure out the details of the data format.  Rather than start with a file I knew to be corrupt, I used an old EA Sports ANM file that I found online to test my code before delving into the digital archaeology project that my brother had unearthed.

ea sports animation

After a few hours of digging into the corrupt file with a hex editor, I had most of the original content playing back in all of it's pixelated glory. No crashes, just a handful of garbage frames introduced by reliance on a flimsy physical media never meant for long term archival data storage.

I was able to hack around the busted frames and managed to salvage most of the original file.  Unfortunately the animation encoding scheme works based on the delta between frames so there's still some visual corruption but I saved most of the content.  Here's the resurrected chapter of the Porth saga saved from a pile of corrupt bytes.