Sunday, August 22, 2010

Digital Fluid (2000)

After spending time teaching my computer how to solve Rubik's cubes, I started thinking about writing something that would cater to my lifelong fascination with gooey matter and infinitely-derivable functions.  The first generation of GPUs had just come out (hardware transformation and lighting, oh my!) and it was time to put my 450$'s worth of graphics hardware to work.  Other than playing games, of course.  Ahem.

By tinkering over the course of a few nights, I wound up writing this little fluid simulation.  As it turns out, most of the computation performed wound up on the CPU, so it was taxing little more than the transfer rate of my AGP 4x bus.  However, it does shun vendor-specific extensions in favor of multipass rendering to layer the specular highlights onto the texture map.

The fluid patch is implemented using a height field; normals and other epiphenoma are derived from the vertex positions.  Texture coordinates are calculated using Snell's law, by putting the texture on a virtual plane behind the fluid patch.

The simulation itself isn't really that interesting from a mathematical standpoint - I was just experimenting, so all the code is ad hoc.  The positions are animated using different models.  For liquids, linear combinations of many simple closed-form sinusoidal decay solutions are used.  For the gooey-looking ones, a simple spring/damper model is used.

(Browsing this code ten years later, I can say that this being my second C++ program, the code stank a bit less than the cube solver. :P )

Be sure to pick HD if available over your connection... the low-resolution version looks like a tie-dye cow.

Lessons learned (or points confirmed):
  • Programmer art sometimes far outlives its intended longevity...  As of this writing, 10 years later, I still haven't replaced that Paint-produced bitmap.
  • Stuff doesn't necessarily need to be complicated to look decent.  In fact, the simpler it is, the easier it usually is to tweak the way you want it.  (Recall that this was in year 2000; register combiner cards were still quite mainstream.)

Rubik's Cube Screen Saver (2000)

Around the same time I was given my first copy of Visual Studio, I bought the OpenGL Superbible.  Feeding these two items through the transfer function of my deranged brain, I wound up brewing the following program as a first foray into both the worlds of C++ and modern API-based graphics programming (as opposed to writing to the metal).

The program solves rubik's cubes, bouncing them around the screen:

The algorithm is the same I first learned to use when solving the cube by hand - the original Singmaster method - and it's far from optimal.  I recorded sequences of moves interactively using a built-in "move editor", then wrote code that analysed the state of the cube and chose the algorithm to play back.  The debug mode output looks something like this:

Lessons learned:
  • As a first contact with the world of hardware abstraction layers, in terms of API design, OpenGL and GLUT are infinitely friendlier than DirectX 5.0.
  • Do read your employment contracts closely.  I got into somewhat serious trouble for posting a copy of this on NeHe, believing the IP belonged to me since I had created it on my own time.  Not so.
  • A 2,300 line switch statement does not constitute "artificial intelligence".  (I still laugh this one today.  In my defense, it's not because I didn't know better in terms of design; it's more that I was still learning so much about the language at the moment that there were more pressing points than learning about the constructs which would have enabled me to organise my code in a cleaner fashion.)