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
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 "abstract_model.h"
20#include "list.h"
21#include "vector.h"
22
23using namespace std;
24
25
26/**
27 *  standard constructor
28*/
29QuadtreeNode::QuadtreeNode (sTriangleExt** triangles, int numTriangles,
30                            const float* pVertices, int numVertices,
31                            Quadtree* quadtree, QuadtreeNode* parent)
32{
33  this->pTriangles = triangles;
34  this->numTriangles = numTriangles;
35  this->pVertices = pVertices;
36  this->numVertices = numVertices;
37  this->quadtree = quadtree;
38  this->treeDepth = 0;
39  this->parent = parent;
40
41  this->init();
42}
43
44
45/**
46 *  standard constructor
47 */
48QuadtreeNode::QuadtreeNode(modelInfo* pModelInfo)
49{
50  this->pModelInfo = pModelInfo;
51
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;
56  this->numVertices = this->pModelInfo->numVertices;
57  for( int i = 0; i < this->pModelInfo->numTriangles; ++i)
58    this->pTriangles[i] = &this->pModelInfo->pTriangles[i];
59  this->treeDepth = 0;
60
61  this->init();
62}
63
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;
73  this->parent = NULL;
74  this->nodeA = NULL;
75  this->nodeB = NULL;
76  this->nodeC = NULL;
77  this->nodeD = NULL;
78}
79
80
81/**
82 *  standard deconstructor
83 */
84QuadtreeNode::~QuadtreeNode ()
85{
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;
94}
95
96
97/**
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
100 */
101void QuadtreeNode::separateNode(int treeDepth, const int maxDepth)
102{
103  this->treeDepth = treeDepth;
104  /* debug output */
105  for( int i = 0; i < treeDepth; ++i)
106    PRINT(3)(" |");
107  PRINT(3)(" | +-| (Event) Separating Node Depth: %i/%i\n", treeDepth, maxDepth);
108
109  /* dimension calculation & limit checking */
110  this->pDimension = this->getDimension();
111  if( treeDepth >= maxDepth)
112    return;
113
114  /* node separation */
115  this->separateNode();
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);
120}
121
122
123/**
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
126*/
127void QuadtreeNode::separateNode(float minLength)
128{
129  /* dimension calculation & limit checking */
130  this->pDimension = this->getDimension();
131  if( minLength <= this->pDimension->getAxis())
132    return;
133
134  /* node separation */
135  this->separateNode();
136  this->nodeA->separateNode(minLength);
137  this->nodeB->separateNode(minLength);
138  this->nodeC->separateNode(minLength);
139  this->nodeD->separateNode(minLength);
140}
141
142
143/**
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)
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        }
171    }
172    for( int i = 0; i < treeDepth; ++i)
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());
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
181  int                            lenA;                                  //!< length array A
182  int                            lenB;                                  //!< length array B
183  int                            lenC;                                  //!< length array C
184  int                            lenD;                                  //!< length array D
185  tIterator<sTriangleExt*>*      iterator;                              //!< iterator for the list iterations
186  sTriangleExt**                 tempTri;                               //!< temp save place for triangle pointer
187  int                            counter;                               //!< counter for the while loops
188
189  lenA = listA->getSize();
190  lenB = listB->getSize();
191  lenC = listC->getSize();
192  lenD = listD->getSize();
193
194  pTriA = new sTriangleExt*[listA->getSize()];
195  pTriB = new sTriangleExt*[listB->getSize()];
196  pTriC = new sTriangleExt*[listC->getSize()];
197  pTriD = new sTriangleExt*[listD->getSize()];
198
199
200  counter = 0;
201  iterator = listA->getIterator();
202  tempTri = iterator->nextElement();
203  while( tempTri)
204    {
205      pTriA[counter] = *tempTri;
206      tempTri = iterator->nextElement();
207      ++counter;
208    }
209
210  counter = 0;
211  iterator = listB->getIterator();
212  tempTri = iterator->nextElement();
213  while( tempTri)
214    {
215      pTriB[counter] = *tempTri;
216      tempTri = iterator->nextElement();
217      ++counter;
218    }
219
220  counter = 0;
221  iterator = listC->getIterator();
222  tempTri = iterator->nextElement();
223  while( tempTri)
224    {
225      pTriC[counter] = *tempTri;
226      tempTri = iterator->nextElement();
227      ++counter;
228    }
229
230  counter = 0;
231  iterator = listD->getIterator();
232  tempTri = iterator->nextElement();
233  while( tempTri)
234    {
235      pTriD[counter] = *tempTri;
236      tempTri = iterator->nextElement();
237      ++counter;
238    }
239
240  /* now do cleanup */
241  delete listA;
242  delete listB;
243  delete listC;
244  delete listD;
245  delete iterator;
246
247  /* now propagate */
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);
252}
253
254
255
256/**
257 *  draws the debug quadtree boxes around the model
258 */
259void QuadtreeNode::drawTree(int depth, int drawMode) const
260{
261
262  Vector t1 = *this->pDimension->getCenter();
263  float ax = this->pDimension->getAxis();
264  float h = 50.0f;
265
266  glBegin(GL_QUADS);
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);
271  glEnd();
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);
281}
282
283
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
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 :)
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
321  for( int i = 0; i < this->treeDepth; ++i)
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());
324  return rect;
325}
326
327
328/**
329   \brief gets the maximal dimension of a model
330   \return the dimension of the AbstractModel as a Rectangle
331
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
342
343  maxX = -999999; maxY = -999999;
344  minX =  999999; minY =  999999;
345  /* get maximal/minimal x/y */
346  for( int i = 0; i < this->numTriangles; ++i)
347  {
348    for( int j = 0; j < 3; ++j)
349    {
350
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    }
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
368  for( int i = 0; i < this->treeDepth; ++i)
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());
371  return rect;
372}
373
Note: See TracBrowser for help on using the repository browser.