Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Firefly

Alter Hase

  • »Firefly« ist der Autor dieses Themas

Beiträge: 484

Wohnort: Irgendwoundnirgendwo

  • Private Nachricht senden

1

22.05.2009, 12:42

Terrain - Picking

Hallo Community,
momentan bin ich dabei einen simplen Terraineditor zu schreiben. Dieser soll am besten "Realtimeediting" unterstützen. Dazu habe ich mir folgendes überlegt: Jeder Pixel bekommt eine Boundingbox die dann auf Kollision geprüft wird. Nun dauert es jedoch relativ lange bei einer Heightmap von 256x256 (wie ich sie gerade verwende) die Koordinaten bei der ein Picking stattgefunden hat, herauszufinden.

Als Optimierung hab ich mir überlegt einen Quadtree einzusetzen, der eine Unterteilung bis 1x1 Pixel aufweist. Jedoch braucht die Baumerstellung sehr lange, und auch der Speicherplatzverbrauch ist sehr hoch.

Beispielzahlen:
Aufteilung bis | Zeit in ms
256 | 9.324090 ms
128 | 49.949085
64 | 71.118820
32 | 173.731018
16 | 666.704529
8 | 2354.911621
4 | 11584.241211
2 | 81486.554688

1 | abgebrochen nach über 15min und 80 MB Verbrauch

Die Frage ist nun ob es vielleicht effizientere Methoden gibt um die Position im Terrain herauszufinden, oder ob ich mir was falsches überlegt habe. Danke im voraus für alle Antowrten.
Firefly

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//Erstellung des PickingTrees

EResult CEditableTerrain::CalcPickNode(SPickNode *pFather, SPickNode *pNode, const int x, const int z, const int w, const int h)
{
    //als erstes die Aabb bestimmen...

    //Schritt 0: Datenübertragung


    pNode->m_pFather = pFather;
    pNode->m_ptCoord.x = x;
    pNode->m_ptCoord.y = z;

    //Kinder nullen

    for(int i = 0; i < 4; i++)pNode->m_pChilds[i] = NULL;
    
    //Schritt 1: Maximale und Minimale Höhe bestimmen

    BYTE cMaxHeight = 0, cMinHeight = 255;

    for(int a = x; a < x + w; a++)
        for(int b = z; b < z + h; b++)
        {
            cMaxHeight = stMax(m_pHeightMap[a + b * m_dwWidth], cMaxHeight);
            cMinHeight = stMin(m_pHeightMap[a + b * m_dwWidth], cMinHeight);
        }
    //Die Minima, Maxima wurden gefunden...

    //Schritt 2: Vektoren anlegen

    pNode->m_Aabb.vMax = stVector((x + w) * m_fStepX + 0.5f * m_fStepX,
                                     cMaxHeight * m_fStepY + 0.5f,
                                     (z + h) * m_fStepZ + 0.5f * m_fStepZ);

    pNode->m_Aabb.vMin = stVector((x) * m_fStepX - 0.5f * m_fStepX,
                                     cMinHeight * m_fStepY - 0.5f,
                                     (z) * m_fStepZ - 0.5f * m_fStepZ);

    //Als begrenzende Werte sind 8 oder 16 gut

    
    //Wenn die Breite != 1, Kinder anlegen

                if(w != 1)  
    {
        //ansonsten weiter unterteilen...

        


        //Speicher reservieren...

        for(int i = 0; i < 4; i++)pNode->m_pChilds[i] = new SPickNode;
        
        CalcPickNode(pNode, pNode->m_pChilds[0], x, z, w / 2, h / 2);
        CalcPickNode(pNode, pNode->m_pChilds[1], x + w / 2, z, w / 2, h / 2);
        CalcPickNode(pNode, pNode->m_pChilds[2], x, z + h / 2, w / 2, h / 2);
        CalcPickNode(pNode, pNode->m_pChilds[3], x + w / 2, z + h / 2, w / 2, h / 2);
    }

    //alles ok

    return E_OK;    
}

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

2

22.05.2009, 12:45

naja einen pixel zu picken hm nen bissl overkill.

vorschlag:

gehe quadweise vor, mach das in einem quadtree, also einen großen fürs terrain, dann 4 für die 128x128 dann vier für 64x64 usw. wenn du das passende quad gefunden hast, mach einen ebenen strahl test, dann haste deinen 3d-punkt und das is nen pixel umzurechnen ist ja nicht schwer :)

Firefly

Alter Hase

  • »Firefly« ist der Autor dieses Themas

Beiträge: 484

Wohnort: Irgendwoundnirgendwo

  • Private Nachricht senden

3

22.05.2009, 12:50

Du meinst also den Quadtree nur bis 128x128 oder 64x64 laufen zu lassen und dann in die Leafs nochmals einen Quadtree einzufügen (bis zum Pixel)?
Oder hab ich was falsch verstanden..?

Firefly

Alter Hase

  • »Firefly« ist der Autor dieses Themas

Beiträge: 484

Wohnort: Irgendwoundnirgendwo

  • Private Nachricht senden

4

22.05.2009, 17:53

So hab das ganze jetzt so gelöst, dass ich bis zu einer Auflösung von 16x16 den Baum erstelle und dann jeweils für ein Pixel eine BoundingBox, welche dann beim Testen gegen den Strahl einfach in einer Schleife durchgetestet werden. Framerate neu: ca. 60 -100 FPS, vorher 20 - 40 FPS, Baumerstellung mit Optimierungen verkürzt auf 126ms

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

5

22.05.2009, 18:23

pro quad reicht doch ein ebenen-strahlen test. das spart dir das pixelweise ;)

EDIT:

also eine quad-tree von 128x128 bis 1x1 und wenn du beim 1x1quad angekommen bist da ne ebene bilden eben strahlen schnittpunkt fertig :)

Werbeanzeige