Re: Fluid Dynamics
Verfasst: 25.06.2011 20:08
Hier dasselbe. Ohne OpenGL Subsystem 3-5 FPS, mit OpenGL 60-75 FPS. Der Sprite Code schafft bei mir ~60-70 FPS. PB 4.6b3, Win7 x64, GeForce GTX 260m
Gruß, Alex
Gruß, Alex
Code: Alles auswählen
; REALTIME FLUID (OpenGL)
; as described in "Real-Time Fluid Dynamics for Games" by Jos Stam
; press mousebutton & move mouse
EnableExplicit
#GRW = 500
#GRH = 500
#SIZE = 5
#GRX = (#GRW / #SIZE)
#GRY = (#GRH / #SIZE)
#PRECISION = 10
#FLOWSPEED = 0.1
#GL_TRIANGLE_STRIP = $0005
#GL_MODELVIEW = $1700
#GL_PROJECTION = $1701
#GL_SMOOTH = $1D01
Global Dim VelX1.f(#GRX , #GRY) , Dim VelX2.f(#GRX , #GRY)
Global Dim VelY1.f(#GRX , #GRY) , Dim VelY2.f(#GRX , #GRY)
Global Dim cRed1.f(#GRX , #GRY) , Dim cRed2.f(#GRX , #GRY)
Global Dim cGrn1.f(#GRX , #GRY) , Dim cGrn2.f(#GRX , #GRY)
Global Dim cBlu1.f(#GRX , #GRY) , Dim cBlu2.f(#GRX , #GRY)
Define glContext , hdc
Define lButton,xo,yo,x,y,sx,sy,color,fps,fpt
Procedure InitOpenGL(hdc)
Protected pfd.PIXELFORMATDESCRIPTOR
Protected glContext
Protected Dim glFloat.f(4)
pfd\nSize = SizeOf(PIXELFORMATDESCRIPTOR)
pfd\nVersion = 1
pfd\dwFlags = #PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER | #PFD_DRAW_TO_WINDOW
pfd\dwLayerMask = #PFD_MAIN_PLANE
pfd\iPixelType = #PFD_TYPE_RGBA
pfd\cColorBits = 16
pfd\cDepthBits = 16
SetPixelFormat_(hdc , ChoosePixelFormat_(hdc, pfd) , pfd)
glContext = wglCreateContext_(hdc)
If glContext
wglMakeCurrent_(hdc , glContext)
glMatrixMode_(#GL_PROJECTION)
glLoadIdentity_()
glMatrixMode_ (#GL_MODELVIEW)
glTranslatef_(-1.0, 1.0, -1.0)
glScalef_(2.0/(#GRX-1),-2.0/(#GRY-1),0.0)
glShadeModel_ (#GL_SMOOTH)
EndIf
ProcedureReturn glContext
EndProcedure
Procedure AddVelocity(x , y , vx.f , vy.f , radius)
Protected xa,ya,xx,yy
For ya = -radius To radius
For xa = -radius To radius
xx = x + xa
yy = y + ya
If xx > 0 And xx < #GRX - 1 And yy > 0 And yy < #GRY - 1
If (xa*xa+ya*ya) <= (radius * radius)
VelX1(xx , yy) + vx
VelY1(xx , yy) + vy
EndIf
EndIf
Next
Next
EndProcedure
Procedure AddColor(x , y , r.f , g.f , b.f , radius)
Protected xa,ya,xx,yy
For ya = -radius To radius
For xa = -radius To radius
xx = x + xa
yy = y + ya
If xx > 0 And xx < #GRX - 1 And yy > 0 And yy < #GRY - 1
If (xa*xa+ya*ya) <= (radius * radius)
cRed1(xx , yy) = r
cGrn1(xx , yy) = g
cBlu1(xx , yy) = b
EndIf
EndIf
Next
Next
EndProcedure
Procedure TestBounds(Array vx1.f(2) , Array vy1.f(2) , Array vx2.f(2) , Array vy2.f(2))
Protected x,y
For x = 1 To #GRX-2
vy1(x , 0 ) = -vy2(x , 1 )
vy1(x , #GRY - 1) = -vy2(x , #GRY - 2)
Next
For y = 1 To #GRY-2
vx1(0 , y) = -vx2(1 , y)
vx1(#GRX - 1 , y) = -vx2(#GRX - 2 , y)
Next
; vx(0 , 0) = 0.5 * (vx(1, 0) + vx(0, 1))
; vy(0 , 0) = 0.5 * (vy(1, 0) + vy(0, 1))
; vx(#GRX - 1 , 0) = 0.5 * (vx(#GRX - 2, 0) + vx(#GRX - 1, 1))
; vy(#GRX - 1 , 0) = 0.5 * (vy(#GRX - 2, 0) + vy(#GRX - 1, 1))
; vx(#GRX - 1 , #GRY - 1) = 0.5 * (vx(#GRX - 2, #GRY - 1) + vx(#GRX - 1, #GRY - 2))
; vy(#GRX - 1 , #GRY - 1) = 0.5 * (vy(#GRX - 2, #GRY - 1) + vy(#GRX - 1, #GRY - 2))
; vx(0 , #GRY - 1) = 0.5 * (vx(1, #GRY - 1) + vx(0, #GRY - 2))
; vy(0 , #GRY - 1) = 0.5 * (vy(1, #GRY - 1) + vy(0, #GRY - 2))
EndProcedure
Procedure Update()
Protected.l h = (#GRX * #GRY) , x,y,x0,y0,x1,y1,p
Protected.f hh = 1.0 / h , a
Protected.f speed = h * #FLOWSPEED
Protected.f xx , yy , s0 , s1 , t0 , t1
; Advect
For y = 0 To #GRY - 1
For x = 0 To #GRX - 1
xx = x - speed * VelX2(x , y)
yy = y - speed * VelY2(x , y)
If xx < 0 : xx = 0 : ElseIf xx > #GRX-1 : xx = #GRX-1 : EndIf
If yy < 0 : yy = 0 : ElseIf yy > #GRY-1 : yy = #GRY-1 : EndIf
x0 = Int(xx) : x1 = x0 + 1
y0 = Int(yy) : y1 = y0 + 1
s1 = xx - x0 : s0 = 1.0 - s1
t1 = yy - y0 : t0 = 1.0 - t1
VelX2(x , y) = s0 * (t0 * VelX1(x0 , y0) + t1 * VelX1(x0 , y1)) + s1 * (t0 * VelX1(x1 , y0) + t1 * VelX1(x1 , y1))
VelY2(x , y) = s0 * (t0 * VelY1(x0 , y0) + t1 * VelY1(x0 , y1)) + s1 * (t0 * VelY1(x1 , y0) + t1 * VelY1(x1 , y1))
cRed2(x , y) = s0 * (t0 * cRed1(x0 , y0) + t1 * cRed1(x0 , y1)) + s1 * (t0 * cRed1(x1 , y0) + t1 * cRed1(x1 , y1))
cGrn2(x , y) = s0 * (t0 * cGrn1(x0 , y0) + t1 * cGrn1(x0 , y1)) + s1 * (t0 * cGrn1(x1 , y0) + t1 * cGrn1(x1 , y1))
cBlu2(x , y) = s0 * (t0 * cBlu1(x0 , y0) + t1 * cBlu1(x0 , y1)) + s1 * (t0 * cBlu1(x1 , y0) + t1 * cBlu1(x1 , y1))
Next
Next
; Project
a = -0.5 * h
For y = 1 To #GRY - 2
For x = 1 To #GRX - 2
VelY1(x , y) = a * (VelX2(x + 1 , y) - VelX2(x - 1 , y) + VelY2(x , y + 1) - VelY2(x , y - 1))
VelX1(x , y) = 0
Next
Next
For p = 1 To #PRECISION
For y = 1 To #GRY - 2
For x = 1 To #GRX - 2
VelX1(x , y) = (VelY1(x , y) + VelX1(x - 1 , y) + VelX1(x + 1 , y) + VelX1(x , y - 1) + VelX1(x , y + 1)) * 0.25
Next
Next
Next
a = 0.5 * hh
For y = 1 To #GRY - 2
For x = 1 To #GRX - 2
VelX2(x , y) - (VelX1(x + 1 , y) - VelX1(x - 1 , y)) * hh
VelY2(x , y) - (Velx1(x , y + 1) - VelX1(x , y - 1)) * hh
Next
Next
; Diffuse
For y = 1 To #GRY - 2
For x = 1 To #GRX - 2
VelX1(x , y) = (VelX2(x , y) + VelX2(x - 1 , y) + VelX2(x + 1 , y) + VelX2(x , y - 1) + VelX2(x , y + 1)) * 0.2
VelY1(x , y) = (VelY2(x , y) + VelY2(x - 1 , y) + VelY2(x + 1 , y) + VelY2(x , y - 1) + VelY2(x , y + 1)) * 0.2
Next
Next
TestBounds(VelX1() , VelY1() , VelX2() , VelY2())
Swap cRed1(),cRed2()
Swap cGrn1(),cGrn2()
Swap cBlu1(),cBlu2()
EndProcedure
Procedure DrawMesh(hdc)
Protected x,y,x1,y1
For y = 0 To #GRY - 2
glBegin_(#GL_TRIANGLE_STRIP)
y1 = y + 1
For x = 0 To #GRX - 1
glColor3f_(cRed1(x ,y ),cGrn1(x ,y ),cBlu1(x ,y ))
glVertex3i_(x ,y , 0)
glColor3f_(cRed1(x ,y1),cGrn1(x ,y1),cBlu1(x ,y1))
glVertex3i_(x ,y1, 0)
Next
glEnd_()
Next
SwapBuffers_(hdc)
EndProcedure
If OpenWindow(0, 0, 0, #GRW, #GRH, "Fluid" , #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
hdc = GetDC_(WindowID(0))
glContext = InitOpenGL(hdc)
If glContext
Repeat
Select WindowEvent()
Case #PB_Event_CloseWindow
wglDeleteContext_(glContext)
End
Case #WM_LBUTTONDOWN : lButton = 1
color = RGB(Random(255) , Random(255) , Random(255))
Case #WM_LBUTTONUP : lButton = 0
Case #WM_MOUSEMOVE
x = WindowMouseX(0) / #SIZE
y = WindowMouseY(0) / #SIZE
sx = (x - xo)
sy = (y - yo)
xo=x
yo=y
If lButton
AddVelocity(x , y , sx * 0.001 , sy * 0.001 , 3)
EndIf
EndSelect
AddColor (#GRX/2 , #GRY-2 , 0.6,0.7,0.9 , 3)
AddVelocity (#GRX/2 , #GRY-2 , 0 , -0.002 , 3)
If lButton
AddColor (x , y , Red(color) / 255.0 ,Green(color) / 255.0 , Blue(color) / 255.0 , 3)
EndIf
Update()
DrawMesh(hdc)
fps + 1
If ElapsedMilliseconds() > fpt
SetWindowTitle(0,Str(fps) + " fps - press mousebutton & move mouse")
fps = 0
fpt = ElapsedMilliseconds() + 1000
EndIf
ForEver
Else
MessageRequester("Error" , "no OpenGL")
EndIf
EndIf
Code: Alles auswählen
; Program: Fluid Dynamics
; Author: (the great) remi_meier (1st changes by 'pphjs', final GUI improvements and speed-up by 'PureLust')
; Date: 25. February 2007 - last changes: 04.07.2011
; OS: Windows (should work on other OS as well)
; Demo: No
; German forum: http://www.purebasic.fr/german/viewtopic.php?t=9894&start=20
EnableExplicit
DisableDebugger
#N = 100 ; Anzahl der Gitterpunkte, die berechnet werden
#DSTEP = 1;5 ; Pixel per Gitterpunkt in der Darstellung
#Zoom = 5
#SIZE = (#N + 2) * (#N + 2)
#MouseSpeed = 5 ; Geschwindigkeit der Mausbewegung (je kleiner, desto schneller)
#Stream = 10 ; Stärke der Strömung unten rechts
#LineHeight1 = 20
#xGui = #N * #Zoom
#xPos1 = 10
#xPos2 = 25
Define GuiWidth = 230
Define YPos=278, LH=15, LS=7 ; Variablen für Gadget Anordnung
Define n
Global pause
Global plot.l = 0 ; 0 - zeichnet Dichtefeld, sonst Geschwindigkeitsfeld
Global dense.f=0.18, grav.f=0.31 ;dense - Diche des Anfangsfeldes und am Rand, grav - Gravitationskonstante
Global visc.f = 0.0001, dt.f = 0.01, diff.f = 0.00018 ; visc - (turbulente) Vikosität
Global xdense.f = 1/dense ; dt - Zeitschritt
Global Viscosity = 5 ; (Originalwert = 19) ; diff - (turbulente) Diffusionskonstante
Global DensityChange.f = 4.2
Global im.l, jm.l ; aktuelle Mouse-Position
Global StreamActive = #True
Global MouseCatched = #True
Structure FArray
f.f[0]
EndStructure
Macro IX(i, j)
(i) + (n + 2) * (j)
EndMacro
Declare set_bnd(n.l, b.l, *x.FArray)
Declare project(n.l, *u.FArray, *v.FArray, *p.FArray, *div.FArray)
Procedure add_source_gravity(n.l, *x.FArray, *s.FArray, *d.FArray, dt.f)
Define.l i, j
For i = 0 To n+1
For j = 0 To n+1
*x\f[IX(i, j)] + dt* (*s\f[IX(i, j)] - grav * (dense-*d\f[IX(i, j)])*xdense)
Next
Next
EndProcedure
Procedure add_source(n.l, *x.FArray, *s.FArray, dt.f)
Define.l i, Size = (n + 2) * (n + 2)
For i = 0 To Size - 1
*x\f[i] + dt * *s\f[i]
Next
EndProcedure
Procedure diffuse(n.l, b.l, *x.FArray, *x0.FArray, diff.f, dt.f)
Define.l i, j, k
Define.f a,xa
a = dt * diff * n * n
xa = 1 / (1.0 + 4.0 * a)
For k = 0 To Viscosity
For i = 1 To n
For j = 1 To n
*x\f[IX(i, j)] = (*x0\f[IX(i, j)] + a * (*x\f[IX(i-1, j)] + *x\f[IX(i+1, j)] + *x\f[IX(i, j-1)] + *x\f[IX(i, j+1)])) * xa
; *x\f[IX(i, j)] = (*x0\f[IX(i, j)] + a * (*x\f[IX(i-1, j)] + *x\f[IX(i+1, j)] + *x\f[IX(i, j-1)] + *x\f[IX(i, j+1)])) / (1.0 + 4.0 * a)
; *x\f[IX(i, j)] = *x0\f[IX(i, j)] + a * (*x0\f[IX(i-1, j)] + *x0\f[IX(i+1, j)] + *x0\f[IX(i, j-1)] + *x0\f[IX(i, j+1)] - 4 * *x0\f[IX(i, j)])
Next
Next
set_bnd(n, b, *x)
Next
EndProcedure
Procedure advect (n.l, b.l, *d.FArray, *d0.FArray, *u.FArray, *v.FArray, dt.f)
Define.l i, j, i0, j0, i1, j1
Define.f x, y, s0, t0, s1, t1, dt0
dt0 = dt * n
For i = 1 To n
For j = 1 To n
x = i - dt0 * *u\f[IX(i, j)]
y = j - dt0 * *v\f[IX(i, j)]
If (x < 0.5)
x = 0.5
ElseIf (x > n + 0.5)
x = n + 0.5
EndIf
i0 = Int(x)
i1 = i0 + 1
If (y < 0.5)
y = 0.5
ElseIf (y > n + 0.5)
y = n + 0.5
EndIf
j0 = Int(y)
j1 = j0 + 1
s1 = x - i0 : s0 = 1 - s1 : t1 = y - j0 : t0 = 1 - t1
*d\f[IX(i, j)] = s0 * (t0 * *d0\f[IX(i0, j0)] + t1 * *d0\f[IX(i0, j1)]) + s1 * (t0 * *d0\f[IX(i1, j0)] + t1 * *d0\f[IX(i1, j1)])
Next
Next
set_bnd(n, b, *d)
EndProcedure
Procedure dens_step(n.l, *x.FArray, *x0.FArray, *u.FArray, *v.FArray, diff.f, dt.f)
add_source(n, *x, *x0, dt)
diffuse(n, 0, *x0, *x, diff, dt )
advect(n, 0, *x, *x0, *u, *v, dt )
EndProcedure
Procedure vel_step(n.l, *u.FArray, *v.FArray, *u0.FArray, *v0.FArray, *d.FArray, visc.f, dt.f)
add_source(n, *u, *u0, dt) : add_source_gravity(n, *v, *v0, *d, dt); add_source(n, *v, *v0, dt)
diffuse(n, 1, *u0, *u, visc, dt)
diffuse(n, 2, *v0, *v, visc, dt)
project(n, *u0, *v0, *u, *v)
advect(n, 1, *u, *u0, *u0, *v0, dt) : advect(n, 2, *v, *v0, *u0, *v0, dt)
project(n, *u, *v, *u0, *v0)
EndProcedure
Procedure project(n.l, *u.FArray, *v.FArray, *p.FArray, *div.FArray)
Define.l i, j, k
Define.f h = 1.0 / n
Define.f xh = 1/h
Define.f hh = -0.5 * h
For i = 1 To n
For j = 1 To n
*div\f[IX(i, j)] = hh * (*u\f[IX(i+1, j)] - *u\f[IX(i-1, j)] + *v\f[IX(i, j+1)] - *v\f[IX(i, j-1)])
*p\f[IX(i, j)] = 0
Next
Next
set_bnd(n, 3, *div) : set_bnd(n, 3, *p)
For k = 0 To Viscosity
For i = 1 To n
For j = 1 To n
*p\f[IX(i, j)] = (*div\f[IX(i, j)] + *p\f[IX(i-1, j)] + *p\f[IX(i+1, j)] + *p\f[IX(i, j-1)] + *p\f[IX(i, j+1)]) * 0.25
Next
Next
set_bnd(n, 3, *p)
Next
For i = 1 To n
For j = 1 To n
*u\f[IX(i, j)] - (0.5 * (*p\f[IX(i+1, j)] - *p\f[IX(i-1, j)]) * xh)
*v\f[IX(i, j)] - (0.5 * (*p\f[IX(i, j+1)] - *p\f[IX(i, j-1)]) * xh)
Next
Next
set_bnd(n, 1, *u) : set_bnd(n, 2, *v)
EndProcedure
Procedure set_bnd(n.l, b.l, *x.FArray)
Define.l i
Select b
Case 0 ; Dichte Rand
For i = 0 To n+1
*x\f[IX(0, i)] = dense
*x\f[IX(n+1, i)] = dense
*x\f[IX(i, 0)] = dense
*x\f[IX(i, n+1)] = dense
Next
Case 1 ; Ost- bzw. Westrand, fester Rand u=0
For i = 0 To n+1
*x\f[IX(0, i)] = 0.0
*x\f[IX(n+1, i)] = 0.0
Next
Case 2 ; Nord- bzw. Suedrand, fester Rand v=0
For i = 0 To n+1
*x\f[IX(i, 0)] = 0.0
*x\f[IX(i, n+1)] = 0.0
Next
Case 3 ; Raender fuer die Naeherungsverfahren
For i = 0 To n+1
*x\f[IX(0, i)] = 0
*x\f[IX(n+1, i)] = 0
*x\f[IX(i, 0)] = 0
*x\f[IX(i, n+1)] = 0
Next
EndSelect
EndProcedure
;- End Simulation
Procedure.l color_gr( f1.d,f2.d)
Protected r.l, g.l, b.l,v.f
v=$500*Sqr(f1*f1+f2*f2)
g=$FF
b=$80
r = $FF -v
If r < 0 : g + r : r=0
If g < 0 : r - g : g=0
If g < $80 : b + g : EndIf
If g >= $80 : b +$FF-g : EndIf
If r < $80 : b + r : EndIf
If r >= $80
If r < $17F
b =$17F-r : r = $80
Else
r-$FF : b=0
If r>=$1FF:r=$FF:g=$FF:b=$FF :EndIf
If r>$FF :g=r-$FF:b=r-$FF:r=$FF:EndIf
EndIf
EndIf
EndIf
EndIf
ProcedureReturn RGB(r, g, b)
EndProcedure
Procedure draw_(n.l, *u.FArray, *v.FArray, im.l, jm.l)
Protected.l i, j , xi, xj
Protected.f um, vm
Protected.s info
If StartDrawing(ScreenOutput())
xi = 0
CompilerIf Subsystem("OpenGL")
Protected xn = (n-1) * #Zoom
For i = 0 To xn Step #Zoom
xi + 1
xj = 0
For j = 0 To xn Step #Zoom
xj + 1
Box(i,j,#Zoom,#Zoom,color_gr(*u\f[IX(xi, xj)],*v\f[IX(xi, xj)]))
Next
Next
If MouseCatched
Line(im*#Zoom-8,jm*#Zoom-3,11, 1,RGB(255,255,255))
Line(im*#Zoom-3,jm*#Zoom-8, 1,11,RGB(255,255,255))
EndIf
CompilerElse
Protected xn = (n-1) * #DSTEP
For i = 0 To xn Step #DSTEP
xi + 1
xj = 0
For j = 0 To xn Step #DSTEP
xj + 1
Plot(i,j,color_gr(*u\f[IX(xi, xj)],*v\f[IX(xi, xj)]))
Next
Next
If MouseCatched
Line(im-2,jm ,5,1,RGB(255,255,255))
Line(im ,jm-2,1,5,RGB(255,255,255))
EndIf
CompilerEndIf
StopDrawing()
EndIf
FlipBuffers()
If plot = 0
SetGadgetText(1,"Akt.Density : "+StrF(*u\f[IX(im, jm)],3)+" kg/m³")
Else
um=*u\f[IX(im, jm)]
vm=*v\f[IX(im, jm)]
SetGadgetText(2,"u = "+StrF(um,3)+" m/s")
SetGadgetText(3,"v = "+StrF(vm,3)+" m/s")
SetGadgetText(4,"Sqrt(u²+v²) = "+StrF(Sqr(um*um+vm*vm),3)+" m/s")
EndIf
SetGadgetText(5,"RGB Color Value = $"+Hex(color_gr(*u\f[IX(im, jm)],*v\f[IX(im, jm)])))
EndProcedure
Procedure set_dens (n.l, *d.FArray)
Define.l i, Size = (n + 2) * (n + 2)
For i = 0 To Size - 1
*d\f[i]= dense
Next
EndProcedure
Procedure set_datas(n.l, *dens0.FArray, *u0.FArray, *v0.FArray, im.l, jm.l)
Define.l z, Size = (n + 2) * (n + 2)
fillmemory_(*dens0, (n + 2) * (n + 2) * SizeOf(Float), 0)
If MouseButton(1)
SetGadgetColor(10,#PB_Gadget_FrontColor,$ff)
If KeyboardPushed(#PB_Key_LeftShift) Or KeyboardPushed(#PB_Key_RightShift)
*dens0\f[IX(im+z, jm)] = - DensityChange / dt ;Dichteaenderung pro Zeitschritt
Else
*dens0\f[IX(im+z, jm)] = DensityChange / dt ;Dichteaenderung pro Zeitschritt
EndIf
Else
SetGadgetColor(10,#PB_Gadget_FrontColor,$00)
EndIf
If MouseButton(2)
SetGadgetColor(11,#PB_Gadget_FrontColor,$ff)
If KeyboardPushed(#PB_Key_LeftShift) Or KeyboardPushed(#PB_Key_RightShift)
*u0\f[IX(im+z, jm)] = -10/dt ;Geschwindigkeitsaenderung pro Zeitschritt
*v0\f[IX(im+z, jm)] = -8 /dt ;Geschwindigkeitsaenderung pro Zeitschritt
Else
*u0\f[IX(im+z, jm)] = 10/dt ;Geschwindigkeitsaenderung pro Zeitschritt
*v0\f[IX(im+z, jm)] = 8 /dt ;Geschwindigkeitsaenderung pro Zeitschritt
EndIf
Else
SetGadgetColor(11,#PB_Gadget_FrontColor,$00)
EndIf
If KeyboardPushed(#PB_Key_LeftShift) Or KeyboardPushed(#PB_Key_RightShift)
SetGadgetColor(12,#PB_Gadget_FrontColor,$ff00)
Else
SetGadgetColor(12,#PB_Gadget_FrontColor,$00)
EndIf
If StreamActive
*u0\f[IX(90, 90)] = - (#Stream /dt) ; hier ist ein Quirl eingebaut, rausnehmen
*v0\f[IX(90, 90)] = - (#Stream /dt)
EndIf
EndProcedure
Procedure main()
Protected *u.FArray = AllocateMemory(#SIZE * SizeOf(Float))
Protected *v.FArray = AllocateMemory(#SIZE * SizeOf(Float))
Protected *u_prev.FArray = AllocateMemory(#SIZE * SizeOf(Float))
Protected *v_prev.FArray = AllocateMemory(#SIZE * SizeOf(Float))
Protected *dens.FArray = AllocateMemory(#SIZE * SizeOf(Float))
Protected *dens_prev.FArray = AllocateMemory(#SIZE * SizeOf(Float))
Protected Drawstart.l, FrameCounter.l, KeyPressed.l, Event.l, n
Static imf.f, jmf.f, Quit.l, oldgrav.f
Protected LastMouseX, LastMouseY, LastPressed.l
set_dens(#N, *dens) ; Dichtefeld fuer den Anfang belegen
Repeat
If FrameCounter = 30 : Drawstart = ElapsedMilliseconds() : FrameCounter = 0 : EndIf
FrameCounter + 1
ExamineMouse()
imf = imf + MouseDeltaX() / #MouseSpeed
jmf = jmf + MouseDeltaY() / #MouseSpeed
If imf > #N : imf = #N : EndIf
If imf < 1 : imf = 1 : EndIf ; 0 ist Randpunkt, darf nicht gesetzt werden
If jmf > #N : jmf = #N : EndIf
If jmf < 1 : jmf = 1 : EndIf
im = imf
jm = jmf
If Not pause Or MouseButton(1) | MouseButton(2)
ExamineKeyboard()
set_datas(#N, *dens_prev, *u_prev, *v_prev, im, jm)
If Not pause
vel_step(#N, *u, *v, *u_prev, *v_prev, *dens, visc, dt)
dens_step(#N, *dens, *dens_prev, *u, *v, diff, dt)
Else
vel_step(#N, *u, *v, *u_prev, *v_prev, *dens, visc/10, dt/10)
dens_step(#N, *dens, *dens_prev, *u, *v, diff*10, dt/10)
EndIf
EndIf
If plot = 0
draw_(#N, *dens,*dens, im, jm)
Else
draw_(#N, *u,*v, im, jm)
EndIf
If FrameCounter = 30 : SetWindowTitle(0,"Fluid Dynamics ("+StrF(30000/(ElapsedMilliseconds()-Drawstart),1)+"fps)") : EndIf
If MouseCatched
ExamineKeyboard()
If KeyPressed < ElapsedMilliseconds()
If KeyboardPushed(#PB_Key_Comma)
oldgrav = grav
If KeyboardPushed(#PB_Key_LeftControl) Or KeyboardPushed(#PB_Key_RightControl)
grav + 0.01
ElseIf KeyboardPushed(#PB_Key_LeftShift) Or KeyboardPushed(#PB_Key_RightShift)
grav + 0.1
Else
grav + 1
EndIf
If grav > 20 : grav = oldgrav : EndIf
SetGadgetText(9,"(G)ravity : "+StrF(grav,2)+" m/sec²")
KeyPressed = ElapsedMilliseconds()+150
ElseIf KeyboardPushed(#PB_Key_Period)
oldgrav = grav
If KeyboardPushed(#PB_Key_LeftControl) Or KeyboardPushed(#PB_Key_RightControl)
grav - 0.01
ElseIf KeyboardPushed(#PB_Key_LeftShift) Or KeyboardPushed(#PB_Key_RightShift)
grav - 0.1
Else
grav - 1
EndIf
If grav < -20 : grav = oldgrav : EndIf
SetGadgetText(9,"(G)ravity : "+StrF(grav,2)+" m/sec²")
KeyPressed = ElapsedMilliseconds()+150
ElseIf KeyboardPushed(#PB_Key_Add)
If Viscosity < 30 : Viscosity +1 : EndIf
SetGadgetText(6,"Viscositylevel : "+Str(Viscosity))
KeyPressed = ElapsedMilliseconds()+150
ElseIf KeyboardPushed(#PB_Key_Subtract)
If Viscosity > 1 : Viscosity -1 : EndIf
SetGadgetText(6,"Viscositylevel : "+Str(Viscosity))
KeyPressed = ElapsedMilliseconds()+150
ElseIf KeyboardPushed(#PB_Key_Down)
If DensityChange < 4.9 : DensityChange + 0.1 : EndIf
SetGadgetText(7,"Injected Density : "+StrF(DensityChange,1)+" kg/m³")
KeyPressed = ElapsedMilliseconds()+60
ElseIf KeyboardPushed(#PB_Key_Up)
If DensityChange > - 4.9 : DensityChange - 0.1 : EndIf
SetGadgetText(7,"Injected Density : "+StrF(DensityChange,1)+" kg/m³")
KeyPressed = ElapsedMilliseconds()+60
ElseIf KeyboardPushed(#PB_Key_D)
plot = 1-plot
DisableGadget(1,plot)
DisableGadget(2,1-plot)
DisableGadget(3,1-plot)
DisableGadget(4,1-plot)
If plot = 0
SetGadgetText(8,"Act. (D)isplay => Density Field")
Else
SetGadgetText(8,"Act. (D)isplay => Flow Velocity")
EndIf
KeyPressed = ElapsedMilliseconds()+150
ElseIf KeyboardPushed(#PB_Key_S)
StreamActive = 1-StreamActive
SetGadgetColor(17, #PB_Gadget_FrontColor, StreamActive * $ff00)
KeyPressed = ElapsedMilliseconds()+150
ElseIf KeyboardPushed(#PB_Key_C)
FillMemory(*u, #SIZE * SizeOf(Float))
FillMemory(*v, #SIZE * SizeOf(Float))
FillMemory(*u_prev, #SIZE * SizeOf(Float))
FillMemory(*v_prev, #SIZE * SizeOf(Float))
FillMemory(*dens, #SIZE * SizeOf(Float))
FillMemory(*dens_prev, #SIZE * SizeOf(Float))
set_dens(#N, *dens)
KeyPressed = ElapsedMilliseconds()+150
ElseIf KeyboardPushed(#PB_Key_G)
If grav = 9.81
grav = 0
Else
grav = 9.81
EndIf
SetGadgetText(9,"Gravity : "+StrF(grav,2)+" m/sec²")
KeyPressed = ElapsedMilliseconds()+150
ElseIf KeyboardPushed(#PB_Key_Space)
pause = 1-pause
If ElapsedMilliseconds() - LastPressed > 1000
KeyPressed = ElapsedMilliseconds()+500
Else
If pause > 0
KeyPressed = ElapsedMilliseconds()+100
Else
KeyPressed = ElapsedMilliseconds()+20
EndIf
EndIf
LastPressed = ElapsedMilliseconds()
ElseIf KeyboardPushed(#PB_Key_Escape)
ReleaseMouse(#True)
HideGadget(18, #True)
HideGadget(25, #False)
MouseCatched = #False
For n = 10 To 23
DisableGadget(n, #True)
Next
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
If LastMouseX Or LastMouseY
SetCursorPos_(LastMouseX, LastMouseY)
EndIf
CompilerEndIf
EndIf
ElseIf Not KeyboardPushed(#PB_Key_All)
KeyPressed = 0
EndIf
EndIf
Repeat
Event = WindowEvent()
If Event = #PB_Event_CloseWindow
Quit = #True
ElseIf Event = #PB_Event_Gadget
ReleaseMouse(#False)
HideGadget(18, #False)
HideGadget(25, #True)
MouseCatched = #True
LastMouseX = DesktopMouseX()
LastMouseY = DesktopMouseY()
For n = 10 To 23
DisableGadget(n, #False)
Next
EndIf
Until Not Event
Until Quit
EndProcedure
InitSprite()
InitMouse()
InitKeyboard()
OpenWindow(0, 100, 100, #xGui+GuiWidth, #N * #Zoom, "Fluid Dynamics", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(1,0,0,10,10,"Dummy")
If StartDrawing(WindowOutput(0))
DrawingFont(GetGadgetFont(1))
GuiWidth = TextWidth("+ <Shift> = Invert Density && Twirl") + 2 * #xPos2
ResizeWindow(0, #PB_Ignore, #PB_Ignore, #xGui+GuiWidth, #PB_Ignore)
StopDrawing()
EndIf
Frame3DGadget(0,#xGui+#xPos1,10,GuiWidth-#xPos1*2,20+#LineHeight1*9,"Actual Values")
TextGadget(1,#xGui+#xPos2,28 + #LineHeight1 * 0, GuiWidth-#xPos2*2, 18,"Dichte : 0.000 kg/m³")
TextGadget(2,#xGui+#xPos2,28 + #LineHeight1 * 1, GuiWidth-#xPos2*2, 18,"u = 0.000 m/s")
TextGadget(3,#xGui+#xPos2,28 + #LineHeight1 * 2, GuiWidth-#xPos2*2, 18,"v = 0.000 m/s")
TextGadget(4,#xGui+#xPos2,28 + #LineHeight1 * 3, GuiWidth-#xPos2*2, 18,"Sqrt(u²+v²) = 0.000 m/s")
TextGadget(5,#xGui+#xPos2,28 + #LineHeight1 * 4, GuiWidth-#xPos2*2, 18,"")
TextGadget(9,#xGui+#xPos2,28 + #LineHeight1 * 5, GuiWidth-#xPos2*2, 18,"(G)ravity : "+StrF(grav,2)+" m/sec²")
TextGadget(6,#xGui+#xPos2,28 + #LineHeight1 * 6, GuiWidth-#xPos2*2, 18,"Viscositylevel : "+Str(Viscosity))
TextGadget(7,#xGui+#xPos2,28 + #LineHeight1 * 7, GuiWidth-#xPos2*2, 18,"Injected Density : "+StrF(DensityChange,1)+" kg/m³")
TextGadget(8,#xGui+#xPos2,28 + #LineHeight1 * 8, GuiWidth-#xPos2*2, 18,"Act. (D)isplay => Density Field")
DisableGadget(2,1)
DisableGadget(3,1)
DisableGadget(4,1)
YPos = 55 + #LineHeight1*9
Frame3DGadget(26,#xGui+#xPos1,YPos-20,GuiWidth-#xPos1*2,#N * #Zoom - YPos + 13,"Control Keys")
TextGadget(10,#xGui+#xPos2, YPos+ 0*LH+0*LS ,GuiWidth-#xPos2*2, 18, "Left-MB = Inject Density")
TextGadget(11,#xGui+#xPos2, YPos+ 1*LH+0*LS ,GuiWidth-#xPos2*2, 18, "Right-MB = Add Twirl")
TextGadget(12,#xGui+#xPos2, YPos+ 2*LH+0*LS ,GuiWidth-#xPos2*2, 18, "+ <Shift> = Invert Density && Twirl")
TextGadget(13,#xGui+#xPos2, YPos+ 3*LH+1*LS ,GuiWidth-#xPos2*2, 16, "< . | , > = Gravity +/- 1.00",#PB_Text_Right)
TextGadget(14,#xGui+#xPos2, YPos+ 4*LH+1*LS ,GuiWidth-#xPos2*2, 16, "<Shift> < . | , > = Gravity +/- 0.10",#PB_Text_Right)
TextGadget(15,#xGui+#xPos2, YPos+ 5*LH+1*LS ,GuiWidth-#xPos2*2, 16, "<Ctrl> < . | , > = Gravity +/- 0.01",#PB_Text_Right)
TextGadget(16,#xGui+#xPos2, YPos+ 6*LH+2*LS ,GuiWidth-#xPos2*2, 16, "<+|-> = Viscosity +/- 1.00",#PB_Text_Right)
TextGadget(20,#xGui+#xPos2, YPos+ 7*LH+2*LS ,GuiWidth-#xPos2*2, 16, "<Shift> <+|-> = Viscosity +/- 0.10",#PB_Text_Right)
TextGadget(21,#xGui+#xPos2, YPos+ 8*LH+3*LS ,GuiWidth-#xPos2*2, 16, "<Csr Up> = Density + 0.10",#PB_Text_Right)
TextGadget(19,#xGui+#xPos2, YPos+ 9*LH+3*LS ,GuiWidth-#xPos2*2, 16, "<Csr Dn> = Density - 0.10",#PB_Text_Right)
TextGadget(17,#xGui+#xPos2, YPos+10*LH+4*LS ,GuiWidth-#xPos2*2, 18, "<S> = bottom right Stream on/off",#PB_Text_Center)
TextGadget(22,#xGui+#xPos2, YPos+11*LH+5*LS-4 ,GuiWidth-#xPos2*2, 18, "<D> = Change Display type",#PB_Text_Center)
TextGadget(23,#xGui+#xPos2, YPos+12*LH+6*LS-8 ,GuiWidth-#xPos2*2, 18, "<Space> = Pause / Stepmotion",#PB_Text_Center)
TextGadget(18,#xGui+#xPos2, YPos+13*LH+7*LS-12 ,GuiWidth-#xPos2*2, 18, "<ESC> = Release Mouse && Kbd",#PB_Text_Center)
ButtonGadget(25,#xGui+#xPos2,YPos+13*LH+7*LS-3-12, GuiWidth-#xPos2*2,22,"Grab Mouse && Keyboard")
HideGadget(25, #True)
SetGadgetColor(17, #PB_Gadget_FrontColor, StreamActive * $ff00)
CompilerIf Subsystem("OpenGL")
OpenWindowedScreen(WindowID(0), 0, 0, #N * #Zoom, #N * #Zoom, #False, 0, 0, #PB_Screen_NoSynchronization)
CompilerElse
OpenWindowedScreen(WindowID(0), 0, 0, #N * #DSTEP, #N * #DSTEP, #True, GuiWidth, 0, #PB_Screen_NoSynchronization)
CompilerEndIf
While WindowEvent() : Wend
main()
CloseScreen()
CloseWindow(0)
End
Code: Alles auswählen
If StartDrawing(ScreenOutput())
xi = 0
For i = 0 To xn Step #DSTEP
xi + 1
xj = 0
For j = 0 To xn Step #DSTEP
xj + 1
;- Draw Boxes instead of a sprite
Box(i,j,#DSTEP,#DSTEP,color_gr(*u\f[IX(xi, xj)],*v\f[IX(xi, xj)]))
Next
Next
;display cross-hair at Mouse position
;- Xor the Cursor
DrawingMode(#PB_2DDrawing_XOr)
Line(im*#DSTEP-#DSTEP/2-1,jm*#DSTEP-2*#DSTEP-1,1,3.5*#DSTEP,$ffffff)
Line(im*#DSTEP-2*#DSTEP-1,jm*#DSTEP-#DSTEP/2-1,3.5*#DSTEP,1,$ffffff)
StopDrawing()
EndIf
FlipBuffers()
Super ... vielen Dank für's Testen und das Feedback.jamirokwai hat geschrieben:... das Teil läuft super unter Mac OS X 10.6.8, PB 4.6b3 und einem C2D 2.3 GHz mit 4GB.