Donc l'utilisateur "pjay" dans le forum anglais de Purebasic a réécrit mes codes à sa manière maintenant il marche ! Ouf Nous sommes arrivés
Code : Tout sélectionner
; fluid dynamics (flame) - PB conversion of https://github.com/983/Fluid-Simulation - Phil James 2023
EnableExplicit
CompilerIf #PB_Compiler_OS=#PB_OS_Linux
Structure point
x.i : y.i
EndStructure
CompilerEndIf
Structure vec2f
x.f : y.f
EndStructure
;#nx = 256 : #ny = 256 : #Upscale = 4 ; ~7ms on 5800h
;#nx = 160 : #ny = 120 : #Upscale = 8 ; ~2ms on 5800h
;#nx = 320 : #ny = 160 : #Upscale = 6 ; ~5ms on 5800h
;#nx = 512 : #ny = 256 : #Upscale = 4 ; ~12ms on 5800h
#nx = 320 : #ny = 400 : #Upscale = 2 ; ~12ms on 5800h
#nx1 = #nx - 1 : #ny1 = #ny - 1 : #nx2 = #nx - 2 : #ny2 = #ny - 2
Global dt.f = 0.02, iterations = 5, vorticity.f = 8.0, mouse.point, lmb, w.i = #nx * #Upscale, h = #ny * #Upscale, texture
Global v1size = #nx * #ny * SizeOf(float), v2size = v1size * 2, onframe
Global Dim old_velocity.vec2f(#ny1,#nx1), Dim new_velocity.vec2f(#ny1,#nx1)
Global Dim old_density.f(#ny1, #nx1), Dim new_density.f(#ny1, #nx1)
Global Dim pixels.l(#ny1,#nx1)
Macro LengthM(x,y) : Sqr((x*x) + (y*y)) : EndMacro
Macro LerpM(a, b, t) : ( a + t * (b - a) ) : EndMacro
Macro Log2M(v) : (Log(v) / 0.6931471805599453094) : EndMacro ; not sure if this is correct Log2...
Macro RandomFloatM(a, b) : LerpM(a, b, Random(1000000) / 1000000.0) : EndMacro
Procedure Init()
Protected x, y
For y = 0 To #ny1 : For x = 0 To #nx1
old_density(y,x) = 0.0 : old_velocity(y,x)\x = 0 : old_velocity(y,x)\y = 0
Next : Next
OpenWindow(0,0,0,w,h,"Fluid-Simulation (Flame)",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
OpenGLGadget(0,0,0,w,h,#PB_OpenGL_NoFlipSynchronization)
glOrtho_(0,1,1,0,0,1)
glEnable_(#GL_TEXTURE_2D);
glGenTextures_(1, @texture);
glBindTexture_(#GL_TEXTURE_2D, texture);
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR);
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR);
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_REPEAT) ;
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_REPEAT) ;
glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGBA, #nx, #ny, 0, #GL_RGBA, #GL_UNSIGNED_BYTE, #Null);
EndProcedure
Procedure.f interpolate(Array grid.f(2), *p.vec2f, *d.float)
Protected ix = Round(*p\x,#PB_Round_Down), iy = Round(*p\y,#PB_Round_Down), ux.f = *p\x - ix, uy.f = *p\y - iy
*d\f = LerpM(LerpM(grid(iy,ix),grid(iy,ix + 1), ux),LerpM(grid(iy+1,ix),grid(iy+1,ix+1), ux), uy)
EndProcedure
Procedure.f interpolateVec2(Array grid.vec2f(2), *p.vec2f, *d.vec2f)
Protected ix = Round(*p\x,#PB_Round_Down), iy = Round(*p\y,#PB_Round_Down), ux.f = *p\x - ix, uy.f = *p\y - iy
*d\x = LerpM(LerpM(grid(iy,ix)\x,grid(iy,ix+1)\x, ux), LerpM(grid(iy+1,ix)\x,grid(iy+1,ix+1)\x, ux), uy)
*d\y = LerpM(LerpM(grid(iy,ix)\y,grid(iy,ix+1)\y, ux), LerpM(grid(iy+1,ix)\y,grid(iy+1,ix+1)\y, ux), uy)
EndProcedure
Procedure advect_density()
Protected pos.vec2f, x, y
For y = 1 To #ny2 : For x = 1 To #nx2
pos\x = x - dt * old_velocity(y,x)\x
pos\y = y - dt * old_velocity(y,x)\y
If pos\y < 1 : pos\y = 1 : ElseIf pos\y > #ny2 : pos\y = #ny2 : EndIf
If pos\x < 1 : pos\x = 1 : ElseIf pos\x > #nx2 : pos\x = #nx2 : EndIf
interpolate(old_density(), @pos, @new_density(y,x));
Next : Next
CopyMemory(@new_density(),@old_density(),v1size)
EndProcedure
Procedure advect_velocity()
Protected pos.vec2f, x, y
For y = 1 To #ny2 : For x = 1 To #nx2
pos\x = x - dt * old_velocity(y,x)\x;
pos\y = y - dt * old_velocity(y,x)\y;
If pos\y < 1 : pos\y = 1 : ElseIf pos\y > #ny2 : pos\y = #ny2 : EndIf
If pos\x < 1 : pos\x = 1 : ElseIf pos\x > #nx2 : pos\x = #nx2 : EndIf
interpolateVec2(old_velocity(), @pos,@new_velocity(y,x))
Next : Next
CopyMemory(@new_velocity(),@old_velocity(),v2size)
EndProcedure
Procedure diffuse_density()
Protected pos.vec2f, x, y, diffusion.f = dt * 100.01, sum.f
For y = 1 To #ny2 : For x = 1 To #nx2
sum = diffusion * (old_density(y, x - 1) + old_density(y, x + 1) + old_density(y - 1, x) + old_density(y + 1, x)) + old_density(y,x);
new_density(y, x) = 1.0 / (1.0 + 4.0 * diffusion) * sum
Next : Next
CopyMemory(@new_density(),@old_density(),v1size)
EndProcedure
Procedure diffuse_velocity()
Protected viscosity = dt*0.000001, x, y, sum.vec2f, gotnan.a = #False
For y = 1 To #ny2 : For x = 1 To #nx2
sum\x = viscosity * (old_velocity(y, x - 1)\x + old_velocity(y, x + 1)\x + old_velocity(y - 1, x)\x + old_velocity(y + 1, x)\x) + old_velocity(y, x)\x
sum\y = viscosity * (old_velocity(y, x - 1)\y + old_velocity(y, x + 1)\y + old_velocity(y - 1, x)\y + old_velocity(y + 1, x)\y) + old_velocity(y, x)\y
new_velocity(y,x)\x = 1.0 / (1.0 + 4.0 * viscosity) * sum\x
new_velocity(y,x)\y = 1.0 / (1.0 + 4.0 * viscosity) * sum\y
Next : Next
CopyMemory(@new_velocity(),@old_velocity(),v2size)
EndProcedure
Procedure project_velocity()
Protected x, y, dx.f, dy.f, k, sum.f
Static Dim p.f(#ny,#nx), Dim p2.f(#ny,#nx), Dim div.f(#ny,#nx)
For y = 1 To #ny2 : For x = 1 To #nx2
dx = old_velocity(y , x + 1)\x - old_velocity(y ,x - 1)\x
dy = old_velocity(y + 1, x )\y - old_velocity(y - 1,x )\y
div(y,x) = dx + dy : p(y,x) = 0.0
Next : Next
For k = 1 To iterations
For y = 1 To #ny2 : For x = 1 To #nx2
sum = -div(y,x) + p(y ,x + 1) + p(y ,x - 1) + p(y + 1,x) + p(y - 1,x)
p2(y,x) = 0.25 * sum
Next : Next
CopyMemory(@p2(),@p(),v1size)
Next
For y = 1 To #ny2 : For x = 1 To #nx2
old_velocity(y,x)\x - (0.5 * (p(y ,x + 1) - p(y , x - 1)))
old_velocity(y,x)\y - (0.5 * (p(y + 1,x ) - p(y - 1, x )))
Next : Next
EndProcedure
Procedure.f curl(y,x)
ProcedureReturn old_velocity(y + 1,x)\x - old_velocity(y - 1,x)\x + old_velocity(y,x - 1)\y - old_velocity(y, x + 1)\y;
EndProcedure
Procedure vorticity_confinement()
Protected direction.vec2f, length.f, x, y;
Static Dim abs_curl.f(#ny1,#nx1)
For y = 1 To #ny2 : For x = 1 To #nx2
abs_curl(y,x) = Abs(curl(y,x));
Next : Next
For y = 1 To #ny2 : For x = 1 To #nx2
direction\x = abs_curl(y - 1, x ) - abs_curl(y + 1, x );
direction\y = abs_curl(y , x + 1) - abs_curl(y , x - 1);
length = lengthM(direction\x,direction\y)
direction\x = vorticity / (length + 1e-5) * direction\x;
direction\y = vorticity / (length + 1e-5) * direction\y;
new_velocity(y,x)\x = old_velocity(y,x)\x + dt * curl(y,x) * direction\x;
new_velocity(y,x)\y = old_velocity(y,x)\y + dt * curl(y,x) * direction\y;
Next : Next
CopyMemory(@new_velocity(),@old_velocity(),v2size)
EndProcedure
Procedure.f Clamp(v.f,Low.f = 0.0, High.f = 1.0)
If v < Low : ProcedureReturn Low : ElseIf v > High : ProcedureReturn High : EndIf
ProcedureReturn v
EndProcedure
Procedure.f SmoothStep(Low.f, High.f, v.f)
V = Clamp((v - low) / (high - low));
ProcedureReturn v * v * (3.0 - 2.0 * v);
EndProcedure
Procedure add_density(px, py, r = 10, value.f = 0.5)
Protected x, y, u.f, rf.f = r, x2, y2
For y = -r To r : For x = -r To r
y2 = py + y : x2 = px + x
If x2 < 0 : x2 = 0 : ElseIf x2 > #nx1 : x2 = #nx1 : EndIf
If y2 < 0 : y2 = 0 : ElseIf y2 > #ny1 : y2 = #ny1 : EndIf
u = SmoothStep(rf, 0.0, Sqr(x*x + y*y));
old_density(y2, x2) + u * value
Next : Next
EndProcedure
Procedure fluid_simulation_step()
Protected x,y, r.f = 10.0
For y = 0 To #ny1 : For x = 0 To #nx1
old_velocity(y,x)\x + RandomFloatM(-r, r) : old_velocity(y,x)\y + RandomFloatM(-r, r);
Next : Next
;// dense regions rise up
For y = 0 To #ny1 : For x = 0 To #nx1
old_velocity(y,x)\y + (old_density(y,x) * 20.0 - 5.0) * dt;
Next : Next
;// fast movement is dampened
For y = 0 To #ny1 : For x = 0 To #nx1
old_velocity(y,x)\x * 0.999 : old_velocity(y,x)\y * 0.999;
Next : Next
;// fade away
For y = 0 To #ny1 : For x = 0 To #nx1
old_density(y,x) * 0.99;
Next : Next
add_density(#nx*0.25, #ny*0.1, 10,0.5);
add_density(#nx*0.75, #ny*0.1, 10,0.5);
If mouse\x > 0 And mouse\y > 0 And mouse\x < #nx And mouse\y < #ny1 : add_density(Mouse\x, #ny - Mouse\y, #nx * 0.025,0.5) : EndIf
vorticity_confinement()
advect_velocity()
project_velocity()
diffuse_velocity()
diffuse_density();
advect_density()
;/ wipe out borders as prevents crashes
For y = 0 To #ny1
old_density(y,0) = 0.0 : old_velocity(y,0)\x = 0 : old_velocity(y,0)\y = 0
old_density(y,1) = 0.0 : old_velocity(y,1)\x = 0 : old_velocity(y,1)\y = 0
old_density(y,#nx1) = 0.0 : old_velocity(y,#nx1)\x = 0 : old_velocity(y,#nx1)\y = 0
old_density(y,#nx2) = 0.0 : old_velocity(y,#nx2)\x = 0 : old_velocity(y,#nx2)\y = 0
Next
For x = 0 To #nx1
old_density(0,x) = 0.0 : old_velocity(0,x)\x = 0 : old_velocity(0,x)\y = 0
old_density(#ny1,x) = 0.0 : old_velocity(#ny1,x)\x = 0 : old_velocity(#ny1,x)\y = 0
old_density(1,x) = 0.0 : old_velocity(1,x)\x = 0 : old_velocity(1,x)\y = 0
old_density(#ny2,x) = 0.0 : old_velocity(#ny2,x)\x = 0 : old_velocity(#ny2,x)\y = 0
Next
EndProcedure
Procedure.l RGBAgl(r.f, g.f, b.f, a.f)
r = clamp(r * 255, 0, 255) : g = clamp(g * 255, 0, 255) : b = clamp(b * 255, 0, 255) : a = clamp(a * 255, 0, 255)
ProcedureReturn (Int(a) << 24) | (Int(b) << 16) | (Int(g) << 8) | Int(r);
EndProcedure
Procedure Render()
;// density field To pixels
Protected x, y, f.f, f3.f, r.f, g.f, b.f
For y = 0 To #ny1 : For x = 0 To #nx1
f = old_density(y,x);
f = log2m( f * 0.25 + 1.0);
f3 = f*f*f
r = 1.5 * f : g = 1.5 * f3 : b = (f3 *f3)
pixels(y,x) = RGBAgl(r, g, b, 1.0);
Next : Next
;// upload pixels() array To texture
glTexSubImage2D_(#GL_TEXTURE_2D, 0, 0, 0, #nx, #ny, #GL_RGBA, #GL_UNSIGNED_BYTE, @pixels());
;// draw texture
glBegin_(#GL_QUADS);
glTexCoord2f_(0.0, 1.0): glVertex2f_(0 , 0)
glTexCoord2f_(1.0, 1.0): glVertex2f_(1.0, 0)
glTexCoord2f_(1.0, 0.0): glVertex2f_(1.0, 1.0)
glTexCoord2f_(0.0, 0.0): glVertex2f_(0 , 1.0)
glEnd_()
SetGadgetAttribute(0,#PB_OpenGL_FlipBuffers,#True)
EndProcedure
Init()
Define Event, Exit, time.i
Repeat
Repeat
Event = WindowEvent()
Select Event
Case #PB_Event_CloseWindow : Exit = #True
Case #PB_Event_Gadget
Select EventType()
Case #PB_EventType_MouseMove
Mouse\x = (GetGadgetAttribute(0,#PB_OpenGL_MouseX) / (w / #nx)) / DesktopResolutionX()
Mouse\y = (GetGadgetAttribute(0,#PB_OpenGL_MouseY) / (h / #ny)) / DesktopResolutionY()
Case #PB_EventType_LeftButtonDown
LMB = #True
add_density(Mouse\x, #ny - Mouse\y, #nx * 0.2,8.0); burst
Case #PB_EventType_LeftButtonUp
LMB = #False
EndSelect
EndSelect
Until Event = 0
time = ElapsedMilliseconds()
fluid_simulation_step();
Render() : onframe + 1
time = ElapsedMilliseconds() - time
If onframe = 60 : onframe = 1
SetWindowTitle(0,"Fluid dynamics w/vorticity - Phil James 2023 - Process time: "+ Str(time)+"ms.")
EndIf
Until Exit = #True
glDeleteTextures_(1,@texture)