Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/graphics/spatial_separation/quadtree_node.cc @ 4913

Last change on this file since 4913 was 4913, checked in by patrick, 19 years ago

orxonox/trunk: working on the hash table alg

File size: 13.3 KB
RevLine 
[4805]1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13   co-programmer: ...
14*/
15
[4808]16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SPATIAL_SEPARATION
[4805]17
18#include "quadtree_node.h"
[4902]19#include "quadtree.h"
20#include "material.h"
[4868]21#include "abstract_model.h"
[4851]22#include "list.h"
23#include "vector.h"
[4805]24
25using namespace std;
26
27
28/**
[4836]29 *  standard constructor
[4805]30*/
[4887]31QuadtreeNode::QuadtreeNode (sTriangleExt** triangles, int numTriangles,
[4896]32                            const float* pVertices, int numVertices,
[4897]33                            Quadtree* quadtree, QuadtreeNode* parent,
[4900]34                            Rectangle* rect, int treeDepth, const int maxDepth, int index
[4897]35                           )
[4805]36{
[4867]37  this->pTriangles = triangles;
38  this->numTriangles = numTriangles;
[4868]39  this->pVertices = pVertices;
40  this->numVertices = numVertices;
[4899]41
[4867]42  this->quadtree = quadtree;
[4896]43  this->parent = parent;
[4899]44
[4897]45  this->pDimension = rect;
[4898]46  this->treeDepth = treeDepth;
47  this->maxDepth = maxDepth;
[4900]48  this->indexNode = index;
[4887]49
[4898]50
51  /* debug output */
52  for( int i = 0; i < this->treeDepth; ++i)
53    PRINT(3)(" |");
[4913]54  PRINT(3)(" | +-| (Event) Building Node Nr. %i Depth: %i/%i, pointer: %p\n", this->indexNode, treeDepth, maxDepth, this);
[4898]55
56  for( int i = 0; i < this->treeDepth; ++i)
57    PRINT(3)(" |");
58  PRINT(3)(" | +-| (II) Rectangle Center (%5.2f, %5.2f), half axis length: %5.2f\n",
59  this->pDimension->getCenter()->x, this->pDimension->getCenter()->z, this->pDimension->getAxis());
60
[4852]61  this->init();
[4805]62}
63
64
65/**
[4845]66 *  standard constructor
67 */
[4902]68QuadtreeNode::QuadtreeNode(modelInfo* pModelInfo, Quadtree* quadtree, const int maxDepth)
[4845]69{
70  this->pModelInfo = pModelInfo;
[4902]71  this->quadtree = quadtree;
[4887]72
[4851]73  /* create an array of triangle references */
74  this->pTriangles = new sTriangleExt*[this->pModelInfo->numTriangles];
75  this->numTriangles = this->pModelInfo->numTriangles;
76  this->pVertices = this->pModelInfo->pVertices;
[4868]77  this->numVertices = this->pModelInfo->numVertices;
[4851]78  for( int i = 0; i < this->pModelInfo->numTriangles; ++i)
79    this->pTriangles[i] = &this->pModelInfo->pTriangles[i];
[4900]80
[4887]81  this->treeDepth = 0;
[4898]82  this->maxDepth = maxDepth;
[4900]83  this->indexNode = 0;
[4852]84
[4898]85  /* debug output */
86  for( int i = 0; i < this->treeDepth; ++i)
87    PRINT(3)(" |");
[4913]88  PRINT(3)(" | +-| (Event) Building Node Nr. %i Depth: %i/%i, pointer: %p\n", this->indexNode, treeDepth, maxDepth, this);
[4898]89
[4897]90  this->pDimension = this->getDimFromModel();
[4852]91  this->init();
[4845]92}
93
[4852]94
95/**
96 * takes the rest of the initialisation process
97 */
98void QuadtreeNode::init()
99{
100  this->setClassID(CL_QUADTREE_NODE, "QuadtreeNode");
101
102  this->offset = 0.0f;
[4911]103  this->nodeIter = 0;
[4899]104
[4896]105  this->parent = NULL;
[4867]106  this->nodeA = NULL;
107  this->nodeB = NULL;
108  this->nodeC = NULL;
109  this->nodeD = NULL;
[4907]110  this->nodes = new QuadtreeNode*[4];
[4911]111  for(int i = 0; i < 4; ++i)
112    this->nodes[i] = NULL;
[4898]113
[4899]114  if( this->treeDepth < this->maxDepth)
115    this->separateNode();
[4852]116}
117
[4887]118
[4845]119/**
[4836]120 *  standard deconstructor
[4852]121 */
[4805]122QuadtreeNode::~QuadtreeNode ()
123{
[4867]124  if( this->nodeA != NULL)
125    delete this->nodeA;
126  if( this->nodeB != NULL)
127    delete this->nodeB;
128  if( this->nodeC != NULL)
129    delete this->nodeC;
130  if( this->nodeD != NULL)
131    delete this->nodeD;
[4805]132}
[4812]133
134
[4887]135
[4911]136void QuadtreeNode::buildHashTable(QuadtreeNode** nodeList, int* index)
137{
[4912]138  int elCount = (int)pow(4, maxDepth - treeDepth) / 2;
139  int loopLimit = (this->nodeIter < elCount)?2:4;
[4911]140
[4913]141  for( int i = 0; i < this->treeDepth; ++i)
142    printf(" ");
143  printf("entering %i: hit counts: %i/%i\n", treeDepth, nodeIter, elCount);
144
[4911]145  /* is it a leaf? */
146  if( this->treeDepth < this->maxDepth)
147  {
[4912]148    for(int i = (this->nodeIter < elCount)?0:2; i < loopLimit; ++i)
[4911]149    {
[4912]150      for( int j = 0; j < this->treeDepth; ++j)
151        printf(" ");
152      printf("-> %i @ depth: %i, %i/%i \n", i, this->treeDepth, nodeIter, elCount);
153
[4911]154      this->nodes[i]->buildHashTable(nodeList, index);
155      ++this->nodeIter;
156    }
157  }
158  else
159  {
[4912]160    for( int j = 0; j < this->treeDepth; ++j)
161      printf(" ");
[4913]162    printf("        leaf, index: %i, pointer: %p\n", *index, this);
[4911]163    nodeList[(*index)++] = this;
164  }
165}
166
167
168
[4812]169/**
[4836]170 *  gives the signal to separate the model into a quadtree
171 * @param treeDepth the max depth, the steps to go if treeDept == 0 leaf reached
[4819]172*/
173void QuadtreeNode::separateNode(float minLength)
[4852]174{
[4888]175  /* dimension calculation & limit checking */
[4867]176  if( minLength <= this->pDimension->getAxis())
177    return;
[4887]178
[4888]179  /* node separation */
[4899]180//   this->separateNode();
181//   this->nodeA->separateNode(minLength);
182//   this->nodeB->separateNode(minLength);
183//   this->nodeC->separateNode(minLength);
184//   this->nodeD->separateNode(minLength);
[4852]185}
[4819]186
187
188/**
[4851]189 *  gives the signal to separate the model into a quadtree
190 * @param treeDepth the max depth, the steps to go if treeDept == 0 leaf reached
191*/
192void QuadtreeNode::separateNode()
193{
194  tList<sTriangleExt*>*           listA = new tList<sTriangleExt*>();    //!< triangle list of nodeA
195  tList<sTriangleExt*>*           listB = new tList<sTriangleExt*>();    //!< triangle list of nodeB
196  tList<sTriangleExt*>*           listC = new tList<sTriangleExt*>();    //!< triangle list of nodeC
197  tList<sTriangleExt*>*           listD = new tList<sTriangleExt*>();    //!< triangle list of nodeD
198  const float*                    pVert;                                 //!< pointer to the vertices
199  const Vector*                   rectCenter;                            //!< vector to the center of the rect
200
201  rectCenter = this->pDimension->getCenter();
202  for( int i = 0; i < this->numTriangles; ++i)
203    {
204      for( int j = 0; j < 3; ++j)
[4887]205        {
206          pVert = &this->pVertices[this->pTriangles[i]->indexToVertices[j]];
207          if( pVert[0] > rectCenter->x + this->offset && pVert[2] > rectCenter->z + this->offset)
208            listA->add(&this->pTriangles[i]);
[4900]209          if( pVert[0] < rectCenter->x + this->offset && pVert[2] > rectCenter->z + this->offset)
[4887]210            listB->add(&this->pTriangles[i]);
[4900]211          if( pVert[0] < rectCenter->x + this->offset && pVert[2] < rectCenter->z + this->offset)
[4887]212            listC->add(&this->pTriangles[i]);
[4900]213          if( pVert[0] > rectCenter->x + this->offset && pVert[2] < rectCenter->z + this->offset)
[4887]214            listD->add(&this->pTriangles[i]);
215        }
[4851]216    }
[4887]217    for( int i = 0; i < treeDepth; ++i)
[4888]218      PRINT(3)(" |");
[4913]219    PRINT(3)(" | +-| (II) Quadtree Counts - separating: A: %i, B: %i, C: %i, D: %i\n", listA->getSize(), listB->getSize(), listC->getSize(), listD->getSize());
[4853]220
221  /* Separating into to the triangle lists  */
222  sTriangleExt**                 pTriA;                                 //!< Triangle array A
223  sTriangleExt**                 pTriB;                                 //!< Triangle array B
224  sTriangleExt**                 pTriC;                                 //!< Triangle array C
225  sTriangleExt**                 pTriD;                                 //!< Triangle array D
[4867]226  int                            lenA;                                  //!< length array A
227  int                            lenB;                                  //!< length array B
228  int                            lenC;                                  //!< length array C
229  int                            lenD;                                  //!< length array D
[4853]230  tIterator<sTriangleExt*>*      iterator;                              //!< iterator for the list iterations
[4855]231  sTriangleExt**                 tempTri;                               //!< temp save place for triangle pointer
[4854]232  int                            counter;                               //!< counter for the while loops
[4853]233
234  lenA = listA->getSize();
235  lenB = listB->getSize();
236  lenC = listC->getSize();
237  lenD = listD->getSize();
[4887]238
[4853]239  pTriA = new sTriangleExt*[listA->getSize()];
240  pTriB = new sTriangleExt*[listB->getSize()];
[4887]241  pTriC = new sTriangleExt*[listC->getSize()];
[4853]242  pTriD = new sTriangleExt*[listD->getSize()];
243
244
[4854]245  counter = 0;
[4853]246  iterator = listA->getIterator();
[4855]247  tempTri = iterator->nextElement();
[4854]248  while( tempTri)
249    {
[4855]250      pTriA[counter] = *tempTri;
251      tempTri = iterator->nextElement();
[4854]252      ++counter;
253    }
[4853]254
[4854]255  counter = 0;
256  iterator = listB->getIterator();
[4855]257  tempTri = iterator->nextElement();
[4854]258  while( tempTri)
259    {
[4855]260      pTriB[counter] = *tempTri;
261      tempTri = iterator->nextElement();
[4854]262      ++counter;
263    }
[4887]264
[4854]265  counter = 0;
266  iterator = listC->getIterator();
[4855]267  tempTri = iterator->nextElement();
[4854]268  while( tempTri)
269    {
[4855]270      pTriC[counter] = *tempTri;
271      tempTri = iterator->nextElement();
[4854]272      ++counter;
273    }
[4853]274
[4854]275  counter = 0;
276  iterator = listD->getIterator();
[4855]277  tempTri = iterator->nextElement();
[4854]278  while( tempTri)
279    {
[4855]280      pTriD[counter] = *tempTri;
281      tempTri = iterator->nextElement();
[4854]282      ++counter;
283    }
[4853]284
[4859]285  /* now do cleanup */
286  delete listA;
287  delete listB;
288  delete listC;
289  delete listD;
290  delete iterator;
291
[4897]292
293  /* now create the rectangle dimensions */
294  Vector v;
295
[4898]296  v.x = this->pDimension->getCenter()->x + this->pDimension->getAxis() / 2.0f;
[4900]297  v.y = 0.0;
[4898]298  v.z = this->pDimension->getCenter()->z + this->pDimension->getAxis() / 2.0f;
[4897]299  Rectangle* rA = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
300
[4898]301  v.z = this->pDimension->getCenter()->z - this->pDimension->getAxis() / 2.0f;
[4897]302  Rectangle* rB = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
303
[4898]304  v.x = this->pDimension->getCenter()->x - this->pDimension->getAxis() / 2.0f;
[4897]305  Rectangle* rC = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
306
[4898]307  v.z = this->pDimension->getCenter()->z + this->pDimension->getAxis() / 2.0f;
[4897]308  Rectangle* rD = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
309
[4859]310  /* now propagate */
[4900]311  this->nodeA = new QuadtreeNode(pTriA, lenA, this->pVertices, this->numVertices, this->quadtree, this, rA, this->treeDepth + 1, this->maxDepth, (this->treeDepth + 1) * 10 + 0);
312
313  this->nodeB = new QuadtreeNode(pTriB, lenB, this->pVertices, this->numVertices, this->quadtree, this, rB, this->treeDepth + 1, this->maxDepth, (this->treeDepth + 1) * 10 + 1);
314
315  this->nodeC = new QuadtreeNode(pTriC, lenC, this->pVertices, this->numVertices, this->quadtree, this, rC, this->treeDepth + 1, this->maxDepth, (this->treeDepth + 1) * 10 + 2);
316
317  this->nodeD = new QuadtreeNode(pTriD, lenD, this->pVertices, this->numVertices, this->quadtree, this, rD, this->treeDepth + 1, this->maxDepth, (this->treeDepth + 1) * 10 + 3);
[4907]318  /* map the array references, this is for faster and automatical interfacing  \todo: use only array */
319  this->nodes[0] = this->nodeA;
320  this->nodes[1] = this->nodeB;
321  this->nodes[2] = this->nodeC;
322  this->nodes[3] = this->nodeD;
[4851]323}
324
325
326/**
[4868]327   \brief gets the maximal dimension of a model
328   \return the dimension of the AbstractModel as a Rectangle
[4887]329
[4868]330   The rectangle is x-z axis aligned. ATTENTION: if there are any vertices in the model, that exceed the
331   size of 999999.0, there probably will be some errors in the dimensions calculations. Write an email to
332   patrick@orxonox.ethz.ch if you will ever encounter a model bigger than 999999.0 units, I will realy be
333   happy to see orxonox used to extensivly :)
334 */
[4897]335Rectangle* QuadtreeNode::getDimFromModel()
[4868]336{
337  float            maxX, maxY;                       //!< the maximal coordinates axis
338  float            minX, minY;                       //!< minimal axis coorindates
339  const float*     pVertices;                        //!< pointer to the current vertices
[4887]340
[4868]341  maxX = -999999; maxY = -999999;
342  minX =  999999; minY =  999999;
343  /* get maximal/minimal x/y */
[4887]344  for( int i = 0; i < this->numTriangles; ++i)
[4868]345  {
[4887]346    for( int j = 0; j < 3; ++j)
347    {
[4868]348
[4887]349      pVertices = &this->pVertices[this->pTriangles[i]->indexToVertices[j]];
350      if( pVertices[0] > maxX)
351        maxX = pVertices[0];
352      if( pVertices[2] > maxY)
353        maxY = pVertices[2];
354
355      if( pVertices[0] < minX)
356        minX = pVertices[0];
357      if( pVertices[2] < minY)
358        minY = pVertices[2];
359    }
[4868]360  }
361
362  Rectangle* rect = new Rectangle();
363  rect->setCenter((maxX + minX) / 2.0f, 0.0f, (maxY + minY) / 2.0f); /* this is little strange, since y is in opengl the up vector */
364  rect->setAxis(fmax(((fabs(maxX) + fabs(minX)) / 2.0f), ((fabs(maxY) + fabs(minY)) / 2.0f)));
365
[4887]366  for( int i = 0; i < this->treeDepth; ++i)
[4888]367    PRINT(3)(" |");
368  PRINT(3)(" | +-| (II) Rectangle Dimension  (%5.2f, %5.2f) to (%5.2f, %5.2f), Center (%5.2f, %5.2f)\n", minX, minY, maxX, maxY, rect->getCenter()->x, rect->getCenter()->z, rect->getAxis());
[4868]369  return rect;
370}
371
[4902]372
373/**
374 *  draws the debug quadtree boxes around the model
375 */
376void QuadtreeNode::drawTree(int depth, int drawMode) const
377{
[4913]378  printf("this = %p\n", this);
379  if( this->treeDepth == this->maxDepth)
[4912]380  {
381    Vector t1 = *this->pDimension->getCenter();
382    float ax = this->pDimension->getAxis();
383    float h = 50.0f;
[4902]384
[4912]385    glBegin(GL_QUADS);
386    this->quadtree->getMaterial(this->indexNode)->select();
387    glVertex3f(t1.x + ax, h - depth * 10.0f, t1.z + ax);
388    glVertex3f(t1.x - ax, h - depth * 10.0f, t1.z + ax);
389    glVertex3f(t1.x - ax, h - depth * 10.0f, t1.z - ax);
390    glVertex3f(t1.x + ax, h - depth * 10.0f, t1.z - ax);
391    glEnd();
392  }
[4913]393
394
[4902]395  if( this->nodeA != NULL)
396    this->nodeA->drawTree(depth - 1, drawMode);
397  if( this->nodeB != NULL)
398    this->nodeB->drawTree(depth - 1, drawMode);
399  if( this->nodeC != NULL)
400    this->nodeC->drawTree(depth - 1, drawMode);
401  if( this->nodeD != NULL)
402    this->nodeD->drawTree(depth - 1, drawMode);
403}
Note: See TracBrowser for help on using the repository browser.