Fluid engine

Discuss issues specific to the Flash/AS3 port of Box2D
Posts: 5
Joined: Wed Aug 03, 2011 5:59 am

Fluid engine

Postby ErikSombroek » Mon Sep 05, 2011 1:49 am


I ported the java version of the box2d fluids (http://www.jbox2d.org/liquid/) to AS3.
I attached it to this topic.

I was hoping to squeeze more performance out of it. I get a average of 19 FPS running 300 particles. I really want to boost this to 500 particles + and a steady 30FPS.
You guys any idea's on how to add to the performance?


Fluid Engine
(224.11 KiB) Downloaded 584 times

Posts: 15
Joined: Mon Oct 10, 2011 4:34 pm

Re: Fluid engine

Postby sicklebrick » Mon Oct 10, 2011 5:01 pm

I've tried a number of ways to optimise the code without reducing the number of particles, nothing seemed to work too well.
In the end, it was the rendering technique that made the difference.

Stuff that didn't work:
-Shifted the code over to a Flashdevelop project to see perhaps if the latest framework did a better job than CS4.
-Switching all function specific vars to public/private made no real difference as I suspected it might.
(including a lot of box2d functions like step())
-I had a look through most of the box2d engine for any cases of something:int = (number/number),
as performing floating point math on an int is noticeably slow. (try it, you can lose 5-10fps)
-I replaced all of the dynamic arrays with private vector< vector< int> > etc, to see if that helped. Didn't really.
-Fixed all of the function definitions, and explicitly set data types, and return types... didn't do much.
-After all of that, I doubt I've squeezed a single extra frame per second out of the engine.

I did find one nice solution for making it look watery though.
-added a numberOfNeighbours variable to b2body
-a second catchupNeighbours value was added.
-when counting neighbours in step2() numberOfNeighbours is set.
-on each frame: catchupNeighbours += ((numberOfNeighbours - catchupNeighbours)/10), so the value slooowly grows/shrinks.
-now draw a blob for each body.
-set the blob's scale to a value dependant on the number of neighbours. i.e. blob.scale = (catchupNeighbours/3 )+1;
-set a nice max-min. (fiddle with it)
So now the blobs will grow as the liquid gets closer to more liquid.

I rendered the blobs like meta balls, as they look fairly liquidy..and to be honest, it's quite a nice simulation, running at 30fps.
Cheers for the port, it's great fun...Sploosh!

Posts: 5
Joined: Wed Aug 03, 2011 5:59 am

Re: Fluid engine

Postby ErikSombroek » Tue Oct 11, 2011 12:10 am

Hello Sicklebrick,

Great to see someone took a shot at it.
I would be really interested to see some of your source, specially the optimized vector arrays and the metaballs (that is like a blur filtering with thresholds thats converted back to textures right?).

I also had a another idea to boost the speed up but i havnt implemented it yet.

The engine runs over 8 neightbours for every node. In this way:


for 300 particles this ends up in ~2400 neighbours to look at.
But some nodes are looked at 8 times. for example when you set the node at any of the above 8 numbers you'll still be running over N in the loop.
I want to drop some nodes when they are looked at.


I want to make a frame switch which does the following;

switch 1:


switch 2:


This way it splits the calculations over 2 frames ( which makes the 'physics' run at half the speed ) but with good tweaking of settings it will be allot faster and still look OK.
Also switch 1 allone might be enough for semi-realistic physics ( which i havnt tested yet).

Haha no problem for the port!



Posts: 16
Joined: Sat Aug 06, 2011 5:32 am

Re: Fluid engine

Postby Schrodinger'sCat » Tue Oct 11, 2011 5:14 pm

Would love to see how this is all going! Very good to see that the Flash Box2D is getting some more work done to it.

Posts: 15
Joined: Mon Oct 10, 2011 4:34 pm

Re: Fluid engine

Postby sicklebrick » Thu Oct 20, 2011 5:29 am

Heyhey, been a little busy and forgot to check back.. sorry 'bout that!

Would love to know how the alternating neighbours idea has worked out. I can't see things getting too wobbly, over the course of one frame anyway. I was about to give it a shot, but plain can't be bothered right now :p

After the last post I got a bit curious about the speed of function calls and stuff, and did this wee example:
I'm thinking that maybe inlining the hashX, hashY and map functions could speed things up a little (at the cost of readablilty).. but again, lack of time!

If I have some time this afternoon, I'll have a bash at it, but for now, here's a few of the changes:
(My full source is a mess from declaring most of the variables private, so a few chunks will have to do.)

Replacing arrays with typed vectors. (slightly faster according to some articles).

Code: Select all

         //sexy 3d vectors
         hash = new Vector.<  Vector.<  Vector.<int>   >   >();
         for (var i:Number = 0; i < 40; ++i)
            hash.push( new Vector.<  Vector.<int>   >() );
            for (var j:Number = 0; j < 40; ++j)
               hash[i].push( new Vector.<int>() )

Setting the body's numNeighbours in the applyLiquidConstraNumber function:

Code: Select all

   private function applyLiquidConstraNumber(deltaT)
      body.neighboursTarg. = neighbours.length;

The cheap ass way of drawing metaballs.
Kinda sucks how the marching squares algorithm could almost use the same structure as the liquid if there were enough cycles left. (fluidblob is a circle I drew in the flash IDE).

Code: Select all

      private var spriteSource:fluidblob = new fluidblob();      
      private function drawBlobs():void {
         var scaleVar:Number = 1;
         var bx:Number;
         var by:Number;
         fluidData.fillRect( new Rectangle(0, 0, fluidData.width, fluidData.height), 0x00000000);
         secondData.fillRect( new Rectangle(0, 0, fluidData.width, fluidData.height), 0x00000000);
         for each ( var b:b2Body in liquid ) {
               bx = b.GetPosition().x * 30;
               by = b.GetPosition().y * 30;
               //grow or shrink slowly over several frames
               b.neighbours += (b.neighboursTarg - b.neighbours) / 100;
               scaleVar = (b.neighbours / 3) + 1;
               if (scaleVar < 0.5 ) scaleVar = 0.5;
               if (scaleVar > 1.7) scaleVar = 2;
               spriteSource.scaleX = scaleVar;
               spriteSource.scaleY = scaleVar;
               fluidBitmap.bitmapData.draw( spriteSource, new Matrix(scaleVar, 0, 0, scaleVar,  bx, by ) );

         //blur the whole thing
         fluidData.applyFilter( fluidData, new Rectangle(0, 0, fluidData.width, fluidData.height), new Point(0, 0), new BlurFilter(18, 18, 1) );
         fluidBitmap.visible = false;      
         //then set the threshhold in a second bitmapdata
         secondData.threshold( fluidData, new Rectangle(0, 0, fluidData.width, fluidData.height), new Point(0, 0), ">=",  0xFF009090, 0xFF0000CC, 0x00FFFFFF, false );

Here it is running 150 particles:
(link subject to change as I get around to writing an article about it)

Oh, almost forgot, if you avoid setting LIQUID_Number, you can still get a decent simulation with a bunch more particles.
temp_blobs.png (37.25 KiB) Viewed 4324 times

Posts: 1
Joined: Fri Sep 21, 2012 12:41 pm

Re: Fluid engine

Postby shoany » Fri Sep 21, 2012 12:45 pm

Hi there,
I realize it's a long shot and it's been a year since you posted this, but any chance you could pop your modification source files online? I think I get the general concept but haven't been successful in translating the general concept into working code. =)


Return to “Flash”

Who is online

Users browsing this forum: Baidu [Spider] and 1 guest