http://www.intpowertechcorp.com/GDC03.pdf
C'est bien rigolo, mais pour le moment ce n'est qu'un code qui refait absolument la même chose,
j'espère pouvoir vous faire une petite personnalisation plus tard
Le code de mise en œuvre est assez sale, mais la partie de simulation est super propre
[EDIT] Version 2, mise à jour
Code : Tout sélectionner
;{######################################
; Programme : Dynamique des Fluides, GAME ENGINE DEMO
#VERSION = "2.00"
;
; Description : - Mets en place quelques fonctions simples et rapide permettant la simulation d'un fluide et de particules
; - L'interface permets de tester ces fonctions rapidement
;
; Détails & TODOs réalisés:
; - Version 1.00
; - Moteur de simulation
; - Interface, clavier / souris
;
; - Version 2.00
; - Ajout de sources flux / particules
; - MAJ de l'interface : + de fluidité
; - Multiples conditions limites : Boite / Libre
;
; Ajouts prévus :
; - Champ de particules de taille != du fluide
; - Image à la place des particules
; - Heigth map des vecteurs vitesse
; - Tracé de lignes de flux continues
;
; Bug trouvés :
; -
;
; Bug corrigés :
; -
;
; Sources :
; - Réalisé à partir de l'article de Jos Stam
; "Real-Time Fluid Dynamics for Games"
; - Plus de document du même auteur :
; http://www.dgp.toronto.edu/people/stam/reality/index.html
; Compilateur :
; - PureBasic 5.22LTS
; - x86 / x64
; - Window / Linux / Mac
; - Pas d'usage d'API
;
; Auteur : graph100 alias Kriek106
;}######################################
DisableDebugger
;{ initialisation
Structure POINT_d
x.d
y.d
EndStructure
Structure tableau
Array tab.d(0, 0)
EndStructure
Macro Tableau_init(_adr_, _struct_)
_adr_ = AllocateMemory(SizeOf(_struct_))
InitializeStructure(_adr_, _struct_)
EndMacro
Macro Tableau_Free(_adr_, _struct_)
ClearStructure(_adr_, _struct_)
FreeMemory(_adr_)
EndMacro
Structure Fluide
; Paramètres
W.l
H.l
Viscosite.d
; Calculs
dim_w.l ; = w + 1 ; Dim 0 et n+1 sont là pour les conditions limites
dim_h.l ; = h + 1
max_wh.d ; max(W, H)
; Tableaux des vitesses du fluide
*u.tableau
*v.tableau
*u_prec.tableau
*v_prec.tableau
EndStructure
Structure Densite
diffusion.d ; taux de diffusion de la densité (entre 0 et 1)
*densite.tableau
*densite_prec.tableau
EndStructure
Structure Source_Vitesse
Pos.POINT
dir.POINT_d ; pixels / seconde
vitesse.d ; indicatif, ne sert pas dans les calculs, mais pour affichage
EndStructure
Structure Source_Particule
Pos.POINT
Debit.d ; particules / seconde
EndStructure
Structure SIM_FL
Fluide.Fluide
Densite.Densite
dt.d ; s entre chaque simulation
List Source_Vitesses.Source_Vitesse()
List Source_Particules.Source_Particule()
EndStructure
Procedure Fluide_Init(*obj.Fluide, Largeur.l, Hauteur.l, Viscosite.d)
With *obj
\W = Largeur
\H = Hauteur
If \W < \H
\max_wh = \W
Else
\max_wh = \H
EndIf
\Viscosite = Viscosite
\Dim_w = \w + 1
\Dim_h = \h + 1
Tableau_init(\u, tableau)
Tableau_init(\v, tableau)
Tableau_init(\u_prec, tableau)
Tableau_init(\v_prec, tableau)
Dim \u\tab(\Dim_w, \Dim_h)
Dim \v\tab(\Dim_w, \Dim_h)
Dim \u_prec\tab(\Dim_w, \Dim_h)
Dim \v_prec\tab(\Dim_w, \Dim_h)
EndWith
EndProcedure
Procedure Densite_Init(*obj.Densite, *fluide.Fluide, Diffusion.d)
With *obj
\diffusion = Diffusion
Tableau_init(\densite, tableau)
Tableau_init(\densite_prec, tableau)
Dim \densite\tab(*fluide\Dim_w, *fluide\Dim_h)
Dim \densite_prec\tab(*fluide\Dim_w, *fluide\Dim_h)
EndWith
EndProcedure
Procedure.i AjouterSource_Flux(*obj.SIM_FL, x.l, y.l, dir_x.d, dir_y.d)
Protected *new_vit.Source_Vitesse = AddElement(*obj\Source_Vitesses())
*new_vit\Pos\x = x
*new_vit\Pos\y =y
*new_vit\dir\x = dir_x
*new_vit\dir\y = dir_y
*new_vit\vitesse = Sqr(*new_vit\dir\x * *new_vit\dir\x + *new_vit\dir\y * *new_vit\dir\y)
ProcedureReturn *new_vit
EndProcedure
Procedure.i AjouterSource_Particules(*obj.SIM_FL, x.l, y.l, debit.d)
Protected *new_part.Source_Particule = AddElement(*obj\Source_Particules())
*new_part\Pos\x = x
*new_part\Pos\y = y
*new_part\Debit = debit
ProcedureReturn *new_part
EndProcedure
;}
;{ Simulation
Procedure FS_SetBoundaryCondition_Boite(*obj.SIM_FL, MODE.l, Array x.d(2))
With *obj
; MODE = 0 : lorsque x() = dens()
; MODE = 1 : lorsque x() = u()
; MODE = 2 : lorsque x() = v()
Protected i
If MODE = 2
For i = 1 To \Fluide\W
x(i, 0) = - x(i, 1)
x(i, \Fluide\dim_h) = - x(i, \Fluide\H)
Next
Else
For i = 1 To \Fluide\W
x(i, 0) = x(i, 1)
x(i, \Fluide\dim_h) = x(i, \Fluide\H)
Next
EndIf
If MODE = 1
For i = 1 To \Fluide\H
x(0, i) = - x(1, i)
x(\Fluide\dim_w, i) = - x(\Fluide\W, i)
Next
Else
For i = 1 To \Fluide\H
x(0, i) = x(1, i)
x(\Fluide\dim_w, i) = x(\Fluide\W, i)
Next
EndIf
; Les coins
x(0, 0) = 0.5 * (x(1, 0) + x(0, 1))
x(0, \Fluide\dim_h) = 0.5 * (x(1, \Fluide\dim_h) + x(0, \Fluide\H))
x(\Fluide\dim_w, 0) = 0.5 * (x(\Fluide\W, 0) + x(\Fluide\dim_w, 1))
x(\Fluide\dim_w, \Fluide\dim_h) = 0.5 * (x(\Fluide\W, \Fluide\dim_h) + x(\Fluide\dim_w, \Fluide\H))
EndWith
EndProcedure
Procedure FS_SetBoundaryCondition_Libre(*obj.SIM_FL, MODE.l, Array x.d(2))
With *obj
Protected i
For i = 1 To \Fluide\W
x(i, 0) = x(i, 1)
x(i, \Fluide\dim_h) = x(i, \Fluide\H)
Next
For i = 1 To \Fluide\H
x(0, i) = x(1, i)
x(\Fluide\dim_w, i) = x(\Fluide\W, i)
Next
; Les coins
x(0, 0) = 0.5 * (x(1, 0) + x(0, 1))
x(0, \Fluide\dim_h) = 0.5 * (x(1, \Fluide\dim_h) + x(0, \Fluide\H))
x(\Fluide\dim_w, 0) = 0.5 * (x(\Fluide\W, 0) + x(\Fluide\dim_w, 1))
x(\Fluide\dim_w, \Fluide\dim_h) = 0.5 * (x(\Fluide\W, \Fluide\dim_h) + x(\Fluide\dim_w, \Fluide\H))
EndWith
EndProcedure
Prototype FS_SetBoundaryCondition(*obj.SIM_FL, MODE.l, Array x.d(2))
Global FS_SetBoundaryCondition.FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Boite()
Procedure FS_LinSolve(*obj.SIM_FL, MODE.l, Array x.d(2), Array x0.d(2), a.d, c.d)
With *obj
Protected.l i, j, k
For k = 0 To 20
For i = 1 To \Fluide\W
For j = 1 To \Fluide\H
x(i, j) = (x0(i, j) + a * (x(i-1, j) + x(i+1, j) + x(i, j-1) + x(i, j+1))) / c
Next
Next
FS_SetBoundaryCondition(*obj, MODE, x())
Next
EndWith
EndProcedure
Procedure FS_AddSource(*obj.SIM_FL, Array x.d(2), Array source.d(2))
With *obj
Protected i, j
For i = 0 To \Fluide\dim_w
For j = 0 To \Fluide\dim_h
x(i, j) = x(i, j) + \dt * source(i, j)
Next
Next
EndWith
EndProcedure
Procedure FS_Diffusion(*obj.SIM_FL, MODE.l, Array x.d(2), Array x0.d(2), diffusion.d, dt.d)
With *obj
Protected.d a = dt * diffusion * \Fluide\W * \Fluide\H
FS_LinSolve(*obj, MODE, x(), x0(), a, 1 + 4 * a)
EndWith
EndProcedure
Procedure FS_Advection(*obj.SIM_FL, MODE.l, Array d.d(2), Array d0.d(2), Array u.d(2), Array v.d(2), dt.d)
With *obj
Protected.l i, j, i0, j0, i1, j1
Protected.d x, y, s0, t0, s1, t1, dt0_u, dt0_v
; dt0 = dt * N ; mais ici j'ai pris un rectangle et non pas un carré !
dt0_u = dt * \Fluide\W
dt0_v = dt * \Fluide\H
For i = 1 To \Fluide\W
For j = 1 To \Fluide\H
x = i - dt0_u * u(i, j)
y = j - dt0_v * v(i, j)
If x < 0.5 : x = 0.5 : EndIf
If x > \Fluide\W + 0.5 : x = \Fluide\W + 0.5 : EndIf
i0 = Round(x, #PB_Round_Down)
i1 = i0 + 1
If y < 0.5 : y = 0.5 : EndIf
If y > \Fluide\H + 0.5 : y = \Fluide\H + 0.5 : EndIf
j0 = Round(y, #PB_Round_Down)
j1 = j0 + 1
s1 = x - i0
s0 = 1 - s1
t1 = y - j0
t0 = 1 - t1
d(i, j) = s0 * (t0 * d0(i0, j0) + t1 * d0(i0, j1)) + s1 * (t0 * d0(i1, j0) + t1 * d0(i1, j1))
Next
Next
FS_SetBoundaryCondition(*obj, MODE, d())
EndWith
EndProcedure
Procedure FS_Projection(*obj.SIM_FL, Array u.d(2), Array v.d(2), Array p.d(2), Array div.d(2))
With *obj
Protected.l i, j
For i = 1 To \Fluide\W
For j = 1 To \Fluide\H
; ici on change le /N qui apparait dans le code original, pour voir comment ça se comporte avec un rectangle
; div(i, j) = -0.5 * ((u(i+1, j) - u(i-1, j)) / *obj\Fluide\W + (v(i, j+1) - v(i, j-1)) / *obj\Fluide\H)
div(i, j) = -0.5 * ((u(i+1, j) - u(i-1, j) + v(i, j+1) - v(i, j-1)) / *obj\Fluide\max_wh)
p(i, j) = 0
Next
Next
FS_SetBoundaryCondition(*obj, 0, div())
FS_SetBoundaryCondition(*obj, 0, p())
FS_LinSolve(*obj, 0, p(), div(), 1, 4) ; boom !! prend ça !
For i = 1 To \Fluide\W
For j = 1 To \Fluide\H
u(i, j) = u(i, j) - 0.5 * \Fluide\W * (p(i+1, j) - p(i-1, j))
v(i, j) = v(i, j) - 0.5 * \Fluide\H * (p(i, j+1) - p(i, j-1))
Next
Next
FS_SetBoundaryCondition(*obj, 1, u())
FS_SetBoundaryCondition(*obj, 2, v())
EndWith
EndProcedure
Procedure Fluide_Sim_Densite(*obj.SIM_FL)
FS_AddSource(*obj, *obj\Densite\densite\tab(), *obj\Densite\densite_prec\tab())
Swap *obj\Densite\densite_prec, *obj\Densite\densite
FS_Diffusion(*obj, 0, *obj\Densite\densite\tab(), *obj\Densite\densite_prec\tab(), *obj\Densite\diffusion, *obj\dt)
Swap *obj\Densite\densite_prec, *obj\Densite\densite
FS_Advection(*obj, 0, *obj\Densite\densite\tab(), *obj\Densite\densite_prec\tab(), *obj\Fluide\u\tab(), *obj\Fluide\v\tab(), *obj\dt)
EndProcedure
Procedure Fluide_Sim_Velocite(*obj.SIM_FL)
FS_AddSource(*obj, *obj\Fluide\u\tab(), *obj\Fluide\u_prec\tab())
FS_AddSource(*obj, *obj\Fluide\v\tab(), *obj\Fluide\v_prec\tab())
Swap *obj\Fluide\u_prec, *obj\Fluide\u
Swap *obj\Fluide\v_prec, *obj\Fluide\v
FS_Diffusion(*obj, 1, *obj\Fluide\u\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\Viscosite, *obj\dt)
FS_Diffusion(*obj, 2, *obj\Fluide\v\tab(), *obj\Fluide\v_prec\tab(), *obj\Fluide\Viscosite, *obj\dt)
FS_Projection(*obj, *obj\Fluide\u\tab(), *obj\Fluide\v\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\v_prec\tab())
Swap *obj\Fluide\u_prec, *obj\Fluide\u
Swap *obj\Fluide\v_prec, *obj\Fluide\v
FS_Advection(*obj, 1, *obj\Fluide\u\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\v_prec\tab(), *obj\dt)
FS_Advection(*obj, 2, *obj\Fluide\v\tab(), *obj\Fluide\v_prec\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\v_prec\tab(), *obj\dt)
FS_Projection(*obj, *obj\Fluide\u\tab(), *obj\Fluide\v\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\v_prec\tab())
EndProcedure
;}
Define Var.SIM_FL : InitializeStructure(Var, SIM_FL)
Define souris.POINT, souris_case.POINT, *Obj_sous_souris, Type_sous_souris.l
Define mouse.POINT, mouse_old.POINT
Enumeration 1
#OBJ_Source_VITESSE
#OBJ_Source_PARTICULE
EndEnumeration
SIMUL = #True
Macro INIT_SIM
Fluide_Init(Var\fluide, 100, 100, 0)
Densite_Init(Var\Densite, Var\Fluide, 0.0)
EndMacro
;{ scénario : la chandelle
INIT_SIM
AjouterSource_Flux(Var, Var\Fluide\dim_w >> 1 - 1, Var\Fluide\dim_h - 5, 0, -50)
AjouterSource_Particules(Var, Var\Fluide\dim_w >> 1, Var\Fluide\dim_h - 20, 1800 / 20)
;}
;{ Démo
;{ fenetre
width = 7
width_sur2moins1 = width >> 1 - 1
width_sur2 = width >> 1
width_moins1 = width - 1
draw_info_h = (Var\Fluide\dim_h + 1) * width +1
draw_info_w = (Var\Fluide\dim_w +1) * width +1
DRAW_CASE = #False
DRAW_VITESSE = #True
DRAW_PARTICULES = #True
DRAW_SOURCES = #True
Tps_Loop_mini.d = 0.040 ; s
OpenWindow(0, 0, 0, draw_info_w, draw_info_h + 200, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), #PB_Canvas_Keyboard)
SetActiveGadget(0)
;}
time = ElapsedMilliseconds()
Repeat
FLAG_MOUSE_RIGHT = #False
FLAG_MOUSE_LEFT = #False
Repeat
event = WindowEvent()
;{ event
If event = #PB_Event_Gadget And EventGadget() = 0
;{ souris
souris\x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
souris\y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
souris_case\x = souris\x / width
souris_case\y = souris\y / width
If souris_case\x < 1 : souris_case\x = 1 : EndIf
If souris_case\x > Var\Fluide\W : souris_case\x = Var\Fluide\W :EndIf
If souris_case\y < 1 : souris_case\y = 1 : EndIf
If souris_case\y > Var\Fluide\H : souris_case\y = Var\Fluide\H :EndIf
;}
;{ Touche D
If GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_D
If *Obj_sous_souris And Type_sous_souris = #OBJ_Source_PARTICULE
ChangeCurrentElement(var\Source_Particules(), *Obj_sous_souris)
With var\Source_Particules()
x = souris\x - (\Pos\x * width + width_sur2)
y = souris\y - (\Pos\y * width + width_sur2)
\Debit = Sqr(x * x + y * y)
EndWith
ElseIf *Obj_sous_souris And Type_sous_souris = #OBJ_Source_VITESSE
ChangeCurrentElement(var\Source_Vitesses(), *Obj_sous_souris)
With var\Source_Vitesses()
\dir\x = souris\x - (\Pos\x * width + width_sur2)
\dir\y = souris\y - (\Pos\y * width + width_sur2)
\vitesse = Sqr(\dir\x * \dir\x + \dir\y * \dir\y)
EndWith
EndIf
EndIf
;}
;{ Touche E
If GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_E
If *Obj_sous_souris And Type_sous_souris = #OBJ_Source_PARTICULE
ChangeCurrentElement(var\Source_Particules(), *Obj_sous_souris)
With var\Source_Particules()
\Pos\x = souris_case\x
\Pos\y = souris_case\y
EndWith
ElseIf *Obj_sous_souris And Type_sous_souris = #OBJ_Source_VITESSE
ChangeCurrentElement(var\Source_Vitesses(), *Obj_sous_souris)
With var\Source_Vitesses()
\Pos\x = souris_case\x
\Pos\y = souris_case\y
EndWith
EndIf
EndIf
;}
If EventType() = #PB_EventType_KeyUp
;{ Key
If GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_Escape
event = #PB_Event_CloseWindow
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_C
INIT_SIM
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_Delete
If *Obj_sous_souris And Type_sous_souris = #OBJ_Source_PARTICULE
ChangeCurrentElement(var\Source_Particules(), *Obj_sous_souris)
DeleteElement(var\Source_Particules())
*Obj_sous_souris = 0
Type_sous_souris = 0
ElseIf *Obj_sous_souris And Type_sous_souris = #OBJ_Source_VITESSE
ChangeCurrentElement(var\Source_Vitesses(), *Obj_sous_souris)
DeleteElement(var\Source_Vitesses())
*Obj_sous_souris = 0
Type_sous_souris = 0
EndIf
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_X
; ajouter ici les autres conditions si besoin
If FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Boite()
FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Libre()
ElseIf FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Libre()
FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Boite()
EndIf
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_V
If DRAW_VITESSE : DRAW_VITESSE = #False
Else : DRAW_VITESSE = #True
EndIf
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_G
If DRAW_CASE : DRAW_CASE = #False
Else : DRAW_CASE = #True
EndIf
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_P
If DRAW_PARTICULES : DRAW_PARTICULES = #False
Else : DRAW_PARTICULES = #True
EndIf
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_S
If DRAW_SOURCES : DRAW_SOURCES = #False
Else : DRAW_SOURCES = #True
EndIf
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_Space
If SIMUL = #True : SIMUL = #False
Else : SIMUL = #True
EndIf
ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_N
If EDIT = #True : EDIT = #False
Else : EDIT = #True
EndIf
EndIf
;}
ElseIf EventType() = #PB_EventType_LeftButtonUp
;{ Ajout source permanente de vitesse
;{ détection d'objet sous la souris
*Obj_sous_souris = 0
Type_sous_souris = 0
; vitesse
ForEach var\Source_Vitesses()
With var\Source_Vitesses()
If \Pos\x = souris_case\x And \Pos\y = souris_case\y
*Obj_sous_souris = Var\Source_Vitesses()
Type_sous_souris = #OBJ_Source_VITESSE
EndIf
EndWith
Next
; particules
ForEach var\Source_Particules()
With var\Source_Particules()
If \Pos\x = souris_case\x And \Pos\y = souris_case\y
*Obj_sous_souris = Var\Source_Particules()
Type_sous_souris = #OBJ_Source_PARTICULE
EndIf
EndWith
Next
;}
If EDIT And *Obj_sous_souris = 0
*Obj_sous_souris = AjouterSource_Flux(Var, souris_case\x, souris_case\y, 20, 0)
Type_sous_souris = #OBJ_Source_VITESSE
EndIf
;}
ElseIf EventType() = #PB_EventType_RightButtonUp
;{ Ajout source permanente de particules
If EDIT
*Obj_sous_souris = AjouterSource_Particules(Var, souris_case\x, souris_case\y, 10)
Type_sous_souris = #OBJ_Source_PARTICULE
EndIf
;}
EndIf
;{ AJOUT à la souris
If EDIT = #False
If GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_RightButton = #PB_Canvas_RightButton
FLAG_MOUSE_RIGHT = #True
EndIf
If GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton = #PB_Canvas_LeftButton
FLAG_MOUSE_LEFT = #True
Else
REINIT = #True
EndIf
EndIf
;}
EndIf
;}
Until event = 0 Or event = #PB_Event_CloseWindow
;{ mise à jour du delta de temps et stabilisation des FPS
Var\dt = (ElapsedMilliseconds() - time) / 1000
If var\dt < Tps_Loop_mini
Delay(1000 * (Tps_Loop_mini - Var\dt))
EndIf
Var\dt = (ElapsedMilliseconds() - time) / 1000 ; on reprend le temps total de la boucle, delay compris
time = ElapsedMilliseconds()
;}
;{ SIMULATION
If SIMUL
tps = ElapsedMilliseconds()
; reset des anciens tableaux
Dim Var\Densite\densite_prec\tab(Var\Fluide\dim_w, Var\Fluide\dim_h)
Dim Var\Fluide\u_prec\tab(Var\Fluide\dim_w, Var\Fluide\dim_h)
Dim Var\Fluide\v_prec\tab(Var\Fluide\dim_w, Var\Fluide\dim_h)
If EDIT = #False
;{ ajout a la souris de particules
If FLAG_MOUSE_RIGHT
var\Densite\densite_prec\tab(souris_case\x, souris_case\y) = 10000 * Var\dt
EndIf
;}
;{ ajout a la souris de vitesse
If FLAG_MOUSE_LEFT
If REINIT
REINIT = #False
mouse_old = souris
EndIf
mouse\x = (souris\x - mouse_old\x) * 50
mouse\y = (souris\y - mouse_old\y) * 50
mouse_old = souris
var\Fluide\u_prec\tab(souris_case\x, souris_case\y) = mouse\x
var\Fluide\v_prec\tab(souris_case\x, souris_case\y) = mouse\y
EndIf
;}
;{ Ajout des sources de particules
ForEach Var\Source_Particules()
With var\Source_Particules()
var\Densite\densite_prec\tab(\Pos\x, \Pos\y) = 20*\Debit * Var\dt
EndWith
Next
;}
;{ Ajout des sources de vitesse
ForEach Var\Source_Vitesses()
With var\Source_Vitesses()
var\Fluide\u_prec\tab(\Pos\x, \Pos\y) = \dir\x
var\Fluide\v_prec\tab(\Pos\x, \Pos\y) = \dir\y
EndWith
Next
;}
EndIf
;For i = 1 To 10
; Simulation
Fluide_Sim_Velocite(Var)
Fluide_Sim_Densite(Var)
;Next
tps = ElapsedMilliseconds() - tps
EndIf
;}
;{ Affichage
If StartDrawing(CanvasOutput(0))
Box(0, 0, OutputWidth(), OutputHeight(), 0)
;{ particules / Grille / vitesse
If DRAW_PARTICULES
; dessin de la densité
NB_particules.d = 0
For i = 0 To Var\Fluide\dim_w
For j = 0 To Var\Fluide\dim_h
x = i * width + width >> 1
y = j * width + width >> 1
c.d = 255*(Var\Densite\densite\tab(i, j))
NB_particules + Var\Densite\densite\tab(i, j)
If c > 255 : c = 255 : EndIf
; Box(x - width_sur2moins1, y - width_sur2moins1, width_moins1, width_moins1, RGB(c, c, c))
Box(x - width_sur2moins1, y - width_sur2moins1, width, width, RGB(c, c, c))
Next
Next
EndIf
If DRAW_CASE
; grille
For i = 0 To Var\Fluide\dim_w +1
Line(i * width, 0, 1, draw_info_h, $003F00)
Next
For i = 0 To Var\Fluide\dim_h +1
Line(0, i * width, draw_info_w, 1, $003F00)
Next
EndIf
If DRAW_VITESSE
; dessin des vecteur vitesse
For i = 0 To Var\Fluide\dim_w
For j = 0 To Var\Fluide\dim_h
x = i * width + width >> 1
y = j * width + width >> 1
LineXY(x, y, x + Var\Fluide\u\tab(i, j) * 10, y + Var\Fluide\v\tab(i, j) * 10, #Red)
Next
Next
EndIf
;}
;{ sources
If DRAW_SOURCES Or EDIT
; vitesse
ForEach var\Source_Vitesses()
With var\Source_Vitesses()
x = \Pos\x * width + width_sur2
y = \Pos\y * width + width_sur2
Circle(x, y, width_sur2, $007AFF)
If *Obj_sous_souris = Var\Source_Vitesses()
DrawingMode(#PB_2DDrawing_Outlined)
Circle(x, y, width_sur2 + 3, #Blue)
Circle(x, y, width_sur2 + 2, #Blue)
DrawingMode(#PB_2DDrawing_Default)
EndIf
LineXY(x, y, x + \dir\x, y + \dir\y, #Green)
EndWith
Next
; particules
ForEach var\Source_Particules()
With var\Source_Particules()
x = \Pos\x * width + width_sur2
y = \Pos\y * width + width_sur2
Circle(x, y, width_sur2, #White)
If *Obj_sous_souris = Var\Source_Particules()
DrawingMode(#PB_2DDrawing_Outlined)
Circle(x, y, width_sur2 + 3, #Blue)
Circle(x, y, width_sur2 + 2, #Blue)
DrawingMode(#PB_2DDrawing_Default)
EndIf
DrawingMode(#PB_2DDrawing_Outlined)
Circle(x, y, \Debit, $007AFF)
DrawingMode(#PB_2DDrawing_Default)
EndWith
Next
EndIf
;}
;{ INFO
If EDIT
Circle(souris_case\x * width + width_sur2, souris_case\y * width + width_sur2, width_sur2, #Blue)
EndIf
; info
If SIMUL
DrawText(10, draw_info_h + 5, "Simulation : En cours", #White, 0)
Else
DrawText(10, draw_info_h + 5, "Simulation : En pause", #White, 0)
EndIf
If EDIT
DrawText(200, draw_info_h + 5, "EDITION des SOURCES", #White, 0)
Else
; DrawText(200, draw_info_h + 5, "", #White, 0)
EndIf
DrawText(10, draw_info_h + 25, "dt = " + StrD(Var\dt, 3), #White, 0)
DrawText(100, draw_info_h + 25, "NB_part = " + StrD(NB_particules, 3), #White, 0)
DrawText(10, draw_info_h + 50, "[Souris Gauche] ajouter du flux", #White, 0)
DrawText(10, draw_info_h + 70, "[Souris Droite] ajouter des particules", #White, 0)
DrawText(10, draw_info_h + 90, "[N] MODE Sources permanentes", #White, 0)
DrawText(10, draw_info_h + 110, "[Clic sur source] Selectionne une source", #White, 0)
DrawText(10, draw_info_h + 130, "[SUPPR] Supprime une source", #White, 0)
DrawText(10, draw_info_h + 150, "[D] Modifier le niveau des sources", #White, 0)
DrawText(10, draw_info_h + 170, "[E] Déplacer une sources", #White, 0)
DrawText(280, draw_info_h + 30, "[C] réinitialiser", #White, 0)
DrawText(280, draw_info_h + 50, "[ESPACE] pause", #White, 0)
DrawText(280, draw_info_h + 70, "[ECHAP] quitter", #White, 0)
DrawText(280, draw_info_h + 90, "[G] Affiche la grille", #White, 0)
DrawText(280, draw_info_h + 110, "[P] Affiche les particules", #White, 0)
DrawText(280, draw_info_h + 130, "[V] Affiche les vecteurs vitesse", #White, 0)
DrawText(280, draw_info_h + 130, "[S] Affiche les Sources", #White, 0)
DrawText(280, draw_info_h + 150, "[X] Change les conditions aux limites", #White, 0)
DrawText(500, draw_info_h + 10, "INFO Object", #White, 0)
If *Obj_sous_souris
If Type_sous_souris = #OBJ_Source_PARTICULE
DrawText(500, draw_info_h + 35, "Type : Source de Particule", #White, 0)
ChangeCurrentElement(var\Source_Particules(), *Obj_sous_souris)
DrawText(500, draw_info_h + 55, "Débit : " + StrD(var\Source_Particules()\Debit * 20, 3), #White, 0)
Else
DrawText(500, draw_info_h + 35, "Type : Source de Flux", #White, 0)
ChangeCurrentElement(var\Source_Vitesses(), *Obj_sous_souris)
DrawText(500, draw_info_h + 55, "Vitesse : " + StrD(var\Source_Vitesses()\vitesse, 3), #White, 0)
EndIf
Else
DrawText(500, draw_info_h + 30, "Pas de sélection", #White, 0)
EndIf
If FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Boite()
DrawText(500, draw_info_h + 80, "Condition Limite : Boite", #White, 0)
ElseIf FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Libre()
DrawText(500, draw_info_h + 80, "Condition Limite : Libre", #White, 0)
EndIf
;}
StopDrawing()
EndIf
;}
Until event = #PB_Event_CloseWindow
;}
End