fluid dynamics

Share your advanced PureBasic knowledge/code with the community.
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

fluid dynamics

Post by gnasen »

Hey guys,
I was very interested in calculating fluids and coded an include to calculate fluids very fast, so they can be used in games etc.
The theory comes from the paper: "Real-Time Fluid Dynamics for Games" by "Jos Stam" and describes, how to write it in c, so I just converted and enhanced it with some features like walls or different layers. The basic theory is given by the Navier-Stokes Equations.

Image

some more pics: pic 2 pic 3

Features:
-create different fluid boxes and calculate them
-create walls and emitters
-manipulate the input/output directly for much speed
-very easy to use
-examples and help file

Download

Maybe someone needs it / wants to play with it.
greetings, gnasen
pb 5.11
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: fluid dynamics

Post by idle »

thanks.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: fluid dynamics

Post by djes »

Great! Thank you :)
pjay
Enthusiast
Enthusiast
Posts: 251
Joined: Thu Mar 30, 2006 11:14 am

Re: fluid dynamics

Post by pjay »

Great stuff, really enjoyed playing with this, thanks for posting.

I had to change the drawing routine though, as it was really slow on my laptop & didn't do the fluid dynamics any justice.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Re: fluid dynamics

Post by Joakim Christiansen »

pjay wrote:I had to change the drawing routine though, as it was really slow on my laptop & didn't do the fluid dynamics any justice.
If you made it faster then it would be nice of you to share those changes to the code.
I like logic, hence I dislike humans but love computers.
pjay
Enthusiast
Enthusiast
Posts: 251
Joined: Thu Mar 30, 2006 11:14 am

Re: fluid dynamics

Post by pjay »

Sure thing, I can only vouch that it's faster on my laptop though :)

Code: Select all

IncludeFile "fluid.pbi"

InitSprite()
InitKeyboard()
InitMouse()

Define X.i, Y.i
Define x1.f,y1.f,x2.f,y2.f,r.f,G.f,b.f
Global mouseX.i, mouseY.i, mouseX0.i, mouseY0.i

OpenScreen(800,600,32,"fluid")
#Fluid_Width = 40 : #Fluid_Height = 30
Global XSize = 800 / #Fluid_Width, YSize = 600 / #Fluid_Height
Global HXSize = XSize / 2, HYSize = YSize / 2
;/ create fluid: 
fluid_create(#Fluid_Width,#Fluid_Height,0.1,0,0,3,#True,10)

;/ create arrays to hold the output informations: !!! size must be (width+1)x(height+1) !!!
Global Dim *densR.f(#Fluid_Width + 1,#Fluid_Height + 1): Global Dim *densG.f(#Fluid_Width + 1,#Fluid_Height + 1) : Global Dim *densB.f(#Fluid_Width + 1,#Fluid_Height + 1)
Global Dim *velH.f(#Fluid_Width + 1,#Fluid_Height + 1) : Global Dim *velV.f(#Fluid_Width + 1,#Fluid_Height + 1)

Macro myMax(c)
  If c > 255
    c=255
  EndIf
EndMacro
Procedure input_stuff()
  
  Protected X.i,Y.i
  
  mouseX = MouseX() : mouseY = MouseY()
  
  *densR() = fluid_density_input(1)
  *densG() = fluid_density_input(2)
  *densB() = fluid_density_input(3)
  
  *velH() = fluid_velocity(#fluid_horizontal)
  *velV() = fluid_velocity(#fluid_vertical)
  
  X = mouseX * #Fluid_Width / 800 + 1
  Y = mouseY * #Fluid_Height / 600 + 1
  
  If KeyboardPushed(#PB_Key_1)
    *densR(X,Y) = 5000
  EndIf
  If KeyboardPushed(#PB_Key_2)
    *densG(X,Y) = 5000
  EndIf
  If KeyboardPushed(#PB_Key_3)
    *densB(X,Y) = 5000
  EndIf
  If KeyboardPushed(#PB_Key_4)
    fluid_wall_create(X,Y,2,2)
    fluid_wall_purge()
  EndIf
  If MouseButton(1)
    *velH(X-1,Y-1) = (mouseX-mouseX0)/2
    *velV(X-1,Y-1) = (mouseY-mouseY0)/2
    
    *densR(X-1,Y-1) = 5000
    If Random(1)
      *densG(X-1,Y-1) = 2500
    EndIf
  EndIf
  If MouseButton(2)

    *velH(X,Y) = (mouseX-mouseX0)/2
    *velV(X,Y) = (mouseY-mouseY0)/2
    *densB(X,Y) = 0
    *densR(X,Y) = 0
    *densG(X,Y) = 0
  EndIf
  If KeyboardReleased(#PB_Key_5)
    fluid_density_reset()
    fluid_wall_clear()
    For X = 1 To #Fluid_Width
      For Y = 1 To #Fluid_Height 
        *densR(X,Y) = 100
        *densG(X,Y) = 100
        *densB(X,Y) = 100
      Next
    Next
    
  EndIf
  If KeyboardReleased(#PB_Key_Up)
    fluid_emitter_velocity(X,Y,1,0,-1)
  EndIf
  If KeyboardReleased(#PB_Key_Down)
    fluid_emitter_velocity(X,Y,1,0,1)
  EndIf
  If KeyboardReleased(#PB_Key_Left)
    fluid_emitter_velocity(X,Y,1,-1,0)
  EndIf
  If KeyboardReleased(#PB_Key_Right)
    fluid_emitter_velocity(X,Y,1,1,0)
  EndIf
  
  mouseX0 = mouseX : mouseY0 = mouseY
  
EndProcedure

Repeat
  
  ExamineKeyboard()
  ExamineMouse()
  
  ;/ take out some density, otherwise it will get very full
  fluid_density_reset(1.000001)
  input_stuff()
  
  ;/ calculate the next density step. All emitters will be used automatically here.
  fluid_calc()

    ;/ Read out the density layers / velocity directions to draw some output
    *densR() = fluid_density(1)
    *densG() = fluid_density(2)
    *densB() = fluid_density(3)
    
    *velH() = fluid_velocity(#fluid_horizontal)
    *velV() = fluid_velocity(#fluid_vertical)
    
    CreateImage(1,#Fluid_Width,#Fluid_Height)
    StartDrawing(ImageOutput(1))
    
      For X=0 To #Fluid_Width-1
        For Y=0 To #Fluid_Height-1
        ; draw the density as boxes
        r  = *densR(X,Y) : G  =  *densG(X,Y) : b  =  *densB(X,Y)
        myMax(r) : myMax(G) : myMax(b) ;cut to high values
        
        ; check if wall
        If fluid_iswall(X,Y)
          Plot(X,Y,$FFFFFF)
        Else
          Plot(X,Y,RGB(r,G,b))
        EndIf
      Next
    Next
    StopDrawing()
    ResizeImage(1,800,600,1)
    
    StartDrawing(ScreenOutput())
      DrawImage(ImageID(1),0,0)
      For X = 1 To #Fluid_Width
        For Y = 1 To #Fluid_Height
          ; draw some velocity Vectors into the center of every box. We multiply them by a factor to get good visuals
          x1 = (X-1)*XSize + HXSize  : y1 = (Y-1)*YSize + HYSize
          x2 = x1+*velH(X,Y)*20 : y2 = y1+*velV(X,Y)*20
          LineXY(x1,y1,x2,y2,$FF3F3F)
        Next
      Next
      DrawingMode(#PB_2DDrawing_Transparent )
      DrawText(0,0,"Press following buttons: ",$FFFFFF,$0)
      DrawText(0,20,"1-3: add R/G/B density",$FFFFFF,$0)
      DrawText(0,40,"4: add wall",$FFFFFF,$0)
      DrawText(0,60,"5: clear",$FFFFFF,$0)
      DrawText(0,80,"arrow keys: Add velocity emitter in this direction",$FFFFFF,$0)
      DrawText(0,100,"L-Mouse: hold and move to 'create' velocity",$FFFFFF,$0)
      DrawText(0,120,"Disable Debugger!",$0000FF,$0)
      DrawingMode(#PB_2DDrawing_Default)
      Box(mouseX-1,mouseY-1,3,3,RGB(255,255,255))
    StopDrawing()
    FreeImage(1)
    
  FlipBuffers()
  
Until KeyboardPushed(#PB_Key_Escape)
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: fluid dynamics

Post by gnasen »

yes sorry, in the examples I just used the drawing commands straight forward, without any speed enhancements.
The calculation of the fluid itself is very fast, in the include fluid.pbi itself is at the bottom a little speed benchmark without any graphics.

you changed the value of fluid_density_reset(1) to fluid_density_reset(1.000001). That means that the whole density gets bigger every step. If you want to see "more" of the color, I would suggest to increase this values:

Code: Select all

If KeyboardPushed(#PB_Key_1)
    *densR(x,y) = 10000 ;maybe 10.000 instead of 5.000
EndIf
pb 5.11
pjay
Enthusiast
Enthusiast
Posts: 251
Joined: Thu Mar 30, 2006 11:14 am

Re: fluid dynamics

Post by pjay »

I've probably changed quite a few of the variable values, due to being a habitual tinkerer..... :)
User avatar
OldSkoolGamer
Enthusiast
Enthusiast
Posts: 150
Joined: Mon Dec 15, 2008 11:15 pm
Location: Nashville, TN
Contact:

Re: fluid dynamics

Post by OldSkoolGamer »

Like an early version of Powder Toy to me, but I like it.
PureLust
Enthusiast
Enthusiast
Posts: 477
Joined: Mon Apr 16, 2007 3:57 am
Location: Germany, NRW

Re: fluid dynamics

Post by PureLust »

Hi gnasen, ... very nice one, indeed. Image

remi_meier from the german forum has done a fluid dynamics example in 2006 as well, to which I added a simple GUI and improved the speed a bit.

It differs a bit to yours, because it's not a fluid simulation in a closed tank (like yours) - it's more like an "open sea" simulation.
Further you don't inject ink in his version, you just insert (or change) the "density" of the fluid.
Because of the Gravity, the more heavy fluid will sink which will generate fluctuation.
The display can be switched from showing the density to showing the flow velocity.

Because it seems to be a bit more performant (which could relay to the way it generates the graphical output), it may be of some interest to you: [Link]

Greetz, PL.
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: fluid dynamics

Post by gnasen »

Thx PureLust, I didnt know that there is existing another fluid dynamic simulation. It looks very good and interesting.

Youre right with your point, the example program is not that performant, because I just used the PB internal drawings on a "bruteforce way" without any speed improvements. Drawing velocity and density at the same time may be a little bit slow, too. Maybe I will improve that in future (or someone other has a look at it ;) ).
If I remember right, there is a speed test without any drawing on the bottom of the include commented.

Indeed you can switch the behaviour from "box" to "open" and create boundaries as you like them (like a ground, a cave...). Even gravity can be created, just modify the velocity with a vector pointing downside.

Im not sure about the "ink-thing" but maybe you (or me) overlooked something. He inserts stuff, which is shown as a color depending on the density. Im doing the same, but in the example I use 3 layers of density, each with its own color instead.

I think the whole topic is very interesting and if I have some time in future, I may rejoin this subject.
pb 5.11
Post Reply