Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: cleaned out the segfaults and some other problems that have been introduced in the last cleanup :)

File size: 15.0 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
[4924]11### File Specific:
[4805]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"
[4923]19
[4902]20#include "quadtree.h"
21#include "material.h"
[4868]22#include "abstract_model.h"
[4851]23#include "list.h"
24#include "vector.h"
[4805]25
26using namespace std;
27
28
29/**
[4836]30 *  standard constructor
[4924]31 */
[4887]32QuadtreeNode::QuadtreeNode (sTriangleExt** triangles, int numTriangles,
[4896]33                            const float* pVertices, int numVertices,
[4897]34                            Quadtree* quadtree, QuadtreeNode* parent,
[4900]35                            Rectangle* rect, int treeDepth, const int maxDepth, int index
[4897]36                           )
[4805]37{
[4924]38  /* save all important variables localy */
[4867]39  this->pTriangles = triangles;
40  this->numTriangles = numTriangles;
[4868]41  this->pVertices = pVertices;
42  this->numVertices = numVertices;
[4867]43  this->quadtree = quadtree;
[4896]44  this->parent = parent;
[4897]45  this->pDimension = rect;
[4898]46  this->treeDepth = treeDepth;
47  this->maxDepth = maxDepth;
[4900]48  this->indexNode = index;
[4887]49
[4898]50  /* debug output */
51  for( int i = 0; i < this->treeDepth; ++i)
52    PRINT(3)(" |");
[4913]53  PRINT(3)(" | +-| (Event) Building Node Nr. %i Depth: %i/%i, pointer: %p\n", this->indexNode, treeDepth, maxDepth, this);
[4898]54
55  for( int i = 0; i < this->treeDepth; ++i)
56    PRINT(3)(" |");
57  PRINT(3)(" | +-| (II) Rectangle Center (%5.2f, %5.2f), half axis length: %5.2f\n",
58  this->pDimension->getCenter()->x, this->pDimension->getCenter()->z, this->pDimension->getAxis());
59
[4852]60  this->init();
[4805]61}
62
63
64/**
[4845]65 *  standard constructor
66 */
[4902]67QuadtreeNode::QuadtreeNode(modelInfo* pModelInfo, Quadtree* quadtree, const int maxDepth)
[4845]68{
[4924]69  /* save all important variables localy */
[4845]70  this->pModelInfo = pModelInfo;
[4902]71  this->quadtree = quadtree;
[4924]72  this->maxDepth = maxDepth;
[4925]73  this->treeDepth = 0;
74  this->indexNode = 0;
[4887]75
[4851]76  /* create an array of triangle references */
77  this->pTriangles = new sTriangleExt*[this->pModelInfo->numTriangles];
78  this->numTriangles = this->pModelInfo->numTriangles;
79  this->pVertices = this->pModelInfo->pVertices;
[4868]80  this->numVertices = this->pModelInfo->numVertices;
[4851]81  for( int i = 0; i < this->pModelInfo->numTriangles; ++i)
82    this->pTriangles[i] = &this->pModelInfo->pTriangles[i];
[4900]83
[4898]84  /* debug output */
85  for( int i = 0; i < this->treeDepth; ++i)
86    PRINT(3)(" |");
[4913]87  PRINT(3)(" | +-| (Event) Building Node Nr. %i Depth: %i/%i, pointer: %p\n", this->indexNode, treeDepth, maxDepth, this);
[4898]88
[4924]89  /* set some important variables */
[4897]90  this->pDimension = this->getDimFromModel();
[4924]91
[4852]92  this->init();
[4845]93}
94
[4852]95
96/**
[4923]97 *  takes the rest of the initialisation process
[4852]98 */
99void QuadtreeNode::init()
100{
101  this->setClassID(CL_QUADTREE_NODE, "QuadtreeNode");
102
[4924]103  /* init the rest of the variables for both init types */
[4852]104  this->offset = 0.0f;
[4914]105  this->nodeIter = -1;
[4921]106  this->bDraw = false;
[4899]107
[4896]108  this->parent = NULL;
[4867]109  this->nodeA = NULL;
110  this->nodeB = NULL;
111  this->nodeC = NULL;
112  this->nodeD = NULL;
[4907]113  this->nodes = new QuadtreeNode*[4];
[4911]114  for(int i = 0; i < 4; ++i)
115    this->nodes[i] = NULL;
[4898]116
[4924]117  /* now separate the nodes */
[4899]118  if( this->treeDepth < this->maxDepth)
119    this->separateNode();
[4852]120}
121
[4887]122
[4845]123/**
[4836]124 *  standard deconstructor
[4852]125 */
[4805]126QuadtreeNode::~QuadtreeNode ()
127{
[4867]128  if( this->nodeA != NULL)
129    delete this->nodeA;
130  if( this->nodeB != NULL)
131    delete this->nodeB;
132  if( this->nodeC != NULL)
133    delete this->nodeC;
134  if( this->nodeD != NULL)
135    delete this->nodeD;
[4805]136}
[4812]137
138
[4887]139
[4922]140/**
[4924]141 *  this functions builds up a hash table containing all leafs of the Quadtree in a sorted array
142 * @param nodeList the nodelist array to add them
143 * @param index the current index in the array
[4922]144
[4923]145  The algorithm used for this purpose is home-brown. its not to fast but and the nodes are not always in the right
146  order. this is why there will be needed a quicksort later on.
[4922]147 */
[4911]148void QuadtreeNode::buildHashTable(QuadtreeNode** nodeList, int* index)
149{
[4914]150  if( this->nodeIter == -1)
151    this->nodeIter = *index;
[4911]152
[4914]153  /*              offset              #of elements in a row            #of rows in a quadtree          */
154  int threshold = this->nodeIter + (int)pow(2, this->maxDepth) * (int)pow(2, maxDepth - treeDepth - 1);
155  int loopLimit = (*index < threshold)?2:4;
[4913]156
[4911]157  /* is it a leaf? */
158  if( this->treeDepth < this->maxDepth)
[4914]159    for(int i = (*index < threshold)?0:2; i < loopLimit; ++i)
[4911]160      this->nodes[i]->buildHashTable(nodeList, index);
161  else
162    nodeList[(*index)++] = this;
163}
164
165
166
[4812]167/**
[4836]168 *  gives the signal to separate the model into a quadtree
169 * @param treeDepth the max depth, the steps to go if treeDept == 0 leaf reached
[4924]170
171 * @todo ATTENION: This function is currently not used and not implemented, but would be a nice addon
[4923]172 */
[4819]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
[4924]191 */
[4851]192void QuadtreeNode::separateNode()
193{
[4924]194  /* separate the four regions into the four lists */
[4851]195  tList<sTriangleExt*>*           listA = new tList<sTriangleExt*>();    //!< triangle list of nodeA
196  tList<sTriangleExt*>*           listB = new tList<sTriangleExt*>();    //!< triangle list of nodeB
197  tList<sTriangleExt*>*           listC = new tList<sTriangleExt*>();    //!< triangle list of nodeC
198  tList<sTriangleExt*>*           listD = new tList<sTriangleExt*>();    //!< triangle list of nodeD
199  const float*                    pVert;                                 //!< pointer to the vertices
200  const Vector*                   rectCenter;                            //!< vector to the center of the rect
201
202  rectCenter = this->pDimension->getCenter();
203  for( int i = 0; i < this->numTriangles; ++i)
[4924]204  {
205    for( int j = 0; j < 3; ++j)
[4851]206    {
[4924]207      pVert = &this->pVertices[this->pTriangles[i]->indexToVertices[j]];
208      if( pVert[0] > rectCenter->x + this->offset && pVert[2] > rectCenter->z + this->offset)
209        listA->add(&this->pTriangles[i]);
210      if( pVert[0] < rectCenter->x + this->offset && pVert[2] > rectCenter->z + this->offset)
211        listB->add(&this->pTriangles[i]);
212      if( pVert[0] < rectCenter->x + this->offset && pVert[2] < rectCenter->z + this->offset)
213        listC->add(&this->pTriangles[i]);
214      if( pVert[0] > rectCenter->x + this->offset && pVert[2] < rectCenter->z + this->offset)
215        listD->add(&this->pTriangles[i]);
[4851]216    }
[4924]217  }
218  for( int i = 0; i < treeDepth; ++i)
219    PRINT(3)(" |");
220  PRINT(3)(" | +-| (II) Quadtree Counts - separating: A: %i, B: %i, C: %i, D: %i\n", listA->getSize(), listB->getSize(), listC->getSize(), listD->getSize());
[4853]221
[4924]222
223  /* Separating into to the triangle arrays */
[4853]224  sTriangleExt**                 pTriA;                                 //!< Triangle array A
225  sTriangleExt**                 pTriB;                                 //!< Triangle array B
226  sTriangleExt**                 pTriC;                                 //!< Triangle array C
227  sTriangleExt**                 pTriD;                                 //!< Triangle array D
[4867]228  int                            lenA;                                  //!< length array A
229  int                            lenB;                                  //!< length array B
230  int                            lenC;                                  //!< length array C
231  int                            lenD;                                  //!< length array D
[4853]232  tIterator<sTriangleExt*>*      iterator;                              //!< iterator for the list iterations
[4855]233  sTriangleExt**                 tempTri;                               //!< temp save place for triangle pointer
[4854]234  int                            counter;                               //!< counter for the while loops
[4853]235
236  lenA = listA->getSize();
237  lenB = listB->getSize();
238  lenC = listC->getSize();
239  lenD = listD->getSize();
[4887]240
[4853]241  pTriA = new sTriangleExt*[listA->getSize()];
242  pTriB = new sTriangleExt*[listB->getSize()];
[4887]243  pTriC = new sTriangleExt*[listC->getSize()];
[4853]244  pTriD = new sTriangleExt*[listD->getSize()];
245
[4854]246  counter = 0;
[4853]247  iterator = listA->getIterator();
[4855]248  tempTri = iterator->nextElement();
[4854]249  while( tempTri)
[4924]250  {
251    pTriA[counter] = *tempTri;
252    tempTri = iterator->nextElement();
253    ++counter;
254  }
[4854]255  counter = 0;
256  iterator = listB->getIterator();
[4855]257  tempTri = iterator->nextElement();
[4854]258  while( tempTri)
[4924]259  {
260    pTriB[counter] = *tempTri;
261    tempTri = iterator->nextElement();
262    ++counter;
263  }
[4854]264  counter = 0;
265  iterator = listC->getIterator();
[4855]266  tempTri = iterator->nextElement();
[4854]267  while( tempTri)
[4924]268  {
269    pTriC[counter] = *tempTri;
270    tempTri = iterator->nextElement();
271    ++counter;
272  }
[4854]273  counter = 0;
274  iterator = listD->getIterator();
[4855]275  tempTri = iterator->nextElement();
[4854]276  while( tempTri)
[4924]277  {
278    pTriD[counter] = *tempTri;
279    tempTri = iterator->nextElement();
280    ++counter;
281  }
[4853]282
[4859]283  /* now do cleanup */
284  delete listA;
285  delete listB;
286  delete listC;
287  delete listD;
288  delete iterator;
289
[4897]290
291  /* now create the rectangle dimensions */
[4924]292  Vector                     v;                                                             //!< temp saving place
293  Rectangle*                 rA;                                                            //!< new size of the node A
294  Rectangle*                 rB;                                                            //!< new size of the node B
295  Rectangle*                 rC;                                                            //!< new size of the node C
296  Rectangle*                 rD;                                                            //!< new size of the node D
[4897]297
[4924]298
[4898]299  v.x = this->pDimension->getCenter()->x + this->pDimension->getAxis() / 2.0f;
[4900]300  v.y = 0.0;
[4898]301  v.z = this->pDimension->getCenter()->z + this->pDimension->getAxis() / 2.0f;
[4924]302  rA = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
[4898]303  v.z = this->pDimension->getCenter()->z - this->pDimension->getAxis() / 2.0f;
[4924]304  rB = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
[4898]305  v.x = this->pDimension->getCenter()->x - this->pDimension->getAxis() / 2.0f;
[4924]306  rC = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
[4898]307  v.z = this->pDimension->getCenter()->z + this->pDimension->getAxis() / 2.0f;
[4924]308  rD = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
[4897]309
[4924]310  /* now create the new nodes  */
[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  this->nodeB = new QuadtreeNode(pTriB, lenB, this->pVertices, this->numVertices, this->quadtree, this, rB, this->treeDepth + 1, this->maxDepth, (this->treeDepth + 1) * 10 + 1);
313  this->nodeC = new QuadtreeNode(pTriC, lenC, this->pVertices, this->numVertices, this->quadtree, this, rC, this->treeDepth + 1, this->maxDepth, (this->treeDepth + 1) * 10 + 2);
[4924]314  this->nodeD = new QuadtreeNode(pTriD, lenD, this->pVertices, this->numVertices, this->quadtree, this, rD, this->treeDepth + 1, this->maxDepth, (this->treeDepth + 1) * 10 + 3);
[4900]315
[4907]316  /* map the array references, this is for faster and automatical interfacing  \todo: use only array */
317  this->nodes[0] = this->nodeA;
318  this->nodes[1] = this->nodeB;
319  this->nodes[2] = this->nodeC;
320  this->nodes[3] = this->nodeD;
[4851]321}
322
323
324/**
[4924]325 *  gets the maximal dimension of a model
326 * @return the dimension of the AbstractModel as a Rectangle
[4887]327
[4868]328   The rectangle is x-z axis aligned. ATTENTION: if there are any vertices in the model, that exceed the
329   size of 999999.0, there probably will be some errors in the dimensions calculations. Write an email to
330   patrick@orxonox.ethz.ch if you will ever encounter a model bigger than 999999.0 units, I will realy be
331   happy to see orxonox used to extensivly :)
332 */
[4897]333Rectangle* QuadtreeNode::getDimFromModel()
[4868]334{
335  float            maxX, maxY;                       //!< the maximal coordinates axis
336  float            minX, minY;                       //!< minimal axis coorindates
337  const float*     pVertices;                        //!< pointer to the current vertices
[4887]338
[4868]339  maxX = -999999; maxY = -999999;
340  minX =  999999; minY =  999999;
341  /* get maximal/minimal x/y */
[4887]342  for( int i = 0; i < this->numTriangles; ++i)
[4868]343  {
[4887]344    for( int j = 0; j < 3; ++j)
345    {
[4868]346
[4887]347      pVertices = &this->pVertices[this->pTriangles[i]->indexToVertices[j]];
348      if( pVertices[0] > maxX)
349        maxX = pVertices[0];
350      if( pVertices[2] > maxY)
351        maxY = pVertices[2];
352
353      if( pVertices[0] < minX)
354        minX = pVertices[0];
355      if( pVertices[2] < minY)
356        minY = pVertices[2];
357    }
[4868]358  }
359
360  Rectangle* rect = new Rectangle();
361  rect->setCenter((maxX + minX) / 2.0f, 0.0f, (maxY + minY) / 2.0f); /* this is little strange, since y is in opengl the up vector */
362  rect->setAxis(fmax(((fabs(maxX) + fabs(minX)) / 2.0f), ((fabs(maxY) + fabs(minY)) / 2.0f)));
363
[4887]364  for( int i = 0; i < this->treeDepth; ++i)
[4888]365    PRINT(3)(" |");
366  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]367  return rect;
368}
369
[4902]370
[4923]371 /**
[4924]372 * checks if a point is included in this quadtree
373 * @param v the vector to be checked
374 * @returns true if the vector is included
[4923]375  */
[4920]376bool QuadtreeNode::includesPoint(const Vector& v)
377{
378  Vector center = *this->pDimension->getCenter();
379  float ax = this->pDimension->getAxis();
[4922]380
[4920]381  if( v.x > center.x - ax && v.x < center.x + ax &&
382      v.z > center.z - ax && v.z < center.z + ax )
[4922]383  {
384    this->bDraw = true;
385    return true;
386  }
387  return false;
[4920]388}
389
[4922]390
[4902]391/**
[4923]392 *  draws all the debug quadtree squares
[4902]393 */
[4922]394void QuadtreeNode::drawTree() const
[4902]395{
[4913]396  if( this->treeDepth == this->maxDepth)
[4912]397  {
398    Vector t1 = *this->pDimension->getCenter();
399    float ax = this->pDimension->getAxis();
400    float h = 50.0f;
[4902]401
[4921]402    this->quadtree->getMaterial(this->indexNode)->select();
[4912]403    glBegin(GL_QUADS);
[4922]404    glVertex3f(t1.x + ax, h - this->treeDepth * 10.0f, t1.z + ax);
405    glVertex3f(t1.x - ax, h - this->treeDepth * 10.0f, t1.z + ax);
406    glVertex3f(t1.x - ax, h - this->treeDepth * 10.0f, t1.z - ax);
407    glVertex3f(t1.x + ax, h - this->treeDepth * 10.0f, t1.z - ax);
[4912]408    glEnd();
409  }
[4913]410
411
[4902]412  if( this->nodeA != NULL)
[4922]413    this->nodeA->drawTree();
[4902]414  if( this->nodeB != NULL)
[4922]415    this->nodeB->drawTree();
[4902]416  if( this->nodeC != NULL)
[4922]417    this->nodeC->drawTree();
[4902]418  if( this->nodeD != NULL)
[4922]419    this->nodeD->drawTree();
[4902]420}
[4921]421
[4922]422
[4923]423/**
424 *  draws only this quadtree square
425 */
[4921]426void QuadtreeNode::draw() const
427{
428  if( likely(!bDraw))
429    return;
430  Vector t1 = *this->pDimension->getCenter();
431  float ax = this->pDimension->getAxis();
432  float h = 70.0f;
433
434  glBegin(GL_QUADS);
435  this->quadtree->getMaterial(this->indexNode)->select();
[4922]436
437  glVertex3f(t1.x + ax, h, t1.z + ax);
438  glVertex3f(t1.x - ax, h, t1.z + ax);
439  glVertex3f(t1.x - ax, h, t1.z - ax);
440  glVertex3f(t1.x + ax, h, t1.z - ax);
441
[4921]442  glEnd();
443
444}
Note: See TracBrowser for help on using the repository browser.