Update June 2013: This program has been ported to WebGL!!!
The other day I came across this neat visual trick:
How to simulate liquid (Flash). It’s a really simple way to
simulate some natural-looking liquid.
- Perform a physics simulation of a number of circular particles.
- Render this simulation in high contrast.
- Gaussian blur the rendering.
- Threshold the blur.
I [made my own version][fun] in Java, using JBox2D for the
For those of you who don’t want to run a Java applet, here’s a video
demonstration. Gravity is reversed every few seconds, causing the
liquid to slosh up and down over and over. The two triangles on the
sides help mix things up a bit. The video flips through the different
components of the animation.
It’s not a perfect liquid simulation. The surface never settles down,
so the liquid is lumpy, like curdled milk. There’s also a lack of
cohesion, since JBox2D doesn’t provide cohesion directly. However, I
think I could implement cohesion on my own by writing a custom
JBox2D is a really nice, easy-to-use 2D physics library. I only had to
read the first two chapters of the Box2D manual. Everything
else can be figured out through the JBox2D Javadocs. It’s also
available from the Maven repository, which is the reason I initially
selected it. My only complaint so far is that the API doesn’t really
follow best practice, but that’s probably because it follows the Box2D
C++ API so closely.
I’m excited about JBox2D and I plan on using it again for some future
project ideas. Maybe even a game.
The most computationally intensive part of the process isn’t the
physics. That’s really quite cheap. It’s actually blurring, by far.
Blurring involves convolving a kernel over the image —
O(n^2) time. The graphics card would be ideal for that step, probably
eliminating it as a bottleneck, but it’s unavailable to pure Java. I
could have pulled in lwjgl, but I wanted to keep it simple,
so that it could be turned into a safe applet.
As a result, it may not run smoothly on computers that are more than a
couple of years old. I’ve been trying to come up with a cheaper
alternative, such as rendering a transparent halo around each ball,
but haven’t found anything yet. Even with that fix, thresholding would
probably be the next bottleneck — something else the graphics card
would be really good at.