Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: implemented a point in triangle function

File size: 15.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
20#include "quadtree.h"
21#include "material.h"
22#include "abstract_model.h"
23#include "list.h"
24#include "vector.h"
25
26using namespace std;
27
28
29/**
30 *  standard constructor
31 */
32QuadtreeNode::QuadtreeNode (sTriangleExt** triangles, int numTriangles,
33                            const float* pVertices, int numVertices,
34                            Quadtree* quadtree, QuadtreeNode* parent,
35                            Rectangle* rect, int treeDepth, const int maxDepth, int index
36                           )
37{
38  /* save all important variables localy */
39  this->pTriangles = triangles;
40  this->numTriangles = numTriangles;
41  this->pVertices = pVertices;
42  this->numVertices = numVertices;
43  this->quadtree = quadtree;
44  this->parent = parent;
45  this->pDimension = rect;
46  this->treeDepth = treeDepth;
47  this->maxDepth = maxDepth;
48  this->indexNode = index;
49
50  /* debug output */
51  for( int i = 0; i < this->treeDepth; ++i)
52    PRINT(3)(" |");
53  PRINT(3)(" | +-| (Event) Building Node Nr. %i Depth: %i/%i, pointer: %p\n", this->indexNode, treeDepth, maxDepth, this);
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
60  this->init();
61}
62
63
64/**
65 *  standard constructor
66 */
67QuadtreeNode::QuadtreeNode(modelInfo* pModelInfo, Quadtree* quadtree, const int maxDepth)
68{
69  /* save all important variables localy */
70  this->pModelInfo = pModelInfo;
71  this->quadtree = quadtree;
72  this->maxDepth = maxDepth;
73  this->treeDepth = 0;
74  this->indexNode = 0;
75
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;
80  this->numVertices = this->pModelInfo->numVertices;
81  for( int i = 0; i < this->pModelInfo->numTriangles; ++i)
82    this->pTriangles[i] = &this->pModelInfo->pTriangles[i];
83
84  /* debug output */
85  for( int i = 0; i < this->treeDepth; ++i)
86    PRINT(3)(" |");
87  PRINT(3)(" | +-| (Event) Building Node Nr. %i Depth: %i/%i, pointer: %p\n", this->indexNode, treeDepth, maxDepth, this);
88
89  /* set some important variables */
90  this->pDimension = this->getDimFromModel();
91
92  this->init();
93}
94
95
96/**
97 *  takes the rest of the initialisation process
98 */
99void QuadtreeNode::init()
100{
101  this->setClassID(CL_QUADTREE_NODE, "QuadtreeNode");
102
103  /* init the rest of the variables for both init types */
104  this->offset = 0.0f;
105  this->nodeIter = -1;
106  this->bDraw = false;
107
108  this->parent = NULL;
109  this->nodeA = NULL;
110  this->nodeB = NULL;
111  this->nodeC = NULL;
112  this->nodeD = NULL;
113  this->nodes = new QuadtreeNode*[4];
114  for(int i = 0; i < 4; ++i)
115    this->nodes[i] = NULL;
116
117  /* now separate the nodes */
118  if( this->treeDepth < this->maxDepth)
119    this->separateNode();
120}
121
122
123/**
124 *  standard deconstructor
125 */
126QuadtreeNode::~QuadtreeNode ()
127{
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;
136}
137
138
139
140/**
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
144
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.
147 */
148void QuadtreeNode::buildHashTable(QuadtreeNode** nodeList, int* index)
149{
150  if( this->nodeIter == -1)
151    this->nodeIter = *index;
152
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;
156
157  /* is it a leaf? */
158  if( this->treeDepth < this->maxDepth)
159    for(int i = (*index < threshold)?0:2; i < loopLimit; ++i)
160      this->nodes[i]->buildHashTable(nodeList, index);
161  else
162    nodeList[(*index)++] = this;
163}
164
165
166
167/**
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
170
171 * @todo ATTENION: This function is currently not used and not implemented, but would be a nice addon
172 */
173void QuadtreeNode::separateNode(float minLength)
174{
175  /* dimension calculation & limit checking */
176  if( minLength <= this->pDimension->getAxis())
177    return;
178
179  /* node separation */
180//   this->separateNode();
181//   this->nodeA->separateNode(minLength);
182//   this->nodeB->separateNode(minLength);
183//   this->nodeC->separateNode(minLength);
184//   this->nodeD->separateNode(minLength);
185}
186
187
188/**
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  /* separate the four regions into the four lists */
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)
204  {
205    for( int j = 0; j < 3; ++j)
206    {
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]);
216    }
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());
221
222
223  /* Separating into to the triangle arrays */
224  sTriangleExt**                 pTriA;                                 //!< Triangle array A
225  sTriangleExt**                 pTriB;                                 //!< Triangle array B
226  sTriangleExt**                 pTriC;                                 //!< Triangle array C
227  sTriangleExt**                 pTriD;                                 //!< Triangle array D
228  int                            lenA;                                  //!< length array A
229  int                            lenB;                                  //!< length array B
230  int                            lenC;                                  //!< length array C
231  int                            lenD;                                  //!< length array D
232  tIterator<sTriangleExt*>*      iterator;                              //!< iterator for the list iterations
233  sTriangleExt**                 tempTri;                               //!< temp save place for triangle pointer
234  int                            counter;                               //!< counter for the while loops
235
236  lenA = listA->getSize();
237  lenB = listB->getSize();
238  lenC = listC->getSize();
239  lenD = listD->getSize();
240
241  pTriA = new sTriangleExt*[listA->getSize()];
242  pTriB = new sTriangleExt*[listB->getSize()];
243  pTriC = new sTriangleExt*[listC->getSize()];
244  pTriD = new sTriangleExt*[listD->getSize()];
245
246  counter = 0;
247  iterator = listA->getIterator();
248  tempTri = iterator->nextElement();
249  while( tempTri)
250  {
251    pTriA[counter] = *tempTri;
252    tempTri = iterator->nextElement();
253    ++counter;
254  }
255  counter = 0;
256  iterator = listB->getIterator();
257  tempTri = iterator->nextElement();
258  while( tempTri)
259  {
260    pTriB[counter] = *tempTri;
261    tempTri = iterator->nextElement();
262    ++counter;
263  }
264  counter = 0;
265  iterator = listC->getIterator();
266  tempTri = iterator->nextElement();
267  while( tempTri)
268  {
269    pTriC[counter] = *tempTri;
270    tempTri = iterator->nextElement();
271    ++counter;
272  }
273  counter = 0;
274  iterator = listD->getIterator();
275  tempTri = iterator->nextElement();
276  while( tempTri)
277  {
278    pTriD[counter] = *tempTri;
279    tempTri = iterator->nextElement();
280    ++counter;
281  }
282
283  /* now do cleanup */
284  delete listA;
285  delete listB;
286  delete listC;
287  delete listD;
288  delete iterator;
289
290
291  /* now create the rectangle dimensions */
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
297
298
299  v.x = this->pDimension->getCenter()->x + this->pDimension->getAxis() / 2.0f;
300  v.y = 0.0;
301  v.z = this->pDimension->getCenter()->z + this->pDimension->getAxis() / 2.0f;
302  rA = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
303  v.z = this->pDimension->getCenter()->z - this->pDimension->getAxis() / 2.0f;
304  rB = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
305  v.x = this->pDimension->getCenter()->x - this->pDimension->getAxis() / 2.0f;
306  rC = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
307  v.z = this->pDimension->getCenter()->z + this->pDimension->getAxis() / 2.0f;
308  rD = new Rectangle(v, this->pDimension->getAxis() / 2.0f);
309
310  /* now create the new nodes  */
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);
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);
315
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;
321}
322
323
324/**
325 *  gets the maximal dimension of a model
326 * @return the dimension of the AbstractModel as a Rectangle
327
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 */
333Rectangle* QuadtreeNode::getDimFromModel()
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
338
339  maxX = -999999; maxY = -999999;
340  minX =  999999; minY =  999999;
341  /* get maximal/minimal x/y */
342  for( int i = 0; i < this->numTriangles; ++i)
343  {
344    for( int j = 0; j < 3; ++j)
345    {
346
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    }
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
364  for( int i = 0; i < this->treeDepth; ++i)
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());
367  return rect;
368}
369
370
371 /**
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
375  */
376bool QuadtreeNode::includesPoint(const Vector& v)
377{
378  Vector center = *this->pDimension->getCenter();
379  float ax = this->pDimension->getAxis();
380
381  if( v.x > center.x - ax && v.x < center.x + ax &&
382      v.z > center.z - ax && v.z < center.z + ax )
383  {
384    this->bDraw = true;
385    return true;
386  }
387  return false;
388}
389
390
391sTriangleExt* QuadtreeNode::getTriangle(const Vector& position)
392{
393
394}
395
396bool QuadtreeNode::pointInTriangle(const Vector&p, const Vector& a, const Vector& b, const Vector& c)
397{
398  if( this->sameSide(p, a, b, c) && this->sameSide(p, b, a, c) && sameSide(p, c, a, b))
399    return true;
400  return false;
401  /*
402  function PointInTriangle(p, a,b,c)
403  if SameSide(p,a, b,c) and SameSide(p,b, a,c)
404  and SameSide(p,c, a,b) then return true
405  else return false
406  */
407}
408
409
410bool QuadtreeNode::sameSide(const Vector& p1, const Vector&p2, const Vector& a, const Vector& b)
411{
412  Vector cp1 = (b - a).cross(p1 - a);
413  Vector cp2 = (b - a).cross(p2 - a);
414
415  if( unlikely(cp1.dot(cp2) >= 0)) return true;
416  return false;
417}
418
419
420/**
421 *  draws all the debug quadtree squares
422 */
423void QuadtreeNode::drawTree() const
424{
425  if( this->treeDepth == this->maxDepth)
426  {
427    Vector t1 = *this->pDimension->getCenter();
428    float ax = this->pDimension->getAxis();
429    float h = 50.0f;
430
431    this->quadtree->getMaterial(this->indexNode)->select();
432    glBegin(GL_QUADS);
433    glVertex3f(t1.x + ax, h - this->treeDepth * 10.0f, t1.z + ax);
434    glVertex3f(t1.x - ax, h - this->treeDepth * 10.0f, t1.z + ax);
435    glVertex3f(t1.x - ax, h - this->treeDepth * 10.0f, t1.z - ax);
436    glVertex3f(t1.x + ax, h - this->treeDepth * 10.0f, t1.z - ax);
437    glEnd();
438  }
439
440
441  if( this->nodeA != NULL)
442    this->nodeA->drawTree();
443  if( this->nodeB != NULL)
444    this->nodeB->drawTree();
445  if( this->nodeC != NULL)
446    this->nodeC->drawTree();
447  if( this->nodeD != NULL)
448    this->nodeD->drawTree();
449}
450
451
452/**
453 *  draws only this quadtree square
454 */
455void QuadtreeNode::draw() const
456{
457  if( likely(!bDraw))
458    return;
459  Vector t1 = *this->pDimension->getCenter();
460  float ax = this->pDimension->getAxis();
461  float h = 70.0f;
462
463  glBegin(GL_QUADS);
464  this->quadtree->getMaterial(this->indexNode)->select();
465
466  glVertex3f(t1.x + ax, h, t1.z + ax);
467  glVertex3f(t1.x - ax, h, t1.z + ax);
468  glVertex3f(t1.x - ax, h, t1.z - ax);
469  glVertex3f(t1.x + ax, h, t1.z - ax);
470
471  glEnd();
472
473}
Note: See TracBrowser for help on using the repository browser.