Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: started cleaning up the code a little and making the comments

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