Eclairage dynamique 2D
Publié : ven. 02/juin/2017 0:42
Il y a 2 bugs que je ne sais pas régler élégamment. Je pense que c'est un problème de virgule flottant avec l'angle et le trie.
Il se fait tard je verrais ça demain. Si vous trouvez avant, dites moi.
Espace pour voir le dessous de l'affaire...
Il se fait tard je verrais ça demain. Si vous trouvez avant, dites moi.
Espace pour voir le dessous de l'affaire...
Code : Tout sélectionner
DisableDebugger
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0:MessageRequester("Error", "Can't open the sprite system", 0):End:EndIf
If OpenWindow(0, 0, 0,800, 600,"lighting", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)=0:MessageRequester("Error", "Can't open windowed screen!", 0):EndIf
If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)=0:MessageRequester("Error", "Can't open windowed screen!", 0):EndIf
Structure seg
x1.d
y1.d
x2.d
y2.d
EndStructure
Structure retour
x.d
y.d
param.d
EndStructure
Structure xy
x.d
y.d
EndStructure
Structure ray
a.xy
b.xy
EndStructure
Global NewList pt.xy()
Global NewList Seg.seg()
Global NewMap dot.xy()
Global NewList angle.d()
NewList ligne.xy()
modedebug.i=0
f.d=0.00001
Ray.ray
Segment.ray
Procedure Intersection(*ray.ray,*seg.seg,*retour.retour)
r_dx.d = *ray\b\x-*ray\a\x
r_dy.d = *ray\b\y-*ray\a\y
s_dx.d = *seg\x2-*seg\x1
s_dy.d = *seg\y2-*seg\y1
r_mag.d = Sqr(r_dx*r_dx+r_dy*r_dy);
s_mag.d = Sqr(s_dx*s_dx+s_dy*s_dy);
If r_dx/r_mag=s_dx/s_mag And r_dy/r_mag=s_dy/s_mag:ProcedureReturn 0:EndIf
T2.d = (r_dx*(*seg\y1-*ray\a\y) + r_dy*(*ray\a\x-*seg\x1))/(s_dx*r_dy - s_dy*r_dx);
T1.d = (*seg\x1+s_dx*T2-*ray\a\x)/r_dx;
If T1<0:ProcedureReturn 0:EndIf
If T2<0 Or T2>1:ProcedureReturn 0:EndIf;
*retour\x=*ray\a\x+r_dx*T1
*retour\y=*ray\a\y+r_dy*T1
*retour\param=T1
ProcedureReturn *retour
EndProcedure
Procedure AddSegment(x1.d,y1.d,x2.d,y2.d)
AddElement(seg()):seg()\x1=x1:seg()\y1=y1:seg()\x2=x2:seg()\y2=y2
dot(Str(x1)+"\"+Str(y1))\x=x1:dot(Str(x1)+"\"+Str(y1))\y=y1
dot(Str(x2)+"\"+Str(y2))\x=x2:dot(Str(x2)+"\"+Str(y2))\y=y2
EndProcedure
Procedure ProcessAllSegments()
; Get all unique points
ForEach dot()
AddElement(pt())
pt()\x=dot()\x
pt()\y=dot()\y
Next
EndProcedure
CreateImage(0,800,600,32,RGB(0,0,0))
CreateSprite(0,800,600)
;external box// Fenêtre englobante
Addsegment(-1,-1,800,-1)
addsegment(800,-1,800,600)
Addsegment(800,600,-1,600)
Addsegment(-1,600,-1,-1)
;random squares// carrés aléatoires
For i=1 To 30
size.d=Random(50,10)
rx.d=Random(750,50)
ry.d=Random(550,50)
Addsegment(rx,ry,rx+size,ry)
Addsegment(rx+size,ry,rx+size,ry+size)
Addsegment(rx+size,ry+size,rx,ry+size)
Addsegment(rx,ry+size,rx,ry)
Next i
For an=0 To 360 Step 36
AddSegment(200+20*Cos(Radian(an)),200+20*Sin(Radian(an)),200+20*Cos(Radian(an+36)),200+20*Sin(Radian(an+36)))
Next an
ProcessAllSegments()
MouseLocate(10,10)
Repeat
Repeat:Until WindowEvent()=0
Delay(3):FlipBuffers():ExamineKeyboard():ExamineMouse():If KeyboardReleased(#PB_Key_Space):modedebug=~modedebug:EndIf
x.d=MouseX():y.d=MouseY()
ClearList(ligne())
ClearList(angle())
; Get all angles
ForEach pt()
dx.d=pt()\x-x:dy.d=pt()\y-y
angle.d=ATan2(dx,dy)
AddElement(angle()):angle()=angle-f
AddElement(angle()):angle()=angle
AddElement(angle()):angle()=angle+f
Next
SortList(angle(),#PB_Sort_Ascending)
ForEach angle()
ray\a\x=x:ray\a\y=y
ray\b\x=Cos(angle())+x:ray\b\y=Sin(angle())+y
Retour.retour
closest.retour
closest\param=10000
ForEach seg()
If Intersection(@ray,@seg(),@retour)=0:Continue:EndIf
If retour\param<closest\param
closest\param=retour\param
closest\x=retour\x
closest\y=retour\y
EndIf
Next
If closest\param=10000:Continue:EndIf
AddElement(ligne())
ligne()\x=closest\x:ligne()\y=closest\y
Next
;Display everything // Affichage
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_Gradient)
BackColor($FFFFFF)
FrontColor($000000)
CircularGradient(x,y,450)
Circle(x,y,800)
StopDrawing()
FirstElement(ligne())
prevx.d=ligne()\x
prevy.d=ligne()\y
StartDrawing(SpriteOutput(0))
Box(0,0,800,600,RGB(1,1,1))
ForEach ligne()
If modedebug:LineXY(x,y,ligne()\x,ligne()\y,RGB(0,255,0)):EndIf
If modedebug=0:LineXY(prevx,prevy,ligne()\x,ligne()\y,#Black):EndIf
prevx=ligne()\x:prevy=ligne()\y
If modedebug:Circle(ligne()\x,ligne()\y,2,RGB(0,255,0)):EndIf
Next
FirstElement(ligne())
If modedebug=0
LineXY(prevx,prevy,ligne()\x,ligne()\y,#Black)
FillArea(x,y,#Black,#Black)
EndIf
;display squares // affiche les segments des carrés
ForEach seg()
LineXY(seg()\x1,seg()\y1,seg()\x2,seg()\y2,RGB(255,0,0))
Next
;display mouse // affiche la souris
Circle(MouseX(),MouseY(),5,RGB(255,0,0))
DrawText(0,0,"Press [SPACE]")
StopDrawing()
;display gradient light // affiche le dégradé d'éclairage
StartDrawing(ScreenOutput())
DrawImage(ImageID(0),0,0)
StopDrawing()
;display mask sprite // Affiche le sprite de masque
DisplayTransparentSprite(0,0,0)
Until KeyboardPushed(#PB_Key_Escape)