This repo holds the pipeline I use to render the liquified octopus on my website. The main attraction is the renderer, which sets up a LiquidFun environment to simulate the water particles and displays the results with glium.
There are also a few python scripts that generate the octopus outline for the renderer and to compress the final results.
I'm using my own fork of a fork of the Rust liquidfun bindings because that is what the open source do. Otherwise, the code and guide should be straightforward.
To run it, install Rust and run:
gzip -dk segments.json.xz # Decompress this file
cargo run --release # Woohoo!
You'll see an octopus like the one above pop up! The renderer will set up the scene which takes some time, since it waits for particles to settle into place, and then it will run the simulation and save frames to frames-rust.bin
.
I've put some care into this project since there exist few other Rust + LiquidFun projects and it may be interesting to generative artisters or game devvers. There's only about 300 lines of code here and it's split into two files:
src/main.rs
: Does the drawing! It retrieves world state from LiquidFun and draws everything.src/model.rs
: Does the simulation! It sets up LiquidFun, adds particles, and records their positions to the fileframes-rust.bin
.
Disclaimer: Despite the cute title heading, the project from here on out is a mess.
There are a few dependencies you're going to need. I'm just including these files below (which I use for my website) in case they're of inspiration to anyone. If you'd actually like to run them, good luck.
draweyes.py
: Chooses pupils for the octopus's eyes by sampling eyeballs. Also sets up clipping paths and animations.drawtrace.py
: Sets up thatsegments.json
file for running the simulation. This script re-traces an svg file to get straight lines that can be rendered with LiquidFun.drawframes.py
: Parses the simulation output to show you the results at the correct FPS. It also closes the holes in the frames (i.e. dilation then erosion) to help the file compress smaller; the holes appear randomly so add unnecessary entropy.compression.py
: Compresses the resulting frames into new frames; more details are below!
I spent a whole night trying various compression schemes and I'm very proud of my productivity and would like to tell you how it went. The frames, uncompressed, weigh about 30 MB. That's ... a lot for a website. But here's the magic: with some simple techniques™ I can beat Gzip's 2.2 MB (okay more like tie but I still win). And Gzipping-the compressed frames further halves the file size!
- Gzipping
frames-rust.bin
: 2.19 MB - Special compression magic™: 2.17 MB
- Gzipping compression magic™: 1.29 MB
You can read more here if you are tickled with curiosity.