Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: extended the constructor interface to force the specification of a parent Node

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