Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Quadtree

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 19.05.2012, 16:52    Titel: Quadtree Antworten mit Zitat

Hi zusammen,

wollte nach längerer Zeit mal wieder etwas neues probieren nachdem ich mich durch die OpenGL Welt gelesen und getestet habe und mir irgendwie schwindelig wurde bei den notwendigen Vorarbeiten eines 'Grundgerüsts' um überhaupt etwas sinnvolles damit anfangen zu können...

Im Moment hänge ich am eine wohl wichtigsten Element, dem Quadtree
das ich mir zu test und übungszwecken erstmal auf 2D fbgfx ebende zusammengebastelt habe.

Erste Versuche klappten super, mit 1-10 'Objekten' kein problem...
wollte das ganze dann mal etwas übertreiben mit 1000, aber da ging nichts und runtergetestet habe ich nun auf 50 und auch da kommt es zu einem Speicherüberlauf...

Bin für jeden Tipp und Verbesserungsvorschlag dankbar lächeln

Code:

Sub CMsg (byval Msg as String)
    Dim FF as integer
    FF = FreeFile
    Open CONS for Output as #FF
    print #FF, Msg
    Close #FF
End Sub

Type OBJList
    minX as single
    minZ as single
   
    maxX as single
    maxZ as single
   
    Color as Integer
End Type

Type test_QuadTree
    minX as single
    minZ as single
   
    maxX as Single
    maxZ as Single
   
    Node(0 to 3) as test_QuadTree ptr
   
    IsSplit as byte
   
    Declare Sub Split()
   
    Declare Sub AddObj(MyObj as OBJList ptr)
   
    Declare Sub Draw()
       
    Objects   as OBJList ptr ptr
    OBJ_Count as Integer
   
    maxSplit  as Integer
End Type

Sub test_QuadTree.Split()
    Dim CenterX as Single
    Dim CenterZ as Single
   
    'CenterX = (this.minX + this.maxX) / 2
    'CenterZ = (this.minZ + this.maxZ) / 2

    CenterX = this.minX + ((this.maxX - this.minX) / 2)
    CenterZ = this.minZ + ((this.maxZ - this.minZ) / 2)


    this.IsSplit = 1
   
    this.Node(0) = new test_Quadtree
        this.Node(0) -> minX = this.minX
        this.Node(0) -> minZ = this.minZ
        this.Node(0) -> maxX = CenterX
        this.Node(0) -> maxZ = CenterZ
        this.Node(0) -> maxSplit = this.maxSplit+1
       
    this.Node(1) = new test_Quadtree
        this.Node(1) -> minX = CenterX
        this.Node(1) -> minZ = this.minZ
        this.Node(1) -> maxX = this.maxX
        this.Node(1) -> maxZ = CenterZ
        this.Node(1) -> maxSplit = this.maxSplit+1
       
    this.Node(2) = new test_Quadtree
        this.Node(2) -> minX = this.minX
        this.Node(2) -> minZ = CenterZ
        this.Node(2) -> maxX = CenterX
        this.Node(2) -> maxZ = this.maxZ
        this.Node(2) -> maxSplit = this.maxSplit+1
       
    this.Node(3) = new test_Quadtree
        this.Node(3) -> minX = CenterX
        this.Node(3) -> minZ = CenterZ
        this.Node(3) -> maxX = this.maxX
        this.Node(3) -> maxZ = this.maxZ
        this.Node(3) -> maxSplit = this.maxSplit+1
End Sub
   
   
   
Sub test_QuadTree.AddObj(MyOBJ as OBJList ptr)
    Dim as Single minX, minZ, maxX, maxZ
    Dim CenterX as Single
    Dim CenterZ as Single
    Dim Temp as any ptr
   
    minX = MyOBJ -> minX
    minZ = MyOBJ -> minZ
    maxX = MyOBJ -> maxX
    maxZ = MyOBJ -> maxZ
   
    'CenterX = (this.minX + this.maxX) / 2
    'CenterZ = (this.minZ + this.maxZ) / 2
   
    CenterX = this.minX + ((this.maxX - this.minX) / 2)
    CenterZ = this.minZ + ((this.maxZ - this.minZ) / 2)
   
    'CMsg "OBJ: min "+str(minX)+","+str(minZ) + " Node: min "+str(this.minX)+","+str(this.minZ)
    'CMsg "OBJ: max "+str(maxX)+","+str(maxZ) + " Node: max "+str(this.maxX)+","+str(this.maxZ)
   
    'line (minX,minZ) - (maxX, maxZ), &hFFFF0000, B
   
    If (minX >= this.minX) and (minZ >= this.minZ) and (maxX <= this.maxX) and (maxZ <= this.maxZ) Then
        'Is Storable!
       
        If this.maxSplit < 4 Then
       
        If (minX >= this.minX) and (minZ >= this.minZ) and (maxX <= CenterX) and (maxZ <= CenterZ) Then ''Upper Left
            'Is Splitable?
            If this.IsSplit=0 then this.Split()
            this.Node(0) -> AddObj(MyOBJ)
            Exit Sub
        End If
       
        If (minX >= CenterX) and (minZ >= this.minZ) and (maxX <= this.maxX) and (maxZ <= CenterZ) Then ''Upper Right
            'Is Splitable?
            If this.IsSplit=0 then this.Split()
            this.Node(1) -> AddObj(MyOBJ)
            Exit Sub
        End If
               
        If (minX >= this.minX) and (minZ >= CenterZ) and (maxX <= CenterX) and (maxZ <= this.maxZ) Then ''Bottom Left
            'Is Splitable?
            If this.IsSplit=0 then this.Split()
            this.Node(2) -> AddObj(MyOBJ)
            Exit Sub
        End If

        If (minX >= CenterX) and (minZ >= CenterZ) and (maxX <= this.maxX) and (maxZ <= this.maxZ) Then ''Bottom Right
            'Is Splitable?
            If this.IsSplit=0 then this.Split()
            this.Node(3) -> AddObj(MyOBJ)
            Exit Sub
        End If
       
        End If
        'Store it here!
        Temp = reallocate(this.Objects,this.OBJ_Count+1)
        this.Objects = Temp
       
        this.Objects[this.OBJ_Count] = MyOBJ
        this.OBJ_Count += 1
        Exit Sub
   
   
    End If
    CMsg "Not Stored!"
End Sub

Sub test_QuadTree.Draw()
    'Debugline
    line (this.minX, this.minZ) - (this.maxX, this.maxZ), &hFF909090, B
   
    If this.OBJ_Count Then
        for i as integer=0 to this.OBJ_Count-1
            line (this.Objects[i] -> minX, this.Objects[i] -> minZ) - (this.Objects[i] -> maxX, this.Objects[i] -> maxZ), this.Objects[i] -> Color, BF
        next i
    End If
   
    If this.IsSplit Then
        this.Node(0) -> Draw()
        this.Node(1) -> Draw()
        this.Node(2) -> Draw()
        this.Node(3) -> Draw()
    End If
End Sub




''''Testit
Randomize Timer
screen 19,32

Dim TestBaum as test_QuadTree
TestBaum.minX=0 : TestBaum.maxX=799
TestBaum.minZ=0 : TestBaum.maxZ=599

Dim testObjects as OBJList ptr
testObjects = new OBJList [50]

Dim rndStartX as integer
Dim rndStartY as integer
Dim rndSize   as integer
Dim rndColor  as Integer

for i as integer=0 to 49

    rndStartX = rnd * 800
    rndStartY = rnd * 600
    rndSize   = rnd * 50
    rndColor  = rnd * &hFFFFFF
   
    If (rndStartX+rndSize) > 799 Then rndStartX -= rndSize
    If (rndStartY+rndSize) > 599 Then rndStartY -= rndSize
   
    testObjects[i].minX  = rndStartX
    testObjects[i].minZ  = rndStartY
    testObjects[i].maxX  = rndStartX+rndSize
    testObjects[i].maxZ  = rndStartY+rndSize
    testObjects[i].Color = rndColor

    TestBaum.AddObj (@testObjects[i])
next i



TestBaum.Draw()
   

sleep

_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
MisterD



Anmeldungsdatum: 10.09.2004
Beiträge: 3071
Wohnort: bei Darmstadt

BeitragVerfasst am: 19.05.2012, 18:52    Titel: Antworten mit Zitat

so ganz spontan: (@testObjects[i]) ist das äquivalent zu (@(testObjects[i])) oder ((@testObjects)[i])?

ansonsten als idee: kriegst du zufällig vllt n speicherüberlauf wenn du in deinen baum zwei objekte mit identischen koordinaten steckst weil er dann endlos splitted oder sowas?

wenn alles nix hilft: a) debuggen oder b) (besser) ordentliche testcases schreiben.
_________________
"It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 20.05.2012, 14:30    Titel: Antworten mit Zitat

Ne das mit der Übergabe war schon richtig so da es eine 'ptr ptr' war und das mit dem endlos splitten hatte ich schon mit der maxsplit verhindert das es sich nur 4 bzw 3 mal teilt wobei gleiche koordinaten gar kein problem darstellen sondern einfach hinein gespeichert werden unabhängig ob an selber stelle schon was ist oder nicht...

Wo hier das problem liegt weiss ich leider immernoch nicht genau, hab das ganze gestern abend nochmal komplett neu geschrieben und funktioniert nun tadellos (getestet mit mehreren 100000 Objekten)

Ein einziges 'Gedankenproblem' das mir aber aufgekommen ist, wenn ich zB ein Objekt habe das sich wegen seiner grösse und koordinaten in einen übergeordneteten Node speichert der später evtl wegen des Frustums 'ignoriert' wird obwohl er grösstenteils in den tieferen Nodes 'zu sehen' ist...
Dieser wird obwohl ich dann evtl quasi direkt davor stehe nicht gezeichnet und somit nicht sichtbar sein obwohl er ja an dieser stelle sein soll?!

Weiss dazu leider noch keine Lösung...
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
MisterD



Anmeldungsdatum: 10.09.2004
Beiträge: 3071
Wohnort: bei Darmstadt

BeitragVerfasst am: 20.05.2012, 16:55    Titel: Antworten mit Zitat

trag ein objekt einfach in jedem blatt ein in dem es drin liegt, nicht in den zwischenknoten.
_________________
"It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 20.05.2012, 17:28    Titel: Antworten mit Zitat

Wäre wohl eine möglichkeit,
gerade noch hab ich getestet ob mein Problem nicht schon behoben würde wenn ich jedes Node mit allen Objekten zeichne das nur 'teilweise' in meiner Kamera zu sehen ist aber da hab ich das grosse problem das ich grössere objekte die sich zB im obersten node befinden gar nicht mehr sehe da es aufgrund meiner kamera grösse eigentlich nie gezeichnet wird...

riskiere ich mit der Möglichkeit nicht aber auch das ich Objekte mehrfach zeichne?

kleines Beispiel zum rumspielen zwinkern
Code:

Sub CMsg (byval Msg as String)
    Dim FF as integer
    FF = FreeFile
    Open CONS for Output as #FF
    print #FF, Msg
    Close #FF
End Sub

Const MaxDepth as Integer = 4

Type Object_
    minx as single
    minz as single
    maxx as single
    maxz as single
    col  as integer
end type

Type Quadtree
    Declare Constructor()
    Declare Constructor(minX as single, minZ as single, maxX as single, maxZ as single, D as UByte = 0)
   
    QT_minX as single
    QT_minZ as single
    QT_maxX as single
    QT_maxZ as single
   
    Node(0 to 3) as Quadtree ptr
   
    Declare Sub Split()
    Declare Sub Draw(viewminx as single, viewminz as single, viewmaxx as single, viewmaxz as single)
   
    IsSplit as UByte
    Depth   as UByte
   
    Declare Sub AddObject(Objptr as Object_ ptr)
   
    Objects  as Object_ ptr ptr
    ObjCount as Integer
End Type

Constructor Quadtree()
    this.QT_minX = 0 : this.QT_minZ = 0
    this.QT_maxX = 0 : this.QT_maxZ = 0
    this.IsSplit = 0 : ObjCount = 0 : Depth = 0
End Constructor

Constructor Quadtree(minX as single, minZ as single, maxX as single, maxZ as single, D as UByte = 0)
    this.QT_minX = minX : this.QT_minZ = minZ
    this.QT_maxX = maxX : this.QT_maxZ = maxZ
    this.IsSplit = 0    : ObjCount = 0
    this.Depth   = D
   
    'CMsg "Node created"
    'CMsg str(this.QT_minX)+","+str(this.QT_minZ)
    'CMsg str(this.QT_maxX)+","+str(this.QT_maxZ)
End Constructor

Sub Quadtree.Split()
    Dim CenterX as single
    Dim CenterZ as single
   
    CenterX = this.QT_minX + ((this.QT_maxX - this.QT_minX) / 2)
    CenterZ = this.QT_minZ + ((this.QT_maxZ - this.QT_minZ) / 2)
   
    Node(0) = NEW Quadtree
    *Node(0) = type(this.QT_minX, this.QT_minZ, CenterX, CenterZ, this.Depth+1)
   
    Node(1) = NEW Quadtree
    *Node(1) = type(CenterX, this.QT_minZ, this.QT_maxX, CenterZ, this.Depth+1)
   
    Node(2) = NEW Quadtree
    *Node(2) = type(this.QT_minX, CenterZ, CenterX, this.QT_maxZ, this.Depth+1)
   
    Node(3) = NEW Quadtree
    *Node(3) = type(CenterX, CenterZ, this.QT_maxX, this.QT_MaxZ, this.Depth+1)
   
    this.IsSplit = 1
End Sub

Sub Quadtree.AddObject(Objptr as Object_ ptr)
    Dim CenterX as single
    Dim CenterZ as single
   
    CenterX = this.QT_minX + ((this.QT_maxX - this.QT_minX) / 2)
    CenterZ = this.QT_minZ + ((this.QT_maxZ - this.QT_minZ) / 2)
   
    Dim Temp as any ptr
   
    ''Main
    If ((Objptr -> minx) >= this.QT_minX) and ((Objptr -> minz) >= this.QT_minZ) and _
       ((Objptr -> maxx) <= this.QT_maxX) and ((Objptr -> maxz) <= this.QT_maxZ) Then
       
        If (this.Depth < MaxDepth) Then
           
            ''Upper left
            If ((Objptr -> minx) >= this.QT_minX) and ((Objptr -> minz) >= this.QT_minZ) and _
               ((Objptr -> maxx) <= CenterX) and ((Objptr -> maxz) <= CenterZ) Then
           
               If (this.IsSplit = 0) Then this.Split()
               this.Node(0) -> AddObject(Objptr)
               Exit Sub
            End If
           
            ''Upper right
            If ((Objptr -> minx) >= CenterX) and ((Objptr -> minz) >= this.QT_minZ) and _
               ((Objptr -> maxx) <= this.QT_maxX) and ((Objptr -> maxz) <= CenterZ) Then
           
               If (this.IsSplit = 0) Then this.Split()
               this.Node(1) -> AddObject(Objptr)
               Exit Sub
            End If
       
            ''Bottom left
            If ((Objptr -> minx) >= this.QT_minX) and ((Objptr -> minz) >= CenterZ) and _
               ((Objptr -> maxx) <= CenterX) and ((Objptr -> maxz) <= this.QT_maxZ) Then
           
               If (this.IsSplit = 0) Then this.Split()
               this.Node(2) -> AddObject(Objptr)
               Exit Sub
            End If

            ''Bottom right
            If ((Objptr -> minx) >= CenterX) and ((Objptr -> minz) >= CenterZ) and _
               ((Objptr -> maxx) <= this.QT_maxX) and ((Objptr -> maxz) <= this.QT_maxZ) Then
           
               If (this.IsSplit = 0) Then this.Split()
               this.Node(3) -> AddObject(Objptr)
               Exit Sub
            End If
        End If
       
        Temp = reallocate (Objects, (this.ObjCount+1)*4)
        Objects = Temp
       
        Objects[ObjCount] = Objptr
       
        this.ObjCount += 1
        CMsg "Object stored : bounding box("+str(Objptr -> minx)+","+str(Objptr -> minz)+")-("+str(Objptr -> maxx)+","+str(Objptr -> maxz)+")"
        Exit Sub
    End If
    CMsg "Object not stored : bounding box("+str(Objptr -> minx)+","+str(Objptr -> minz)+")-("+str(Objptr -> maxx)+","+str(Objptr -> maxz)+")"
End Sub

Function IsIn(x as single, z as single, minx as single, minz as single, maxx as single, maxz as single) as integer
    If (x >= minx) and (z >= minz) and (x <= maxx) and (z <= maxz) then return 1
   
    return 0
End Function
   

Sub Quadtree.Draw(viewminx as single, viewminz as single, viewmaxx as single, viewmaxz as single)
   
    If IsIn(this.QT_minX,this.QT_minZ,viewminx,viewminz,viewmaxx,viewmaxz)=1 or _
       IsIn(this.QT_maxX,this.QT_minZ,viewminx,viewminz,viewmaxx,viewmaxz)=1 or _
       IsIn(this.QT_minX,this.QT_maxZ,viewminx,viewminz,viewmaxx,viewmaxz)=1 or _
       IsIn(this.QT_maxX,this.QT_maxZ,viewminx,viewminz,viewmaxx,viewmaxz)=1 Then
   
   
    If (this.ObjCount > 0) Then
        'debug line
        line (this.QT_minX, this.QT_minZ) - (this.QT_maxX, this.QT_maxZ), &hFF909090, B
       
        for i as integer=0 to this.ObjCount-1
            line (this.Objects[i] -> minx, this.Objects[i] -> minz) - (this.Objects[i] -> maxx, this.Objects[i] -> maxz), this.Objects[i] -> col, BF
        next i
    End If
   
    End If

    If (this.IsSplit > 0) Then
        this.Node(0) -> Draw(viewminx, viewminz, viewmaxx, viewmaxz)
        this.Node(1) -> Draw(viewminx, viewminz, viewmaxx, viewmaxz)
        this.Node(2) -> Draw(viewminx, viewminz, viewmaxx, viewmaxz)
        this.Node(3) -> Draw(viewminx, viewminz, viewmaxx, viewmaxz)
    End If
End Sub

Randomize Timer
screen 19,32

Dim MyTree as Quadtree ptr = new Quadtree
*MyTree = type(0,0,800,600)

Dim TestOBJ as Object_ ptr ptr
TestOBJ = callocate(100*4)

Dim as Integer rndStartX, rndStartZ, rndSize, rndColor

for i as integer=0 to 99
    rndStartX = rnd * 800
    rndStartZ = rnd * 600
    rndSize   = rnd * 150
    rndColor  = rnd * &hFFFFFF
         
    TestOBJ[i] = new Object_
    TestOBJ[i] -> minx = rndStartX
    TestOBJ[i] -> minz = rndStartZ
    TestOBJ[i] -> maxx = rndStartX + rndSize
    TestOBJ[i] -> maxz = rndStartZ + rndSize
    TestOBJ[i] -> col  = rndColor
   
    MyTree -> AddObject(TestOBJ[i])
next i

Dim as Integer MouseX, MouseY
Dim as single vminX, vminZ, vmaxX, vmaxZ
Dim switchcam as integer

Do
    getmouse MouseX, MouseY
   
    If switchcam=0 then
        vminX=MouseX-100 : if vminX<0 then vminX=0
        vminZ=MouseY-100 : if vminZ<0 then vminZ=0
   
        vmaxX=MouseX+100 : if vmaxX>799 then vmaxX=799
        vmaxZ=MouseY+100 : if vmaxZ>599 then vmaxZ=599
    else
        vminX=0 : vmaxX=800
        vminZ=0 : vmaxZ=600
    end if
   
   
    If multikey(&h3B) Then
        if switchcam=0 then
            switchcam=1
        Else
            switchcam=0
        end if
        while multikey(&h3B):wend
    end if
   
   
    screenlock
        cls
        MyTree -> Draw(vminX,vminZ,vmaxX,vmaxZ)
        line (vminX,vminZ) - (vmaxX, vmaxZ), &hFF333333, B
    screenunlock
   
    sleep 1   
Loop until multikey(&h01)


sleep

_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 20.05.2012, 20:43    Titel: Antworten mit Zitat

Quadtree die Dritte grinsen

Objecte in jeden Node zu speichern den es schneidet scheint mir tatsächlich sinnvoll, jedenfalls was die bisherigen Probleme angeht sieht es nun ganz gut aus, aber ich glaube immernoch das einiges nun genau deswegen mehrfach gezeichnet wird...

Code:

Sub CMsg (byval Msg as String)
    Dim FF as integer
    FF = FreeFile
    Open CONS for Output as #FF
    print #FF, Msg
    Close #FF
End Sub


Const MaxQuadDepth as Integer = 6
Type vec2
    X as single
    Z as single
End Type

Type testobj
    min as vec2
    max as vec2
    col as integer
End Type


''Quelle: http://www.back-side.net/codingrects.html
Function QuadIntersection(Q1Start as vec2, Q1Len as vec2, Q2Start as vec2, Q2Len as vec2) As Integer
    Dim as Integer xl, zo, xr, zu 'Eckpunkte des umschriebenen Rechtecks: (xl,yo)-(xr-1,yu-1)

    'Bestimmen der Eckpunktkoordinaten
    xl = Q1Start.X           'links
    zo = Q1Start.Z           'oben
    xr = Q2Start.X + Q2Len.X 'rechts + 1
    zu = Q2Start.Z + Q2Len.Z 'unten  + 1
   
    If Q2Start.X < Q1Start.X Then xl = Q2Start.X
    If Q2Start.Z < Q1Start.Z Then zo = Q2Start.Z
   
    If (Q1Start.X + Q1Len.X) > (Q2Start.X + Q2Len.X) Then xr = Q1Start.X + Q1Len.X
    If (Q1Start.Z + Q1Len.Z) > (Q2Start.Z + Q2Len.Z) Then zu = Q1Start.Z + Q1Len.Z

    'Prüfen auf Kollision
    If ((Q1Len.X + Q2Len.X) > (xr - xl)) And ((Q1Len.Z + Q2Len.Z) > (zu - zo)) Then Return 1
    Return 0
End Function

''Quadtree
Type Quadtree
    Declare Constructor()
    Declare Constructor(lo as vec2, hi as vec2, QuadDepth as Integer = 0)
   
    Bound_lo      as vec2
    Bound_hi      as vec2
    Center        as vec2
   
    IsSplit       as Integer
    Declare Function Split() as Integer
   
    QuadDepth     as Integer
    Nodes(0 to 3) as Quadtree ptr
   
    Declare Function AddObject(objdata as testobj ptr) as integer
   
    Objects_Count as Integer
    Objects_Data  as testobj ptr ptr
   
    Declare Function Draw(min as vec2, max as vec2) as Integer
End Type

Constructor Quadtree()
    this.Bound_lo      = type(0,0)
    this.Bound_hi      = type(0,0)
    this.Center        = type(0,0)
    this.QuadDepth     = 0
    this.Objects_Count = 0
    this.IsSplit       = 0
End Constructor
   
Constructor Quadtree(lo as vec2, hi as vec2, QuadDepth as Integer = 0)
    this.Bound_lo      = lo
    this.Bound_hi      = hi
    ''2D test!
        this.Center    = Type( lo.X + ((hi.X - lo.X) / 2), lo.Z + ((hi.Z - lo.Z) / 2) )
    ''3D
        'this.Center.X =
        'this.Center.Z =
    this.QuadDepth     = QuadDepth
    this.Objects_Count = 0
    this.IsSplit       = 0
End Constructor

Function Quadtree.Split() as Integer
    If (this.IsSplit = 1) or (this.QuadDepth = MaxQuadDepth) Then Return 0
   
    'Upper Left
    this.Nodes(0)  = NEW Quadtree
    *this.Nodes(0) = Type<Quadtree>( type<vec2>(this.Bound_lo.X, this.Bound_lo.Z), type<vec2>(this.Center.X, this.Center.Z)    , this.QuadDepth+1)

    'Upper Right
    this.Nodes(1)  = NEW Quadtree
    *this.Nodes(1) = Type<Quadtree>( type<vec2>(this.Center.X, this.Bound_lo.Z)  , type<vec2>(this.Bound_hi.X, this.Center.Z)  , this.QuadDepth+1)

    'Bottom Left
    this.Nodes(2)  = NEW Quadtree
    *this.Nodes(2) = Type<Quadtree>( type<vec2>(this.Bound_lo.X, this.Center.Z)  , type<vec2>(this.Center.X, this.Bound_hi.Z)  , this.QuadDepth+1)

    'Bottom Right
    this.Nodes(3)  = NEW Quadtree
    *this.Nodes(3) = Type<Quadtree>( type<vec2>(this.Center.X, this.Center.Z)    , type<vec2>(this.Bound_hi.X, this.Bound_hi.Z), this.QuadDepth+1)
 
    this.IsSplit = 1
    CMsg "Splitted :"+str(QuadDepth+1)
    Return 1
End Function

Function Quadtree.AddObject(objdata as testobj ptr) as Integer
   
    Dim QuadLen as vec2
    Dim ObjLen  as vec2
    QuadLen = type<vec2>(this.Bound_hi.X - this.Bound_lo.X , this.Bound_hi.Z - this.Bound_lo.Z)
    ObjLen  = type<vec2>((objdata -> max.X) - (objdata -> min.X) , (objdata -> max.Z) - (objdata -> min.Z))
   
    Dim Temp as any ptr
   
    If QuadIntersection(this.Bound_lo, QuadLen, (objdata -> min), ObjLen) = 1 Then
        Temp = reallocate(this.Objects_Data, (this.Objects_Count+1)*4)
        this.Objects_Data=Temp
        this.Objects_Data[this.Objects_Count] = objdata
        this.Objects_Count += 1
       
        If this.IsSplit=1 or this.Split()=1 then
            this.Nodes(0) -> AddObject(objdata)
            this.Nodes(1) -> AddObject(objdata)
            this.Nodes(2) -> AddObject(objdata)
            this.Nodes(3) -> AddObject(objdata)
        End If
       
        CMsg "Object Stored"
    End If
   
    return 0
End Function

Function Quadtree.Draw(min as vec2, max as vec2) as integer
    If this.Bound_lo.X>min.X and this.Bound_lo.Z>min.Z and this.Bound_hi.X<max.X and this.Bound_hi.Z<max.Z and this.Objects_Count>0 Then
       
        for i as integer=0 to this.Objects_Count-1
            line (this.Objects_Data[i] -> min.X, this.Objects_Data[i] -> min.Z) - _
                 (this.Objects_Data[i] -> max.X, this.Objects_Data[i] -> max.Z), this.Objects_Data[i] -> col, BF
        next i
       
        'debugline
        line (this.Bound_lo.X,this.Bound_lo.Z)-(this.Bound_hi.X,this.Bound_hi.Z),&hFF999999, B
    End If         
   
        If this.IsSplit = 1 Then
            this.Nodes(0) -> Draw(min,max)
            this.Nodes(1) -> Draw(min,max)
            this.Nodes(2) -> Draw(min,max)
            this.Nodes(3) -> Draw(min,max)
        End If
   
    Return 0
End Function   
'---------------------'
'test Quadtree

Randomize Timer
screen 19,32

Dim MyTree as Quadtree ptr = new Quadtree
*MyTree = type<Quadtree>(type<vec2>(0,0),type<vec2>(800,600))

Dim TestOBJ as testobj ptr ptr
TestOBJ = callocate(100*4)

Dim as Integer rndStartX, rndStartZ, rndSize, rndColor

for i as integer=0 to 99
    rndStartX = rnd * 800
    rndStartZ = rnd * 600
    rndSize   = rnd * 150
    rndColor  = rnd * &hFFFFFF
         
    TestOBJ[i] = new testobj
    TestOBJ[i] -> min = type<vec2>(rndStartX,rndStartZ)
    TestOBJ[i] -> max = type<vec2>(rndStartX + rndSize, rndStartZ + rndSize)
    TestOBJ[i] -> col  = rndColor
   
    MyTree -> AddObject(TestOBJ[i])
next i
CMsg "Done"

Dim as Integer MouseX, MouseY
Dim as single vminX, vminZ, vmaxX, vmaxZ
Dim switchcam as integer

Do
    getmouse MouseX, MouseY
   
    If switchcam=0 then
        vminX=MouseX-100 : if vminX<0 then vminX=0
        vminZ=MouseY-100 : if vminZ<0 then vminZ=0
   
        vmaxX=MouseX+100 : if vmaxX>799 then vmaxX=799
        vmaxZ=MouseY+100 : if vmaxZ>599 then vmaxZ=599
    else
        vminX=0 : vmaxX=800
        vminZ=0 : vmaxZ=600
    end if
   
   
    If multikey(&h3B) Then
        if switchcam=0 then
            switchcam=1
        Else
            switchcam=0
        end if
        while multikey(&h3B):wend
    end if
   
   
    screenlock
        cls
        MyTree -> Draw(type<vec2>(vminX,vminZ),type<vec2>(vmaxX,vmaxZ))
        line (vminX,vminZ) - (vmaxX, vmaxZ), &hFF333333, B
    screenunlock
   
    sleep 1   
Loop until multikey(&h01)


Edit: glaube aber eine Lösung dafür zu haben, wenn ich jeden hinzugefügten Objekt eine ID verpasse und vor dem Zeichnen Prüfe ob dieses nicht bereits gezeichnet wurde... mal sehen ob das so geht wie ich mir das vorstelle...
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 21.05.2012, 00:20    Titel: Antworten mit Zitat

Sorry für den Doppelpost

Ich schätze ich hab den eigentlich Sinn eines Quadtrees inzwischen ziemlich verunstaltet, da ich objekte nun nur noch auf der tiefsten schnittebende Speicher, dann aber bei grossen Objekten immernoch auf mehreren...



In Diesem Image kann man meine imaginäre Kamera am grossen Rahmen erkennen, das Objekt hier Grün wird mir in all den 6 Nodes das es schneidet auch 6 mal gezeichnet.

Die Idee mit einer ID hab ich leider nicht hinbekommen.

Wie kann ich das verhindern das er mir das gleiche Objekt mehrfach zeichnet?!

Das ganze würde wenn das Grüne viereck bspw. ein Haus oder dergleichen im 3D Raum wär etwas blöd werden

In den meisten Quadtree beispielen und tutorials soll man dann die objekte entlang der schnittlinie 'teilen/trennen' das allerdings würde ich sehr gern vermeiden... mit den vierecken wär das ja noch leicht machbar, aber wenn dieses dann ein 3D objekt sein soll wird es doch etwas komplizierter.. zumal ich vorhabe die objekte per VBO sich selbst rendern zu lassen...
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 21.05.2012, 04:20    Titel: Antworten mit Zitat

wir wärs mit einem "HasDraw"? grinsen

http://ops.ath.cx/code?id=241


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
XOR



Anmeldungsdatum: 23.07.2010
Beiträge: 161

BeitragVerfasst am: 21.05.2012, 15:56    Titel: Antworten mit Zitat

aufgefallen ist mir:
1) man sollte ein node erst dann teilen, wenn die anzahl der objekte in ihm eine bestimmte anzahl übersteigen.
2) ist ein node geteilt, muss es nicht mehr die objekte speichern, da das die untergeordneten nods machen.
3) ist ein node nicht im sichtbaren bereich, sind das die untergeordneten nodes auch nicht.
4) ist ein objekt bei deinem programm nur zum teil in einem node, so wird es nicht gezeichnet, wenn das node aber sichtbar ist.
5) keine speicherbereinigung!

die punkte habe ich verbessert:
Code:
Sub CMsg (ByVal Msg As String)
   Dim FF as integer
   FF = FreeFile
   Open CONS for Output as #FF
   print #FF, Msg
   Close #FF
End Sub


Const MaxQuadDepth As Integer = 8
Const NumberOfObjects As Integer = 1000
Const SplitWhenMoreThan As Integer = 3

Type vec2
   X As Single
   Z As Single
End Type

Type testobj
   min As vec2
   max As vec2
   col As Integer
   isDrawn As Integer
End Type


''Quelle: http://www.back-side.net/codingrects.html
Function QuadIntersection(Q1Start As vec2, Q1Len As vec2, Q2Start As vec2, Q2Len As vec2) As Integer
   Dim As Integer xl, zo, xr, zu 'Eckpunkte des umschriebenen Rechtecks: (xl,yo)-(xr-1,yu-1)

   'Bestimmen der Eckpunktkoordinaten
   xl = Q1Start.X           'links
   zo = Q1Start.Z           'oben
   xr = Q2Start.X + Q2Len.X 'rechts + 1
   zu = Q2Start.Z + Q2Len.Z 'unten  + 1

   If Q2Start.X < Q1Start.X Then xl = Q2Start.X
   If Q2Start.Z < Q1Start.Z Then zo = Q2Start.Z

   If (Q1Start.X + Q1Len.X) > (Q2Start.X + Q2Len.X) Then xr = Q1Start.X + Q1Len.X
   If (Q1Start.Z + Q1Len.Z) > (Q2Start.Z + Q2Len.Z) Then zu = Q1Start.Z + Q1Len.Z

   'Prüfen auf Kollision
   If ((Q1Len.X + Q2Len.X) > (xr - xl)) And ((Q1Len.Z + Q2Len.Z) > (zu - zo)) Then Return 1
   Return 0
End Function

''Quadtree
Type Quadtree
   Declare Constructor()
   Declare Constructor(lo As vec2, hi As vec2, QuadDepth As Integer = 0)
   Declare Destructor()

   Bound_lo      As vec2
   Bound_hi      As vec2
   Center        As vec2

   IsSplit       As Integer
   Declare Function Split() As Integer

   QuadDepth     As Integer
   Nodes(0 To 3) As Quadtree Ptr

   Declare Function AddObject(objdata As testobj Ptr) As Integer

   Objects_Count As Integer
   Objects_Data  As testobj Ptr Ptr

   Declare Function Draw(min As vec2, max As vec2) As Integer
End Type

Constructor Quadtree()
   this.Bound_lo      = Type(0,0)
   this.Bound_hi      = Type(0,0)
   this.Center        = Type(0,0)
   this.QuadDepth     = 0
   this.Objects_Count = 0
   this.IsSplit       = 0
End Constructor

Constructor Quadtree(lo As vec2, hi As vec2, QuadDepth As Integer = 0)
   this.Bound_lo      = lo
   this.Bound_hi      = hi
   ''2D test!
   this.Center    = Type( lo.X + ((hi.X - lo.X) / 2), lo.Z + ((hi.Z - lo.Z) / 2) )
   ''3D
   'this.Center.X =
   'this.Center.Z =
   this.QuadDepth     = QuadDepth
   this.Objects_Count = 0
   this.IsSplit       = 0
End Constructor

Destructor Quadtree()
   If(This.IsSplit)Then
      Delete This.Nodes(0)
      Delete This.Nodes(1)
      Delete This.Nodes(2)
      Delete This.Nodes(3)
   EndIf
   If(This.Objects_Data)Then DeAllocate(This.Objects_Data)
End Destructor

Function Quadtree.Split() As Integer
   If (this.IsSplit = 1) Or (this.QuadDepth = MaxQuadDepth) Then Return 0

   'Upper Left
   this.Nodes(0)  = New Quadtree( Type<vec2>(this.Bound_lo.X, this.Bound_lo.Z), Type<vec2>(this.Center.X, this.Center.Z)    , this.QuadDepth+1)
   '*this.Nodes(0) = Type<Quadtree>( Type<vec2>(this.Bound_lo.X, this.Bound_lo.Z), Type<vec2>(this.Center.X, this.Center.Z)    , this.QuadDepth+1)

   'Upper Right
   this.Nodes(1)  = New Quadtree( Type<vec2>(this.Center.X, this.Bound_lo.Z)  , Type<vec2>(this.Bound_hi.X, this.Center.Z)  , this.QuadDepth+1)
   '*this.Nodes(1) = Type<Quadtree>( Type<vec2>(this.Center.X, this.Bound_lo.Z)  , Type<vec2>(this.Bound_hi.X, this.Center.Z)  , this.QuadDepth+1)

   'Bottom Left
   this.Nodes(2)  = New Quadtree( Type<vec2>(this.Bound_lo.X, this.Center.Z)  , Type<vec2>(this.Center.X, this.Bound_hi.Z)  , this.QuadDepth+1)
   '*this.Nodes(2) = Type<Quadtree>( Type<vec2>(this.Bound_lo.X, this.Center.Z)  , Type<vec2>(this.Center.X, this.Bound_hi.Z)  , this.QuadDepth+1)

   'Bottom Right
   this.Nodes(3)  = New Quadtree( Type<vec2>(this.Center.X, this.Center.Z)    , Type<vec2>(this.Bound_hi.X, this.Bound_hi.Z), this.QuadDepth+1)
   '*this.Nodes(3) = Type<Quadtree>( Type<vec2>(this.Center.X, this.Center.Z)    , Type<vec2>(this.Bound_hi.X, this.Bound_hi.Z), this.QuadDepth+1)

   this.IsSplit = 1
   CMsg "Splitted :"+Str(QuadDepth+1)
   Return 1
End Function

Function Quadtree.AddObject(objdata As testobj Ptr) As Integer
   Dim QuadLen As vec2
   Dim ObjLen  As vec2
   QuadLen = Type<vec2>(this.Bound_hi.X - this.Bound_lo.X , this.Bound_hi.Z - this.Bound_lo.Z)
   ObjLen  = Type<vec2>((objdata -> max.X) - (objdata -> min.X) , (objdata -> max.Z) - (objdata -> min.Z))

   Dim Temp As Any Ptr

   If QuadIntersection(this.Bound_lo, QuadLen, (objdata -> min), ObjLen) = 1 Then
      If(this.IsSplit=1)Then
         this.Nodes(0) -> AddObject(objdata)
         this.Nodes(1) -> AddObject(objdata)
         this.Nodes(2) -> AddObject(objdata)
         this.Nodes(3) -> AddObject(objdata)
      Else
         If(this.Objects_Count >= SplitWhenMoreThan)Then
            If(this.Split())Then
               For i As Integer = 0 To this.Objects_Count-1
                  this.Nodes(0) -> AddObject(This.Objects_Data[i])
                  this.Nodes(1) -> AddObject(This.Objects_Data[i])
                  this.Nodes(2) -> AddObject(This.Objects_Data[i])
                  this.Nodes(3) -> AddObject(This.Objects_Data[i])
               Next i
               this.Objects_Count = 0
               If(This.Objects_Data)Then DeAllocate(This.Objects_Data)
               This.Objects_Data = 0
               this.Nodes(0) -> AddObject(objdata)
               this.Nodes(1) -> AddObject(objdata)
               this.Nodes(2) -> AddObject(objdata)
               this.Nodes(3) -> AddObject(objdata)
            Else
               this.Objects_Data = ReAllocate(this.Objects_Data, (this.Objects_Count+1)*4)
               this.Objects_Data[this.Objects_Count] = objdata
               this.Objects_Count += 1
               CMsg "Object Stored"
            EndIf
         Else
            this.Objects_Data = ReAllocate(this.Objects_Data, (this.Objects_Count+1)*4)
            this.Objects_Data[this.Objects_Count] = objdata
            this.Objects_Count += 1
            CMsg "Object Stored"
         EndIf
      EndIf
   EndIf

   Return 0
End Function

Function Quadtree.Draw(min As vec2, max As vec2) As Integer
   Dim QuadLen As vec2
   Dim ObjLen  As vec2
   QuadLen = Type<vec2>(this.Bound_hi.X - this.Bound_lo.X , this.Bound_hi.Z - this.Bound_lo.Z)
   ObjLen  = Type<vec2>((max.X) - (min.X) , (max.Z) - (min.Z))

   If QuadIntersection(this.Bound_lo, QuadLen, min, ObjLen) Then
      If this.IsSplit = 1 Then
         this.Nodes(0) -> Draw(min,max)
         this.Nodes(1) -> Draw(min,max)
         this.Nodes(2) -> Draw(min,max)
         this.Nodes(3) -> Draw(min,max)
      Else
         For i As Integer=0 To this.Objects_Count-1
            If(this.Objects_Data[i]->isDrawn = 0)Then
               Line (this.Objects_Data[i] -> min.X, this.Objects_Data[i] -> min.Z) - _
               (this.Objects_Data[i] -> max.X, this.Objects_Data[i] -> max.Z), this.Objects_Data[i] -> col, BF
               this.Objects_Data[i]->isDrawn = 1
            EndIf
         Next i
         'debugline
         Line (this.Bound_lo.X,this.Bound_lo.Z)-(this.Bound_hi.X,this.Bound_hi.Z),&hFF999999, B
      EndIf
   End If

   Return 0
End Function
'---------------------'
'test Quadtree

Randomize Timer
Screen 19,32

Dim MyTree As Quadtree Ptr = New Quadtree(Type<vec2>(0,0),Type<vec2>(800,600))
'*MyTree = Type<Quadtree>(Type<vec2>(0,0),Type<vec2>(800,600))

Dim TestOBJ As testobj Ptr Ptr
TestOBJ = Callocate(NumberOfObjects*4)

Dim As Integer rndStartX, rndStartZ, rndSize, rndColor

For i As Integer=0 To NumberOfObjects-1
   CMsg "Add Object"+Str(i)
   
   rndStartX = Rnd * 799
   rndStartZ = Rnd * 599
   rndSize   = Rnd * 25 + 5
   rndColor  = Rnd * &hFFFFFF

   TestOBJ[i] = New testobj
   TestOBJ[i] -> min = Type<vec2>(rndStartX,rndStartZ)
   TestOBJ[i] -> max = Type<vec2>(rndStartX + rndSize, rndStartZ + rndSize)
   TestOBJ[i] -> col  = rndColor
   TestOBJ[i] -> isDrawn = 0

   MyTree -> AddObject(TestOBJ[i])
Next i
CMsg "Done"

Dim As Integer MouseX, MouseY
Dim As Single vminX, vminZ, vmaxX, vmaxZ
Dim switchcam As Integer
Dim As Integer numDrawnObjects

Do
   GetMouse MouseX, MouseY

   If switchcam=0 Then
      vminX=MouseX-100 : If vminX<0 Then vminX=0
      vminZ=MouseY-100 : If vminZ<0 Then vminZ=0

      vmaxX=MouseX+100 : If vmaxX>799 Then vmaxX=799
      vmaxZ=MouseY+100 : If vmaxZ>599 Then vmaxZ=599
   Else
      vminX=0 : vmaxX=800
      vminZ=0 : vmaxZ=600
   End If


   If MultiKey(&h3B) Then
      If switchcam=0 Then
         switchcam=1
      Else
         switchcam=0
      End If
      While MultiKey(&h3B):Wend
   End If


   ScreenLock
   Cls
   MyTree -> Draw(Type<vec2>(vminX,vminZ),Type<vec2>(vmaxX,vmaxZ))
   Line (vminX,vminZ) - (vmaxX, vmaxZ), &hFF333333, B
   Locate 1,1
   Print numDrawnObjects
   ScreenUnLock

   numDrawnObjects = 0
   For i As Integer = 0 To NumberOfObjects-1
      If(TestOBJ[i] -> isDrawn = 1)Then
         numDrawnObjects+=1
      EndIf
      TestOBJ[i] -> isDrawn = 0
   Next

   Sleep 1
Loop Until MultiKey(&h01)

Delete MyTree
For i As Integer=0 To NumberOfObjects-1
   Delete TestOBJ[i]
Next i
DeAllocate(TestOBJ)

und das doppelt zeichnen habe ich auch mit der gleichen methode wie ThePuppetMaster behoben.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 21.05.2012, 19:35    Titel: Antworten mit Zitat

Zitat:

1) man sollte ein node erst dann teilen, wenn die anzahl der objekte in ihm eine bestimmte anzahl übersteigen.
2) ist ein node geteilt, muss es nicht mehr die objekte speichern, da das die untergeordneten nods machen.


Die Punkte entziehen sich meinem Verständnis ein bisschen...

Als zusatz hab ich noch gelesen das man keine Objekte im obersten Node der ja quasi die gesamte Welt/Bildschirm darstellt speichern...
Also muss ich ja immerhin EINMAL teilen bevor ich zu speichern anfange...
Warum sollte ich allerdings nun ein sehr kleines Objekt in ein sehr grosses Node speichern?!

Wenn ich nun dennoch punkt 1 und 2 berücksichtige, eleminiere ich nicht eigentlich einen mehrfachverweis von objekten?!
darf mir dann aber auch keine teilgrenze setzen und so lange teilen wie noch objekte 'eingelagert' werden?!?!

Zitat:

3) ist ein node nicht im sichtbaren bereich, sind das die untergeordneten nodes auch nicht.


Der punkt ist mir klar, hab mir mein eigenes Beispiel oben nicht mehr so genau angesehen, machte er bei meinen neuen Versuchen allerdings auch nicht

Mein Problem war noch, das ich probehalber aber gezeichnet habe wenn das node auch nur teilweise sichtbar war, was mir aber fatal schien
wenn ich zB auf die schnittpunkte in der mitte der ersten teilung bin, wurde mir da quasi fast die gesamte Welt gezeichnet...
Somit hab ich bei einem neuen Versuch eben Objekte in allen Nodes gespeichert die es schneidet anschliessend aber nur nodes gezeichnet die GANZ im sichtbereich sind,
was bei den oberen Nodes aber nie der fall sein würde, weshalb eben beim einlagern bis zur maximalen tiefe geteilt wird und in jedes entstandende Node das vom
Objekt geschnitten wurde auch den Verweis zum Objekt angegeben habe (was dann aber eben zu der unangenehmen mehrfachzeichung kam)
bzw. in meinem letzten versuch habe ich alle objekte ins lezte node verwiesen wärend aber die oberen nodes leer sind

was mich schon zu der Frage bewegt hat ob eine art Gitter Container nicht vielleicht die sinnvollere Wahl wäre...

Zitat:

4) ist ein objekt bei deinem programm nur zum teil in einem node, so wird es nicht gezeichnet, wenn das node aber sichtbar ist.


Sollte in meinem letzten Versuch eigentlich behoben sein.. alle GANZ sichtbaren Nodes zeichnet alle in sich enthaltenen Objekte...

Zitat:

5) keine speicherbereinigung!

Ich weiss, wollte ich hinzufügen wenn das ganze 'einsatzfähig' ist happy

Zitat:

und das doppelt zeichnen habe ich auch mit der gleichen methode wie ThePuppetMaster behoben.


Der Ansatz ansich gefällt mir sehr gut, löst in diesem Beispiel auch das Problem ist jedoch nicht sehr praktisch...

Hier im beispiel hab ich einfach ein paar zufalls objekte in einem grossen Pointer gestopft, das eigentlich ziel aber sollte später sein
das ich es ganz anders mache: zB so (Pseudo code)
Code:

Dim Welt as Quadtree

Dim Haus as 3DObjekt
Haus=Lade3DObjekt("Haus.3d")

Welt.Add(Haus,x,y,z)

Welt.Draw()


So oder so ähnlich. Jedenfalls wäre es sinnvoll könnte man das irgendwie in der Quadtree.Draw Function mit einbinden,
das man auf sowas in der Hauptschleife nachher nicht mehr achten müsste...


Hier nochmal mein eigener letzter Versuch von gestern Abend:
Code:

Sub CMsg (byval Msg as String)
    Dim FF as integer
    FF = FreeFile
    Open CONS for Output as #FF
    print #FF, Msg
    Close #FF
End Sub


Const MaxQuadDepth as Integer = 5
Type vec2
    X as single
    Z as single
End Type

Type testobj
    min as vec2
    max as vec2
    col as integer
    Declare Sub Draw()
End Type

Sub testobj.Draw()
    line (this.min.X, this.min.Z) - _
         (this.max.X, this.max.Z), this.col, BF
End Sub



''Quelle: http://www.back-side.net/codingrects.html
Function QuadIntersection(Q1Start as vec2, Q1Len as vec2, Q2Start as vec2, Q2Len as vec2) As Integer
    Dim as Integer xl, zo, xr, zu 'Eckpunkte des umschriebenen Rechtecks: (xl,yo)-(xr-1,yu-1)

    'Bestimmen der Eckpunktkoordinaten
    xl = Q1Start.X           'links
    zo = Q1Start.Z           'oben
    xr = Q2Start.X + Q2Len.X 'rechts + 1
    zu = Q2Start.Z + Q2Len.Z 'unten  + 1
   
    If Q2Start.X < Q1Start.X Then xl = Q2Start.X
    If Q2Start.Z < Q1Start.Z Then zo = Q2Start.Z
   
    If (Q1Start.X + Q1Len.X) > (Q2Start.X + Q2Len.X) Then xr = Q1Start.X + Q1Len.X
    If (Q1Start.Z + Q1Len.Z) > (Q2Start.Z + Q2Len.Z) Then zu = Q1Start.Z + Q1Len.Z

    'Prüfen auf Kollision
    If ((Q1Len.X + Q2Len.X) > (xr - xl)) And ((Q1Len.Z + Q2Len.Z) > (zu - zo)) Then Return 1
    Return 0
End Function

''Quadtree
Type Quadtree
    Declare Constructor()
    Declare Constructor(lo as vec2, hi as vec2, QuadDepth as Integer = 0)
   
    Bound_lo      as vec2
    Bound_hi      as vec2
    Center        as vec2
   
    IsSplit       as Integer
    Declare Function Split() as Integer
   
    QuadDepth     as Integer
    Nodes(0 to 3) as Quadtree ptr
   
    Declare Function AddObject(objdata as testobj ptr) as integer
   
    Objects_Count as Integer
    Objects_Data  as testobj ptr ptr
   
    Declare Function Draw(min as vec2, max as vec2) as Integer
End Type

Constructor Quadtree()
    this.Bound_lo      = type(0,0)
    this.Bound_hi      = type(0,0)
    this.Center        = type(0,0)
    this.QuadDepth     = 0
    this.Objects_Count = 0
    this.IsSplit       = 0
End Constructor
   
Constructor Quadtree(lo as vec2, hi as vec2, QuadDepth as Integer = 0)
    this.Bound_lo      = lo
    this.Bound_hi      = hi
    ''2D test!
        this.Center    = Type( lo.X + ((hi.X - lo.X) / 2), lo.Z + ((hi.Z - lo.Z) / 2) )
    ''3D
        'this.Center.X =
        'this.Center.Z =
    this.QuadDepth     = QuadDepth
    this.Objects_Count = 0
    this.IsSplit       = 0
End Constructor

Function Quadtree.Split() as Integer
    If (this.IsSplit = 1) or (this.QuadDepth = MaxQuadDepth) Then Return 0
   
    'Upper Left
    this.Nodes(0)  = NEW Quadtree
    *this.Nodes(0) = Type<Quadtree>( type<vec2>(this.Bound_lo.X, this.Bound_lo.Z), type<vec2>(this.Center.X, this.Center.Z)    , this.QuadDepth+1)

    'Upper Right
    this.Nodes(1)  = NEW Quadtree
    *this.Nodes(1) = Type<Quadtree>( type<vec2>(this.Center.X, this.Bound_lo.Z)  , type<vec2>(this.Bound_hi.X, this.Center.Z)  , this.QuadDepth+1)

    'Bottom Left
    this.Nodes(2)  = NEW Quadtree
    *this.Nodes(2) = Type<Quadtree>( type<vec2>(this.Bound_lo.X, this.Center.Z)  , type<vec2>(this.Center.X, this.Bound_hi.Z)  , this.QuadDepth+1)

    'Bottom Right
    this.Nodes(3)  = NEW Quadtree
    *this.Nodes(3) = Type<Quadtree>( type<vec2>(this.Center.X, this.Center.Z)    , type<vec2>(this.Bound_hi.X, this.Bound_hi.Z), this.QuadDepth+1)
 
    this.IsSplit = 1
    'CMsg "Splitted :"+str(QuadDepth+1)
    Return 1
End Function

Function Quadtree.AddObject(objdata as testobj ptr) as Integer
   
    Dim QuadLen(0 to 4) as vec2
    Dim ObjLen  as vec2
    QuadLen(0) = type<vec2>(this.Bound_hi.X - this.Bound_lo.X , this.Bound_hi.Z - this.Bound_lo.Z)
    ObjLen  = type<vec2>((objdata -> max.X) - (objdata -> min.X) , (objdata -> max.Z) - (objdata -> min.Z))
   
    Dim Temp as any ptr
    Dim NX as Integer
   
    If QuadIntersection(this.Bound_lo, QuadLen(0), (objdata -> min), ObjLen) = 1 Then
        If this.IsSplit=1 or this.Split()=1 then
           
            QuadLen(1) = type<vec2>( (this.Nodes(0) -> Bound_hi.X) - (this.Nodes(0) -> Bound_lo.X) , (this.Nodes(0) -> Bound_hi.Z) - (this.Nodes(0) -> Bound_lo.Z) )
            QuadLen(2) = type<vec2>( (this.Nodes(1) -> Bound_hi.X) - (this.Nodes(1) -> Bound_lo.X) , (this.Nodes(1) -> Bound_hi.Z) - (this.Nodes(1) -> Bound_lo.Z) )
            QuadLen(3) = type<vec2>( (this.Nodes(2) -> Bound_hi.X) - (this.Nodes(2) -> Bound_lo.X) , (this.Nodes(2) -> Bound_hi.Z) - (this.Nodes(2) -> Bound_lo.Z) )
            QuadLen(4) = type<vec2>( (this.Nodes(3) -> Bound_hi.X) - (this.Nodes(3) -> Bound_lo.X) , (this.Nodes(3) -> Bound_hi.Z) - (this.Nodes(3) -> Bound_lo.Z) )

            If QuadIntersection(this.Nodes(0) -> Bound_lo, QuadLen(1), (objdata -> min), ObjLen) = 1 Then NX+=&b1000
            If QuadIntersection(this.Nodes(1) -> Bound_lo, QuadLen(2), (objdata -> min), ObjLen) = 1 Then NX+=&b0100
            If QuadIntersection(this.Nodes(2) -> Bound_lo, QuadLen(3), (objdata -> min), ObjLen) = 1 Then NX+=&b0010
            If QuadIntersection(this.Nodes(3) -> Bound_lo, QuadLen(4), (objdata -> min), ObjLen) = 1 Then NX+=&b0001
           
            If NX>0 Then
                If (NX >= &b1000) Then this.Nodes(0) -> AddObject(objdata)
                If (NX >= &b0100) Then this.Nodes(1) -> AddObject(objdata)
                If (NX >= &b0010) Then this.Nodes(2) -> AddObject(objdata)
                If (NX >= &b0001) Then this.Nodes(3) -> AddObject(objdata)
            End If
        Else
            Temp = reallocate(this.Objects_Data, (this.Objects_Count+1)*4)
            this.Objects_Data=Temp
            this.Objects_Data[this.Objects_Count] = objdata
            this.Objects_Count += 1
        End If
    End If
   
    return 0
End Function

Function Quadtree.Draw(min as vec2, max as vec2) as integer
    If this.Bound_lo.X>min.X and this.Bound_lo.Z>min.Z and this.Bound_hi.X<max.X and this.Bound_hi.Z<max.Z and this.Objects_Count>0 Then
       
        for i as integer=0 to this.Objects_Count-1
            this.Objects_Data[i] -> Draw()
            'line (this.Objects_Data[i] -> min.X, this.Objects_Data[i] -> min.Z) - _
            '     (this.Objects_Data[i] -> max.X, this.Objects_Data[i] -> max.Z), this.Objects_Data[i] -> col, BF
        next i
       
        'debugline
        line (this.Bound_lo.X,this.Bound_lo.Z)-(this.Bound_hi.X,this.Bound_hi.Z),&hFF999999, B
    End If                 
   
    If this.IsSplit = 1 Then
        this.Nodes(0) -> Draw(min,max)
        this.Nodes(1) -> Draw(min,max)
        this.Nodes(2) -> Draw(min,max)
        this.Nodes(3) -> Draw(min,max)
    End If
   
    Return 0
End Function   
'---------------------'
'test Quadtree

Randomize Timer
screen 19,32

Dim MyTree as Quadtree ptr = new Quadtree
*MyTree = type<Quadtree>(type<vec2>(0,0),type<vec2>(800,600))

Dim TOBJ as testobj ptr ptr
TOBJ = callocate(1000*4)

Dim as Integer rndStartX, rndStartZ, rndSize, rndColor

for i as integer=0 to 9
    rndStartX = rnd * 800
    rndStartZ = rnd * 600
    rndSize   = rnd * 150
    rndColor  = rnd * &hFFFFFF
         
    TOBJ[i] = new testobj
    TOBJ[i] -> min = type<vec2>(rndStartX,rndStartZ)
    TOBJ[i] -> max = type<vec2>(rndStartX + rndSize, rndStartZ + rndSize)
    TOBJ[i] -> col  = rndColor
   
    MyTree -> AddObject(TOBJ[i])
next i
CMsg "Done"

Dim as Integer MouseX, MouseY
Dim as single vminX, vminZ, vmaxX, vmaxZ
Dim switchcam as integer

Do
    getmouse MouseX, MouseY
   
    If switchcam=0 then
        vminX=MouseX-100 : if vminX<0 then vminX=0
        vminZ=MouseY-100 : if vminZ<0 then vminZ=0
   
        vmaxX=MouseX+100 : if vmaxX>799 then vmaxX=799
        vmaxZ=MouseY+100 : if vmaxZ>599 then vmaxZ=599
    else
        vminX=0 : vmaxX=800
        vminZ=0 : vmaxZ=600
    end if
   
   
    If multikey(&h3B) Then
        if switchcam=0 then
            switchcam=1
        Else
            switchcam=0
        end if
        while multikey(&h3B):wend
    end if
   
   
    screenlock
        cls
        MyTree -> Draw(type<vec2>(vminX,vminZ),type<vec2>(vmaxX,vmaxZ))
        line (vminX,vminZ) - (vmaxX, vmaxZ), &hFF333333, B
        'CMsg "-------------"
    screenunlock
   
    sleep 1
Loop until multikey(&h01)

_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 21.05.2012, 20:50    Titel: Antworten mit Zitat

das lässt sich durchaus auch im draw machen, wenn du darauf verzichtest, das Draw sich selbst rekrusiv aufruft. dan kannst du das "reset" nämlich im draw, nur für das obj. erledigen.

Das Rücksetzen wollte ich ursprünglich auch im draw machen, bis ich gesehen habe, wie du damit umgehst. .. wichtig ist einfach, das du dieses objekt nur 1x zurücksetzen, und nicht mehrfach und das ist eben obj. bezogen.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
XOR



Anmeldungsdatum: 23.07.2010
Beiträge: 161

BeitragVerfasst am: 21.05.2012, 21:15    Titel: Antworten mit Zitat

Zitat:

Zitat:
1) man sollte ein node erst dann teilen, wenn die anzahl der objekte in ihm eine bestimmte anzahl übersteigen.
2) ist ein node geteilt, muss es nicht mehr die objekte speichern, da das die untergeordneten nods machen.


Die Punkte entziehen sich meinem Verständnis ein bisschen...


Aufgabe des Quad- oder Octree ist es, die objekte, die nicht im sichtbereich sind, herauszufiltern. da es bei sehr vielen objekten lange braucht zu schauen ob jedes im sichtbereich liegt, benutzt man Quad- oder Octrees.
Wenn man nun die objekte in der baumstruktur hat, kann man schauen ob ein node sichtbar ist. ist das nicht der fall, sind die childs auch nicht sichtbar und es muss auch nicht geprüft werden. ist das node sichtbar, muss man auch bei den childes schauen ob sie sichtbar sind. wenn jetzt aber in einem child 8ten grades oder tiefer nun ein sehr kleines Objekt liegt, muss man alle übergeordneten nodes auf sichtbarkeit kontrollieren und das nur wegen dem einen kleinen Objekt. wenn man dieses nun aber zusammen mit 100 anderen in einem child, das näher am stamm liegt speichert kann es sein, das es gezeichnet wird, ohne das es im sichtbereich ist, aber das ist schneller. und man benutzt die Quad- oder Octree um möglichst schnell alles zu zeichnen.

Zitat:
Der punkt ist mir klar, hab mir mein eigenes Beispiel oben nicht mehr so genau angesehen, machte er bei meinen neuen Versuchen allerdings auch nicht

aber genau dadurch ist das ganze so schnell.

Zitat:
Sollte in meinem letzten Versuch eigentlich behoben sein.. alle GANZ sichtbaren Nodes zeichnet alle in sich enthaltenen Objekte...

aber auch die nur zum teil sichtbaren Nodes müssen gezeichnet werden.

Zitat:
Zitat:
und das doppelt zeichnen habe ich auch mit der gleichen methode wie ThePuppetMaster behoben.

Der Ansatz ansich gefällt mir sehr gut, löst in diesem Beispiel auch das Problem ist jedoch nicht sehr praktisch...

folgende idee: jeden frame wird ein counter um 1 erhöt. wird das objekt gezeichnet, so wird dessen variable "last drawn" die zahl vom counter zugewiesen. bevor das objekt gezeichnet wird schaut man also ob dessen last drawn ungleich dem counter ist und zeichnet dann.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 22.05.2012, 00:21    Titel: Antworten mit Zitat

Zitat:
ist das node sichtbar, muss man auch bei den childes schauen ob sie sichtbar sind.

Eigentlich mein ich gelesen zu haben, ist ein Node sichtbar, braucht man die Child Nodes nicht mehr zu prüfen,
denn logischerweise sind die 'kleineren' blätter ja dann auch sichtbar...
Anders ist es nun in meinem neusten Versuch, da ich Nodes auf TEILWEISE sichtbar prüfe, muss ich dann auch die Childs prüfen

Hab das Beispiel diesmal ein bisschen besser Dokumentiert,
Probleme stellen die schnittlinien dar...

In diesem Versuch speicher ich Objekte Ihrer Grösse nach, so kann es unter umständen sein das Objekte auch in der Wurzel gespeichert werden
was ich als 'Sonderfall sehe' (in der Regel hab ich nicht vor so grosse objekte zu nutzen)
In Diesem besonderen Fall wird jedes in der Wurzel befindliche Objekt auf sichtbarkeit geprüft...

Und wie gesagt, die schnittlinien, da objekte sich darauf befinden können, heisst es sie passen nicht im unterliegenden Node und werden daher eine Ebene
höher gespeichert und somit gelegentlich unnötig mehr objekte gezeichnet als nötig wäre...

ABER (VORTEIL!) keine mehrfachverweise und damit das verbundene Problem von mehrfach zeichnungen...

Obwohl mir die letzte Idee von Dir gefällt, hätte nun jedem Frame eine zufalls ID gegeben
welche ich wiederrum der gezeichneten Objekte übergebe, hat Objekt(X) diese ID wäre es schon
gezeichnet und könnte übersprungen werden...

Werd den Ansatz evtl auch nochmal ausprobieren.
Dieser hier gefällt mir nun aber auch schon ganz gut

Code:

Randomize Timer
Const AnzahlObjekte as Integer = 1200
Const QuadMaxDepth as Integer = 16


'' Diese Klasse ist nur zu testzwecken
Type ObjectData
    'Hält die Eckpunkte (bounding box) des Objekts fest
    Min_X as Integer
    Max_X as Integer
    Min_Y as Integer
    Max_Y as Integer
   
    col   as integer
    'Hier können später sonstige relevanten Daten eingefügt werden
    'sind für diesen Test aber nicht erforderlich
   
    'Zeichnet das Objekt
    Declare Sub Draw()
End Type

Sub ObjectData.Draw()
    with this
        line (.Min_X, .Min_Y) - (.Max_X, .Max_Y), .col, BF
    end with
End Sub


Function IfBoxKollision(BoxA_MinX as Integer, BoxA_MinY as Integer, BoxA_MaxX as Integer, BoxA_MaxY as Integer, _
                        BoxB_MinX as Integer, BoxB_MinY as Integer, BoxB_MaxX as Integer, BoxB_MaxY as Integer) as Integer
   
    Dim as Integer XLeft, YUp, XRight, YDown 'Eckpunkte des umschriebenen Rechtecks
    Dim as Integer BoxA_LenX, BoxA_LenY, BoxB_LenX, BoxB_LenY 'Seitenlänge beider Rechtecke
   
    'Seitenlänge der Boxen feststellen
    BoxA_LenX = BoxA_MaxX-BoxA_MinX
    BoxA_LenY = BoxA_MaxY-BoxA_MinY
    BoxB_LenX = BoxB_MaxX-BoxB_MinX
    BoxB_LenY = BoxB_MaxY-BoxB_MinY
   
    'Bestimmen der Eckpunktkoordinaten
    XLeft  = IIF(BoxA_MinX<BoxB_MinX, BoxA_MinX, BoxB_MinX)        'links
    YUp    = IIF(BoxA_MinY<BoxB_MinY, BoxA_MinY, BoxB_MinY)        'oben
    XRight = IIF(BoxA_MaxX>BoxB_MaxX, BoxA_MaxX, BoxB_MaxX)        'rechts
    YDown  = IIF(BoxA_MaxY>BoxB_MaxY, BoxA_MaxY, BoxB_MaxY)        'unten
   
    'Prüfen auf Kollision
    If ( (BoxA_LenX + BoxB_LenX) > (XRight - XLeft) ) And ( (BoxA_LenY + BoxB_LenY) > (YDown - YUp)) Then Return 1
    Return 0
End Function

'' Quadtree

Type Quadtree
    Declare Constructor()
    Declare Constructor(minx as Integer, miny as Integer, maxx as integer, maxy as integer)
   
    'Enthält die Eckpunkte des Node
    Min_X as Integer
    Max_X as Integer
    Min_Y as Integer
    Max_Y as Integer

    'Tiefe des Baums (0 = Wurzel)
    Depth as Integer
   
    'IsSplit: wurde bereits geteilt? (TRUE/FALSE)
    IsSplit as Integer
   
    'Enthält die 4 Child Nodes
    Node(0 to 3) as Quadtree ptr
   
    'Teilt das Node in 4 neue Child Nodes
    Declare Function Split() as Integer
   
    'Trägt einen Verweis eines Objekts in den Baum
    Declare Sub AddObject(NewObject as ObjectData ptr)
   
    'Enthält die Anzahl eingetragener Verweise zu Objekten
    Objects_Count as Integer
   
    'Liste der Verweise auf Objekte
    Objects_Data as ObjectData ptr ptr
   
    'Declare Sub Draw() ''Bei 3D wird die 'sichtbare Box' durch ein Frustum check ersetzt
    'Alle sichtbaren Nodes/Objekte im Baum zeichnen
    Declare Sub Draw(minx as integer, miny as integer, maxx as integer, maxy as integer)
End Type

Constructor Quadtree()
End Constructor

Constructor Quadtree(minx as Integer, miny as Integer, maxx as integer, maxy as integer)
    with this
        .Min_X = minx
        .Max_X = maxx
        .Min_Y = miny
        .Max_Y = maxy
    end with
End Constructor

Function Quadtree.Split() as Integer
    Dim as Integer CenterX, CenterY
    With this
        'Wenn Node bereits aufgeteilt ist ODER die maximale
        'Tiefe erreicht hat, nicht weiter aufteilen.
        If (.IsSplit = 1) or (Depth = QuadMaxDepth) Then Return 0
       
        'Mittelpunkt des Nodes ermitteln
        CenterX = (.Min_X + ((.Max_X - .Min_X) / 2) )
        CenterY = (.Min_Y + ((.Max_Y - .Min_Y) / 2) )
       
        '4 Child Nodes erstellen
       
        'links oben
        .Node(0) = NEW Quadtree
        'Eckpunkte
        .Node(0) -> Min_X = .Min_X
        .Node(0) -> Max_X = CenterX
        .Node(0) -> Min_Y = .Min_Y
        .Node(0) -> Max_Y = CenterY
        'Tiefe
        .Node(0) -> Depth = .Depth+1
       
        'recht oben
        .Node(1) = NEW Quadtree
        .Node(1) -> Min_X = CenterX
        .Node(1) -> Max_X = .Max_X
        .Node(1) -> Min_Y = .Min_Y
        .Node(1) -> Max_Y = CenterY
        'Tiefe
        .Node(1) -> Depth = .Depth+1
       
        'links unten
        .Node(2) = NEW Quadtree
        .Node(2) -> Min_X = .Min_X
        .Node(2) -> Max_X = CenterX
        .Node(2) -> Min_Y = CenterY
        .Node(2) -> Max_Y = .Max_Y
        'Tiefe
        .Node(2) -> Depth = .Depth+1
       
        'rechts unten
        .Node(3) = NEW Quadtree
        .Node(3) -> Min_X = CenterX
        .Node(3) -> Max_X = .Max_X
        .Node(3) -> Min_Y = CenterY
        .Node(3) -> Max_Y = .Max_Y
        'Tiefe
        .Node(3) -> Depth = .Depth+1
       
        'Festhalten das Node geteilt wurde
        .IsSplit = 1
    End With
    Return 1
End Function

Sub Quadtree.AddObject(NewObject as ObjectData ptr)
    Dim CenterX as Integer
    Dim CenterY as Integer
   
    Dim Temp as any ptr
   
    with this
        'Mittelpunkt des Nodes ermitteln
        CenterX = (.Min_X + ((.Max_X - .Min_X) / 2) )
        CenterY = (.Min_Y + ((.Max_Y - .Min_Y) / 2) )

        'Prüfen ob Node noch teilbar ist (QuadMaxDepth)
        If .Depth < QuadMaxDepth Then
           
           'Prüfen ob Object in einem tieferen Node passt
           
           'links oben?
           If ((NewObject -> Min_X) >= .Min_X ) and ((NewObject -> Min_Y) >= .Min_Y ) and _
              ((NewObject -> Max_X) <= CenterX) and ((NewObject -> Max_Y) <= CenterY) Then
               'Object passt eine Ebene tiefer, ins Node links oben!
               
               'Wenn Node noch nicht geteilt ist, dann jetzt teilen.
               If (.IsSplit = 0) Then .Split()
               
               'Objekt ins nächste Child Node übergeben.
               .Node(0) -> AddObject(NewObject)
               Exit Sub
           End If'elseif verwenden?
           
           ' rechts oben?
           If ((NewObject -> Min_X) >= CenterX) and ((NewObject -> Min_Y) >= .Min_Y ) and _
              ((NewObject -> Max_X) <= .Max_X ) and ((NewObject -> Max_Y) <= CenterY) Then
               'Object passt eine Ebene tiefer, ins Node links oben!
               
               'Wenn Node noch nicht geteilt ist, dann jetzt teilen.
               If (.IsSplit = 0) Then .Split()
               
               'Objekt ins nächste Child Node übergeben.
               .Node(1) -> AddObject(NewObject)
               Exit Sub
           End If
           
           ' links unten?
           If ((NewObject -> Min_X) >= .Min_X ) and ((NewObject -> Min_Y) >= CenterY) and _
              ((NewObject -> Max_X) <= CenterX) and ((NewObject -> Max_Y) <= .Max_Y ) Then
               'Object passt eine Ebene tiefer, ins Node links oben!
               
               'Wenn Node noch nicht geteilt ist, dann jetzt teilen.
               If (.IsSplit = 0) Then .Split()
               
               'Objekt ins nächste Child Node übergeben.
               .Node(2) -> AddObject(NewObject)
               Exit Sub
           End If
           
           ' rechts unten?
           If ((NewObject -> Min_X) >= CenterX) and ((NewObject -> Min_Y) >= CenterY) and _
              ((NewObject -> Max_X) <= .Max_X ) and ((NewObject -> Max_Y) <= .Max_Y ) Then
               'Object passt eine Ebene tiefer, ins Node links oben!
               
               'Wenn Node noch nicht geteilt ist, dann jetzt teilen.
               If (.IsSplit = 0) Then .Split()
               
               'Objekt ins nächste Child Node übergeben.
               .Node(3) -> AddObject(NewObject)
               Exit Sub
           End If
        End If
       
        'Objekt passt in keine tiefere Ebene oder maximale teilung ist erreicht
        'Objekt Verweis hier speichern
       
        Temp = reallocate (.Objects_Data, (.Objects_Count+1)*4) 'Speicher realloziieren
        .Objects_Data = Temp
        .Objects_Data[.Objects_Count] = NewObject           'Neuen Verweis eintragen
        .Objects_Count += 1                                 'Objektzähler um 1 erhöhen
    End With
End Sub

'Sub Quadtree.Draw()       
Sub Quadtree.Draw(minx as integer, miny as integer, maxx as integer, maxy as integer)
    with this
        'Sonderfall!
        'Objekte die, wegen ihrer grösser und/oder position nur in der
        'Wurzel passten, müssen einzeln auf Sichtbarkeit geprüft werden!
       
        'Schneidet dieses Node unseren Sichtbaren Bereich?
        If IfBoxKollision(.Min_X, .Min_Y, .Max_X, .Max_Y, _
                          minx, miny, maxx, maxy) = 1 Then
           
            If (.Objects_Count > 0) Then
                'Befinden wir uns in der Wurzel des Baums
                If (.Depth = 0) Then
                    'Jedes Objekt auf sichtbarkeit prüfen
                    for i as integer=0 to Objects_Count-1
                        If IfBoxKollision( (.Objects_Data[i] -> Min_X), (.Objects_Data[i] -> Min_Y), _
                                           (.Objects_Data[i] -> Max_X), (.Objects_Data[i] -> Max_Y), _
                                            minx, miny, maxx, maxy ) = 1 Then Objects_Data[i] -> Draw()
                    Next i
                Else
                    for i as integer=0 to Objects_Count-1
                        Objects_Data[i] -> Draw()
                    next i
                End If
               
                'Debugline
                line (.Min_X, .Min_Y) - (.Max_X, .Max_Y), &hFF999999, B
            End If               
               
            'Wenn Node geteilt dann untere Bäume Zeichnen
            If (.IsSplit=1) Then
                .Node(0) -> Draw(minx,miny,maxx,maxy)
                .Node(1) -> Draw(minx,miny,maxx,maxy)
                .Node(2) -> Draw(minx,miny,maxx,maxy)
                .Node(3) -> Draw(minx,miny,maxx,maxy)
            End If
        End If
    End with
End Sub       


''Screen
Screenres 800,600,32

''Welt/Quadtree
Dim Welt as Quadtree
Welt=Type<Quadtree>(0,0,800,600)

''Testobjekte erstellen
Dim as Integer rndStartX, rndStartY, rndSize, rndCol
Dim testobjekte as ObjectData ptr ptr
testobjekte=callocate(AnzahlObjekte*4)

'Dim as Integer XS, YS
for i as integer=0 to AnzahlObjekte-1
    'rndStartX = rnd * 800
    'rndStartY = rnd * 600
    rndSize   = 18'rnd * 50
   
    rndCol    = rnd * &hFFFFFF
   
    testobjekte[i] = NEW ObjectData
    testobjekte[i] -> Min_X = rndStartX
    testobjekte[i] -> Min_Y = rndStartY
    testobjekte[i] -> Max_X = rndStartX+rndSize
    testobjekte[i] -> Max_Y = rndStartY+rndSize
    testobjekte[i] -> col   = rndcol
   
    Welt.AddObject(testobjekte[i])
   
    rndStartX += 20 : if (rndStartX > 799) Then rndStartY += 20 : rndStartX = 0
next i

Dim as Integer MouseX, MouseY
Dim as Integer vminX, vminY, vmaxX, vmaxY

do
    getmouse MouseX, MouseY
   
    vminX=MouseX-100 : if vminX<0 then vminX=0
    vminY=MouseY-100 : if vminY<0 then vminY=0
   
    vmaxX=MouseX+100 : if vmaxX>799 then vmaxX=799
    vmaxY=MouseY+100 : if vmaxY>599 then vmaxY=599   
   
    screenlock
        cls
        Welt.Draw(vminX,vminY,vmaxX,vmaxY)
       
        line (vminX,vminY) - (vmaxX, vmaxY), &hFF333333, B
    screenunlock   
   
    sleep 1
loop until multikey(&h01)


Edit: bekam gerade ein Fehler als ich die Zeile
Code:
rndCol = rnd * &hFFFFFF

zu dieser
Code:
rndCol = &hFF0000

geändert habe, mit dem ich irgendwie nichts anfangen kann...

Zitat:

D:\FreeBASIC\lib/libfb.a(math_rnd.o):math_rnd.ctraurig.text+0x63a): undefined reference to `CryptAcquireContextA@20'
D:\FreeBASIC\lib/libfb.a(math_rnd.o):math_rnd.ctraurig.text+0x672): undefined reference to `CryptGenRandom@12'
D:\FreeBASIC\lib/libfb.a(math_rnd.o):math_rnd.ctraurig.text+0x69d): undefined reference to `CryptReleaseContext@8'


Edit:
kann es sein das ich mir irgendwie was zerschossen habe?

Wenn ich randomize timer reinhauen will kommt dieser fehler...
irgendwie die lib geschrottet?!"
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Eternal_pain



Anmeldungsdatum: 08.08.2006
Beiträge: 1783
Wohnort: BW/KA

BeitragVerfasst am: 22.05.2012, 14:17    Titel: Antworten mit Zitat

Schein mir wirklich was zerschossen zu haben, FB neu istalliert und behoben happy

So, hab nun beide Varianten meines Quadtree's nochmal probiert:

Edit: Falsche beschreibungen im Source traurig

Variante 1

'Objekte werden nach Ihrer Grösser ins Quadtree abgelegt und ein Verweis nur einmal im gesamten Baum gespeichert
'Sonderfallbehandlung: Objekte werden auch in der Wurzel des Baums abgelegt

'Vorteil - Objekt-Verweise sind nur einmal vorhanden, eine Prüfung ob Objekt bereits gezeichnet wurde entfällt
' - Quadtree wird nur so oft geteilt wie unbedingt nötig

'Nachteil - Eine Menge (nicht sichtbare) überflüssiger Objekte wird gezeichnet

Variante 2

'Objekte werden in JEDES Node abgelegt das es schneidet

'Vorteil - Es werden nur ein minimum an Sichtbaren Objekte gezeichnet

'Nachteil - Das einlagern erfordert je nach maximaler Tiefe mehr Zeit
' Objekte werden mehrfach im Baum verwiesen und müssen daher geprüft werden ob sie bereits gezeichnet sind
' Quadtree wird IMMER bis zur maximaltiefe geteilt


Beide haben Ihre Vor- und Nachteile, aber ich glaube ich bleibe bei Variante1


Oder sollte ich doch noch eine Dritte Variante versuchen?
XOR's Vorschlag, (maximale Anzahl Objekte per Node??)
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz