Sunday, August 2, 2009

Implementing navier stokes - the fun of fluid mechanics

A few weeks ago I got a new HP - tx2, basically one of the first 3 lappies that support NTrig's multi-touch functionality. 

The plan being to explore more intuitive ways to interact with large sets of data that's a lot more natural and organic than throwing figures into grids on the screen. This is my first tablet, and so far I've been pretty impressed - especially after cleaning it and putting on the easiest install of Windows (win 7) I've ever done (seriously, it found all the right drivers from the start, and have been stable ever since).

After a bit of messing around with nesher's excellent Multitouch Vista library, I started to wonder how to get a bit lower down in the code and implement a visualization, such as those DSP plugins for winamp/wmplayer. 

I wanted to go for something that was very responsive to the user, and physically accurate to the environment as I could. Starting where a lot of people start out - I dusted off the old math books and found that Navier Stokes could help out. The implementation has been written many times by many people, but this was my first time so things were a bit shaky.

The basic formula goes something like:



which in plain English reads something along the lines of "the flow velocity and density of some fluid over time is affected by external pressures, viscosity/diffusion and additional density sources"

Basically if you take a blob of red dye inside a square container of water to be 'density'; it can get have it's shape changed by whatever's pushing it around (ie water). Invariably it will disperse out as it gets pushed around, hence the density will slowly disintegrate.

Without thinking too much, I launched VS2008 and started a new winforms 3.5 project, the idea being I could just write the output to a new image and throw it in a picbox. At this point I wasn't as concerned with a good frame rate as I was with just getting it working.  This would come back to bite me.

After a couple of nights work, I finally had something that worked. More than that, it would launch, jump into full screen, then be manipulated with my finger on the touch screen. The down side was that I was getting about 3fps. 

It was this time that I decided to translate it over to C++, and run it with OpenGL under Ubuntu.  A few hours later the code was translated, and not only did it run much faster, i was able to squeeze out a better resolution. result:


So I achieved what I set out to do, at least as a good first step.

The next iteration is to then combine this with OpenCV and wire it to the projector. I'm aiming to add collision detection of the density & velocity so that it naturally wraps around whatever gets in its way. 

Once that's complete, it should be a relatively simple process of using an average background diff method to pull foreground objects out of a scene and use their silhouette as generators to modify the fluid scene.


Lessons learned from this? Winforms is definitely not the right technology for this sort of processing. That was sort of a given, but there's nothing like jumping in and thinking later. Despite jumping out of managed code, I still couldn't push it very hard.

I started down the path of DirectX, and then was considering going to XNA; but I really wanted to write it at a lower level where I could have much better control over how things were being calculated and displayed. OpenGL/C++ provided a good route, but I've heard a lot of good things about the performance of XNA - so the code might be written for a 3rd time just to squeeze a bit more juice out of the app.

No comments:

Post a Comment