Basic Univers
Global p1.POINT, p2.POINT
Macro CosD(x)
Cos((x)*0.0174532)
EndMacro
Macro SinD(x)
Sin((x)*0.0174532)
EndMacro
Enumeration
#CHILD00
#CHILD01
#CHILD11
#CHILD10
EndEnumeration
Structure CAMERA
x.l
y.l
fov.l
EndStructure
Structure QUADTREE
xmin.l
ymin.l
xmax.l
ymax.l
*Child.QUADTREE[4]
EndStructure
Procedure Camera(x, y, fov)
*this.CAMERA = AllocateMemory(SizeOf(CAMERA))
*this\x = x : *this\y = y : *this\fov = fov
ProcedureReturn *this
EndProcedure
Procedure PointInFrustumL(*this.CAMERA, x, y)
If(-(x - *this\x) *(p1\y - *this\y) +(y - *this\y) *(p1\x - *this\x) >= 0)
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure PointInFrustumR(*this.CAMERA, x, y)
If( -(x - *this\x) *(p2\y - *this\y) +(y - *this\y) *(p2\x - *this\x) <= 0)
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure PointInFrustumF(*this.CAMERA, x, y)
ProcedureReturn( -(x - *this\x) *(p3y - *this\y) +(y - *this\y) *(p3x - *this\x) >= 0)
EndProcedure
Procedure Quadtree(xmin, ymin, xmax, ymax, depth)
*this.QUADTREE = AllocateMemory(SizeOf(QUADTREE))
*this\xmin = xmin
*this\xmax = xmax
*this\ymin = ymin
*this\ymax = ymax
If(depth > 0)
xmoy =(xmin + xmax) / 2
ymoy =(ymin + ymax) / 2
depth = depth - 1
*this\Child[#CHILD00] = Quadtree(xmin, ymin, xmoy, ymoy, depth)
*this\Child[#CHILD01] = Quadtree(xmin, ymoy, xmoy, ymax, depth)
*this\Child[#CHILD11] = Quadtree(xmoy, ymoy, xmax, ymax, depth)
*this\Child[#CHILD10] = Quadtree(xmoy, ymin, xmax, ymoy, depth)
EndIf
ProcedureReturn *this
EndProcedure
Procedure QuadInFrustum(*this.QUADTREE, *cam.CAMERA)
Define nbPlansInterieur
nbPlansInterieur = 0
nbPlansInterieur = nbPlansInterieur + PointInFrustumL(*cam, *this\xmin, *this\ymin)
nbPlansInterieur = nbPlansInterieur + PointInFrustumL(*cam, *this\xmin, *this\ymax)
nbPlansInterieur = nbPlansInterieur + PointInFrustumL(*cam, *this\xmax, *this\ymin)
nbPlansInterieur = nbPlansInterieur + PointInFrustumL(*cam, *this\xmax, *this\ymax)
If nbPlansInterieur = 0 : ProcedureReturn #False : EndIf
nbPlansInterieur = 0
nbPlansInterieur = nbPlansInterieur + PointInFrustumR(*cam, *this\xmin, *this\ymin)
nbPlansInterieur = nbPlansInterieur + PointInFrustumR(*cam, *this\xmin, *this\ymax)
nbPlansInterieur = nbPlansInterieur + PointInFrustumR(*cam, *this\xmax, *this\ymin)
nbPlansInterieur = nbPlansInterieur + PointInFrustumR(*cam, *this\xmax, *this\ymax)
If nbPlansInterieur = 0 : ProcedureReturn #False : EndIf
ProcedureReturn #True
EndProcedure
Procedure RenderQuadtree(*this.QUADTREE, *cam.CAMERA, depth)
If QuadInFrustum(*this, *cam)
If(depth > 1)
FrontColor(#Gray)
LineXY((*this\xmin +*this\xmax)/2, *this\ymin,(*this\xmin +*this\xmax)/2, *this\ymax)
LineXY(*this\xmin,(*this\ymin +*this\ymax)/2, *this\xmax,(*this\ymin +*this\ymax)/2)
depth = depth - 1
RenderQuadtree(*this\Child[#CHILD00], *cam, depth)
RenderQuadtree(*this\Child[#CHILD01], *cam, depth)
RenderQuadtree(*this\Child[#CHILD11], *cam, depth)
RenderQuadtree(*this\Child[#CHILD10], *cam, depth)
Else
FrontColor(RGB(196, 196, 196))
Box(*this\xmin + 1, *this\ymin + 1, *this\xmax -*this\xmin - 1, *this\ymax -*this\ymin - 1)
EndIf
EndIf
EndProcedure
Procedure.f Atan2(y.f, x.f)
!fld dword[p.v_y]
!fld dword[p.v_x]
!fpatan
ProcedureReturn
EndProcedure
InitSprite()
InitMouse()
InitKeyboard()
OpenScreen(800, 600, 32, "Simple Quadtree Demo - Seyhajin")
QuadDepth = 6
QuadSize = 599
CamSpeed.f = 2
CamFOV.f = 60.0 / 2.0
ViewLine = 200
*cam.CAMERA = camera(QuadSize/2, QuadSize/2, CamFOV)
*root.QUADTREE = Quadtree(0, 0, QuadSize, QuadSize, QuadDepth)
Repeat
ClearScreen(#Black)
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Up)
*cam\y = *cam\y - CamSpeed
ElseIf KeyboardPushed(#PB_Key_Down)
*cam\y = *cam\y + CamSpeed
EndIf
If KeyboardPushed(#PB_Key_Left)
*cam\x = *cam\x - CamSpeed
ElseIf KeyboardPushed(#PB_Key_Right)
*cam\x = *cam\x + CamSpeed
EndIf
If ExamineMouse()
x.f = MouseX() - *cam\x
y.f = MouseY() - *cam\y
angle.f = 180 +(ATan2(- y, - x)*57.295779)
EndIf
StartDrawing(ScreenOutput())
Box(*root\xmin, *root\ymin, *root\xmax, *root\ymax, #White)
RenderQuadtree(*root, *cam, QuadDepth)
LineXY(*cam\x, *cam\y, *cam\x +(ViewLine/2)*CosD(angle), *cam\y +(ViewLine/2)*SinD(angle), #Yellow)
p1\x = *cam\x + ViewLine*CosD(angle - CamFOV)
p1\y = *cam\y + ViewLine*SinD(angle - CamFOV)
LineXY(*cam\x, *cam\y, p1\x, p1\y, #Red)
p2\x = *cam\x + ViewLine*CosD(angle + CamFOV)
p2\y = *cam\y + ViewLine*SinD(angle + CamFOV)
LineXY(*cam\x, *cam\y, p2\x, p2\y, #Red)
Circle(*cam\x, *cam\y, 6, #Blue)
StopDrawing()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)