Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/collision_detection/obb_tree_node.cc @ 4618

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

orxonox/trunk: the obb tree now gets rendered correctly

File size: 18.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_COLLISION
17
18#include "obb_tree_node.h"
19#include "list.h"
20#include "obb.h"
21#include "obb_tree.h"
22#include "vector.h"
23#include "abstract_model.h"
24
25#include <math.h>
26
27
28#define WANT_STREAM
29#define WANT_MATH
30#define WANT_FSTREAM
31
32
33#include "include.h"
34#include "newmat.h"
35#include "newmatap.h"
36#include "newmatio.h"
37
38
39
40
41using namespace std;
42
43
44/**
45   \brief standard constructor
46 */
47OBBTreeNode::OBBTreeNode ()
48{
49  this->setClassID(CL_OBB_TREE_NODE, "OBBTreeNode");
50  this->nodeLeft = NULL;
51  this->nodeRight = NULL;
52}
53
54
55/**
56   \brief standard deconstructor
57 */
58OBBTreeNode::~OBBTreeNode ()
59{
60  // delete what has to be deleted here
61}
62
63
64
65/**
66   \brief creates a new BVTree or BVTree partition
67   \param depth: how much more depth-steps to go: if == 1 don't go any deeper!
68   \param verticesList: the list of vertices of the object - each vertices triple is interpreted as a triangle
69 */
70void OBBTreeNode::spawnBVTree(const int depth, sVec3D *verticesList, const int length)
71{
72  this->depth = depth;
73
74  this->bvElement = this->createBox();
75  this->calculateBoxAttributes(this->bvElement, verticesList, length);
76
77  if( likely( this->depth > 0))
78  {
79    this->forkBox(this->bvElement);
80  }
81}
82
83
84OBB* OBBTreeNode::createBox()
85{
86  return new OBB();
87}
88
89
90void OBBTreeNode::calculateBoxAttributes(OBB* box, sVec3D* verticesList, int length)
91{
92  float     facelet[length];                         //!< surface area of the i'th triangle of the convex hull
93  float     face;                                    //!< surface area of the entire convex hull
94  Vector    centroid[length];                        //!< centroid of the i'th convex hull
95  Vector    center;                                  //!< the center of the entire hull
96  Vector    p, q, r;                                 //!< holder of the polygon data, much more conveniant to work with Vector than sVec3d
97  Vector    t1, t2;                                  //!< temporary values
98  float     covariance[3][3];                        //!< the covariance matrix
99
100  this->numOfVertices = length;
101  this->vertices = verticesList;
102  box->vertices = verticesList;
103  box->numOfVertices = length;
104
105
106  /* fist compute all the convex hull face/facelets and centroids */
107  for(int i = 0; i < length; i+=3)          /* FIX-ME-QUICK: hops of 3, array indiscontinuity*/
108  {
109    p = verticesList[i];
110    q = verticesList[i +1];
111    r = verticesList[i + 2];
112
113    t1 = p - q; t2 = p - r;
114
115    /* finding the facelet surface via cross-product */
116    facelet[i] = 0.5f * fabs( t1.cross(t2).len() );
117    /* update the entire convex hull surface */
118    face += facelet[i];
119
120    /* calculate the cetroid of the hull triangles */
121    centroid[i] = (p + q + r) * 1/3;
122    /* now calculate the centroid of the entire convex hull, weighted average of triangle centroids */
123    center += centroid[i] * facelet[i];
124  }
125  /* take the average of the centroid sum */
126  center /= face;
127
128
129
130  /* now calculate the covariance matrix - if not written in three for-loops, it would compute faster: minor */
131  for(int j = 0; j < 3; ++j)
132  {
133    for(int k = 0; k < 3; ++k)
134    {
135      for(int i = 0; i < length; i+=3)
136      {
137        p = verticesList[i];
138        q = verticesList[i +1];
139        r = verticesList[i + 2];
140
141        covariance[j][k] = facelet[i] / (12.0f * face) * (9.0f * centroid[i][j] * centroid[i][k] + p[j]* p[k] +
142            q[j] * q[k] + r[j]*r[k]) - center[j] * center[k];
143      }
144    }
145  }
146
147  printf("\nVertex Data:\n");
148  for(int i = 0; i < length; i++)
149  {
150    printf("vertex %i: %f, %f, %f\n", i, verticesList[i][0], verticesList[i][1], verticesList[i][2]);
151  }
152
153  printf("\nCovariance Matrix:\n");
154  for(int j = 0; j < 3; ++j)
155  {
156    printf(" |");
157    for(int k = 0; k < 3; ++k)
158    {
159      printf(" \b%f ", covariance[j][k]);
160    }
161    printf(" |\n");
162  }
163  printf("center: %f, %f, %f\n\n", center.x, center.y, center.z);
164
165
166  for(int i = 0; i < 3; ++i)
167  {
168
169    box->covarianceMatrix[i][0] = covariance[i][0];
170    box->covarianceMatrix[i][1] = covariance[i][1];
171    box->covarianceMatrix[i][3] = covariance[i][2];
172  }
173  *box->center = center;
174
175
176  /* now getting spanning vectors of the sub-space:
177  the eigenvectors of a symmertric matrix, such as the
178  covarience matrix are mutually orthogonal.
179  after normalizing them, they can be used as a the basis
180  vectors
181  */
182  Matrix                V(3,3);                               //!< for eigenvectors
183  DiagonalMatrix        D(3);                                 //!< for eigenvalues
184  SymmetricMatrix       C(3);                                 //!< for the covariance symmetrical matrix
185  Vector**              axis = new Vector*[3];                //!< the references to the obb axis
186
187  C(1,1) = covariance[0][0];
188  C(1,2) = covariance[0][1];
189  C(1,3) = covariance[0][2];
190  C(2,1) = covariance[1][0];
191  C(2,2) = covariance[1][1];
192  C(2,3) = covariance[1][2];
193  C(3,1) = covariance[2][0];
194  C(3,2) = covariance[2][1];
195  C(3,3) = covariance[2][2];
196
197  Jacobi(C, D, V);                                            /* do the jacobi decomposition */
198
199  printf("\nwe got a result! YES: \n");
200
201  for(int j = 1; j < 4; ++j)
202  {
203    printf(" |");
204    for(int k = 1; k < 4; ++k)
205    {
206      printf(" \b%f ", V(j, k));
207    }
208    printf(" |\n");
209  }
210
211  axis[0] = new Vector(V(1, 1), V(2, 1), V(3, 1));
212  axis[1] = new Vector(V(1, 2), V(2, 2), V(3, 2));
213  axis[2] = new Vector(V(1, 3), V(2, 3), V(3, 3));
214  box->axis = axis;
215
216  printf("\neigenvector: %f, %f, %f\n", box->axis[0]->x, box->axis[0]->y, box->axis[0]->z);
217  printf("eigenvector: %f, %f, %f\n", box->axis[1]->x, box->axis[1]->y, box->axis[1]->z);
218  printf("eigenvector: %f, %f, %f\n", box->axis[2]->x, box->axis[2]->y, box->axis[2]->z);
219
220
221  /* now get the axis length */
222  Line                ax[3];                                 //!< the axis
223  float*              halfLength = new float[3];             //!< half length of the axis
224  float               tmpLength;                             //!< tmp save point for the length
225  Plane               p0(*box->axis[0], *box->center);       //!< the axis planes
226  Plane               p1(*box->axis[1], *box->center);
227  Plane               p2(*box->axis[2], *box->center);
228
229  halfLength[0] = -1.0f;
230  for(int j = 0; j < length; ++j)
231  {
232    tmpLength = fabs(p0.distancePoint(vertices[j]));
233    if( tmpLength > halfLength[0])
234      halfLength[0] = tmpLength;
235  }
236
237  halfLength[1] = -1.0f;
238  for(int j = 0; j < length; ++j)
239  {
240    tmpLength = fabs(p1.distancePoint(vertices[j]));
241    if( tmpLength > halfLength[1])
242      halfLength[1] = tmpLength;
243  }
244
245  halfLength[2] = -1.0f;
246  for(int j = 0; j < length; ++j)
247  {
248    tmpLength = fabs(p2.distancePoint(vertices[j]));
249    if( tmpLength > halfLength[2])
250      halfLength[2] = tmpLength;
251  }
252
253  box->halfLength = halfLength;
254
255
256  printf("\nwe got length: \n");
257  for(int i = 0; i < 3; ++i)
258    printf("length[%i] = %f\n", i, box->halfLength[i]);
259}
260
261
262
263/**
264  \brief this separates an ob-box in the middle
265  \param box: the box to separate
266
267  this will separate the box into to smaller boxes. the separation is done along the middle of the longest axis
268 */
269void OBBTreeNode::forkBox(OBB* box)
270{
271  /* get the longest axis of the box */
272  float               aLength = -1.0f;                     //!< the length of the longest axis
273  int                 axisIndex = 0;                       //!< this is the nr of the longest axis
274
275  for(int i = 0; i < 3; ++i)
276  {
277    if( aLength < box->halfLength[i])
278    {
279      aLength = box->halfLength[i];
280      axisIndex = i;
281    }
282  }
283
284  printf("\nlongest axis is: nr %i with a half-length of: %f\n", axisIndex, aLength);
285
286
287  /* get the closest vertex near the center */
288  float               dist = 999999.0f;                    //!< the smallest distance to each vertex
289  float               tmpDist;                             //!< temporary distance
290  int                 vertexIndex;
291  Plane               middlePlane(*box->axis[axisIndex], *box->center); //!< the middle plane
292
293  for(int i = 0; i < box->numOfVertices; ++i)
294  {
295    tmpDist = fabs(middlePlane.distancePoint(box->vertices[i]));
296    if( tmpDist < dist)
297    {
298      dist = tmpDist;
299      vertexIndex = i;
300    }
301  }
302
303  printf("\nthe clostest vertex is nr: %i, with a dist of: %f\n", vertexIndex ,dist);
304
305
306  /* now definin the separation plane through this specified nearest point and partition
307  the points depending on which side they are located
308  */
309  Plane              separationPlane(*box->axis[axisIndex], box->vertices[vertexIndex]);  //!< separation plane
310  tList<sVec3D>      partition1;                           //!< the vertex partition 1
311  tList<sVec3D>      partition2;                           //!< the vertex partition 2
312
313  for(int i = 0; i < box->numOfVertices; ++i)
314  {
315    if( separationPlane.distancePoint(box->vertices[i]) > 0.0f)
316      partition1.add(&box->vertices[i]);
317    else
318      partition2.add(&box->vertices[i]);
319  }
320  partition1.add(&box->vertices[vertexIndex]);
321
322  printf("\npartition1: got %i vertices/ partition 2: got %i vertices\n", partition1.getSize(), partition2.getSize());
323
324
325  /* now comes the separation into two different sVec3D arrays */
326  tIterator<sVec3D>* iterator;                             //!< the iterator to go through the lists
327  sVec3D*            element;                              //!< the elements
328  int                index;                                //!< index storage place
329  sVec3D*            vertList1;                            //!< the vertex list 1
330  sVec3D*            vertList2;                            //!< the vertex list 2
331
332  vertList1 = new sVec3D[partition1.getSize()];
333  vertList2 = new sVec3D[partition2.getSize()];
334
335  iterator = partition1.getIterator();
336  element = iterator->nextElement();
337  index = 0;
338  while( element != NULL)
339  {
340    vertList1[index][0] = element[0][0];
341    vertList1[index][1] = element[0][1];
342    vertList1[index][2] = element[0][2];
343    ++index;
344    element = iterator->nextElement();
345  }
346
347  printf("\npartition 1:\n");
348  for(int i = 0; i < partition1.getSize(); ++i)
349  {
350    printf("v[%i][0] = %f\n", i, vertList1[i][0]);
351    printf("v[%i][1] = %f\n", i, vertList1[i][1]);
352    printf("v[%i][2] = %f\n", i, vertList1[i][2]);
353  }
354
355  iterator = partition2.getIterator();
356  element = iterator->nextElement();
357  index = 0;
358  while( element != NULL)
359  {
360    vertList2[index][0] = element[0][0];
361    vertList2[index][1] = element[0][1];
362    vertList2[index][2] = element[0][2];
363    ++index;
364    element = iterator->nextElement();
365  }
366
367  printf("\npartition 2:\n");
368  for(int i = 0; i < partition2.getSize(); ++i)
369  {
370    printf("v[%i][0] = %f\n", i, vertList2[i][0]);
371    printf("v[%i][1] = %f\n", i, vertList2[i][1]);
372    printf("v[%i][2] = %f\n", i, vertList2[i][2]);
373  }
374
375  /* now spawn the obb tree: create the nodes and descent */
376  OBBTreeNode*       node1 = new OBBTreeNode();
377  OBBTreeNode*       node2 = new OBBTreeNode();
378
379  this->nodeLeft = node1;
380  this->nodeRight = node2;
381
382  this->nodeLeft->spawnBVTree(depth - 1, vertList1, partition1.getSize());
383  this->nodeRight->spawnBVTree(depth - 1, vertList2, partition2.getSize());
384}
385
386
387void OBBTreeNode::collideWith(const BVTree &tree)
388{}
389
390
391void OBBTreeNode::drawBV(int depth) const
392{
393//   glBegin(GL_LINE_LOOP);
394//   glColor3f(1.0, 1.0, 1.0);
395//   for(int i = 0; i < this->bvElement->numOfVertices; ++i)
396//     {
397//       glVertex3f(this->bvElement->vertices[i][0], this->bvElement->vertices[i][1], this->bvElement->vertices[i][2]);
398//       //printf("v(%f, %f, %f)\n", this->vertices[i][0], this->vertices[i][1], this->vertices[i][2]);
399//     }
400//   glEnd();
401  //this->drawBVPolygon(currentDepth, depth);
402}
403
404
405void OBBTreeNode::drawBVPolygon(int depth) const
406{
407
408  OBBTree::material->select();
409
410  /* draw world axes */
411//   glBegin(GL_LINES);
412//   glColor3f(0.0, 0.4, 0.3);
413//   glVertex3f(0.0, 0.0, 0.0);
414//   glVertex3f(3.0, 0.0, 0.0);
415//
416//   glVertex3f(0.0, 0.0, 0.0);
417//   glVertex3f(0.0, 3.0, 0.0);
418//
419//   glVertex3f(0.0, 0.0, 0.0);
420//   glVertex3f(0.0, 0.0, 3.0);
421//   glEnd();
422
423
424
425  /* draw the obb axes */
426//   glBegin(GL_LINES);
427//   glColor3f(0.0, 0.4, 0.3);
428//   glVertex3f(this->bvElement->center->x, this->bvElement->center->y, this->bvElement->center->z);
429//   glVertex3f(this->bvElement->center->x + this->bvElement->axis[0]->x * this->bvElement->halfLength[0],
430//              this->bvElement->center->y + this->bvElement->axis[0]->y * this->bvElement->halfLength[0],
431//              this->bvElement->center->z + this->bvElement->axis[0]->z * this->bvElement->halfLength[0]);
432//
433//   glVertex3f(this->bvElement->center->x, this->bvElement->center->y, this->bvElement->center->z);
434//   glVertex3f(this->bvElement->center->x + this->bvElement->axis[1]->x * this->bvElement->halfLength[1],
435//              this->bvElement->center->y + this->bvElement->axis[1]->y * this->bvElement->halfLength[1],
436//              this->bvElement->center->z + this->bvElement->axis[1]->z * this->bvElement->halfLength[1]);
437//
438//   glVertex3f(this->bvElement->center->x, this->bvElement->center->y, this->bvElement->center->z);
439//   glVertex3f(this->bvElement->center->x + this->bvElement->axis[2]->x * this->bvElement->halfLength[2],
440//              this->bvElement->center->y + this->bvElement->axis[2]->y * this->bvElement->halfLength[2],
441//              this->bvElement->center->z + this->bvElement->axis[2]->z * this->bvElement->halfLength[2]);
442//   glEnd();
443
444
445  Vector cen = *this->bvElement->center;
446  Vector** axis = this->bvElement->axis;
447  float* len = this->bvElement->halfLength;
448
449  /* draw bounding box */
450  glBegin(GL_LINE_LOOP);
451  glColor3f(0.3, 0.4, 0.7);
452  glVertex3f(cen.x + axis[0]->x * len[0] + axis[1]->x * len[1] + axis[2]->x * len[2],
453             cen.y + axis[0]->y * len[0] + axis[1]->y * len[1] + axis[2]->y * len[2],
454             cen.z + axis[0]->z * len[0] + axis[1]->z * len[1] + axis[2]->z * len[2]);
455  glVertex3f(cen.x + axis[0]->x * len[0] + axis[1]->x * len[1] - axis[2]->x * len[2],
456             cen.y + axis[0]->y * len[0] + axis[1]->y * len[1] - axis[2]->y * len[2],
457             cen.z + axis[0]->z * len[0] + axis[1]->z * len[1] - axis[2]->z * len[2]);
458  glVertex3f(cen.x + axis[0]->x * len[0] - axis[1]->x * len[1] - axis[2]->x * len[2],
459             cen.y + axis[0]->y * len[0] - axis[1]->y * len[1] - axis[2]->y * len[2],
460             cen.z + axis[0]->z * len[0] - axis[1]->z * len[1] - axis[2]->z * len[2]);
461  glVertex3f(cen.x + axis[0]->x * len[0] - axis[1]->x * len[1] + axis[2]->x * len[2],
462             cen.y + axis[0]->y * len[0] - axis[1]->y * len[1] + axis[2]->y * len[2],
463             cen.z + axis[0]->z * len[0] - axis[1]->z * len[1] + axis[2]->z * len[2]);
464  glEnd();
465
466  glBegin(GL_LINE_LOOP);
467  glVertex3f(cen.x + axis[0]->x * len[0] - axis[1]->x * len[1] + axis[2]->x * len[2],
468             cen.y + axis[0]->y * len[0] - axis[1]->y * len[1] + axis[2]->y * len[2],
469             cen.z + axis[0]->z * len[0] - axis[1]->z * len[1] + axis[2]->z * len[2]);
470  glVertex3f(cen.x + axis[0]->x * len[0] - axis[1]->x * len[1] - axis[2]->x * len[2],
471             cen.y + axis[0]->y * len[0] - axis[1]->y * len[1] - axis[2]->y * len[2],
472             cen.z + axis[0]->z * len[0] - axis[1]->z * len[1] - axis[2]->z * len[2]);
473  glVertex3f(cen.x - axis[0]->x * len[0] - axis[1]->x * len[1] - axis[2]->x * len[2],
474             cen.y - axis[0]->y * len[0] - axis[1]->y * len[1] - axis[2]->y * len[2],
475             cen.z - axis[0]->z * len[0] - axis[1]->z * len[1] - axis[2]->z * len[2]);
476  glVertex3f(cen.x - axis[0]->x * len[0] - axis[1]->x * len[1] + axis[2]->x * len[2],
477             cen.y - axis[0]->y * len[0] - axis[1]->y * len[1] + axis[2]->y * len[2],
478             cen.z - axis[0]->z * len[0] - axis[1]->z * len[1] + axis[2]->z * len[2]);
479  glEnd();
480
481  glBegin(GL_LINE_LOOP);
482  glVertex3f(cen.x - axis[0]->x * len[0] - axis[1]->x * len[1] + axis[2]->x * len[2],
483             cen.y - axis[0]->y * len[0] - axis[1]->y * len[1] + axis[2]->y * len[2],
484             cen.z - axis[0]->z * len[0] - axis[1]->z * len[1] + axis[2]->z * len[2]);
485  glVertex3f(cen.x - axis[0]->x * len[0] - axis[1]->x * len[1] - axis[2]->x * len[2],
486             cen.y - axis[0]->y * len[0] - axis[1]->y * len[1] - axis[2]->y * len[2],
487             cen.z - axis[0]->z * len[0] - axis[1]->z * len[1] - axis[2]->z * len[2]);
488  glVertex3f(cen.x - axis[0]->x * len[0] + axis[1]->x * len[1] - axis[2]->x * len[2],
489             cen.y - axis[0]->y * len[0] + axis[1]->y * len[1] - axis[2]->y * len[2],
490             cen.z - axis[0]->z * len[0] + axis[1]->z * len[1] - axis[2]->z * len[2]);
491  glVertex3f(cen.x - axis[0]->x * len[0] + axis[1]->x * len[1] + axis[2]->x * len[2],
492             cen.y - axis[0]->y * len[0] + axis[1]->y * len[1] + axis[2]->y * len[2],
493             cen.z - axis[0]->z * len[0] + axis[1]->z * len[1] + axis[2]->z * len[2]);
494  glEnd();
495
496  glBegin(GL_LINE_LOOP);
497  glVertex3f(cen.x - axis[0]->x * len[0] + axis[1]->x * len[1] - axis[2]->x * len[2],
498             cen.y - axis[0]->y * len[0] + axis[1]->y * len[1] - axis[2]->y * len[2],
499             cen.z - axis[0]->z * len[0] + axis[1]->z * len[1] - axis[2]->z * len[2]);
500  glVertex3f(cen.x - axis[0]->x * len[0] + axis[1]->x * len[1] + axis[2]->x * len[2],
501             cen.y - axis[0]->y * len[0] + axis[1]->y * len[1] + axis[2]->y * len[2],
502             cen.z - axis[0]->z * len[0] + axis[1]->z * len[1] + axis[2]->z * len[2]);
503  glVertex3f(cen.x + axis[0]->x * len[0] + axis[1]->x * len[1] + axis[2]->x * len[2],
504             cen.y + axis[0]->y * len[0] + axis[1]->y * len[1] + axis[2]->y * len[2],
505             cen.z + axis[0]->z * len[0] + axis[1]->z * len[1] + axis[2]->z * len[2]);
506  glVertex3f(cen.x + axis[0]->x * len[0] + axis[1]->x * len[1] - axis[2]->x * len[2],
507             cen.y + axis[0]->y * len[0] + axis[1]->y * len[1] - axis[2]->y * len[2],
508             cen.z + axis[0]->z * len[0] + axis[1]->z * len[1] - axis[2]->z * len[2]);
509  glEnd();
510
511/*
512  glVertex3f(cen.x - axis[0]->x * len[0] + axis[1]->x * len[1] - axis[2]->x * len[2],
513  cen.y - axis[0]->y * len[0] + axis[1]->y * len[1] - axis[2]->y * len[2],
514  cen.z - axis[0]->z * len[0] + axis[1]->z * len[1] - axis[2]->z * len[2]);
515  glVertex3f(cen.x - axis[0]->x * len[0] + axis[1]->x * len[1] + axis[2]->x * len[2],
516  cen.y - axis[0]->y * len[0] + axis[1]->y * len[1] + axis[2]->y * len[2],
517  cen.z - axis[0]->z * len[0] + axis[1]->z * len[1] + axis[2]->z * len[2]);*/
518
519
520  glEnd();
521
522  if( this->nodeLeft != NULL && depth != 0)
523    this->nodeLeft->drawBVPolygon(depth -1);
524  if( this->nodeRight != NULL && depth != 0)
525    this->nodeRight->drawBVPolygon(depth -1);
526
527}
528
529
530void OBBTreeNode::drawBVBlended(int depth) const
531{}
532
533
534void OBBTreeNode::debug()
535{
536
537  /*
538  for(int i = 0; i < length; i++)
539  {
540  printf("vertex %i: %f, %f, %f\n", i, verticesList[i][0], verticesList[i][1], verticesList[i][2]);
541}
542  */
543}
Note: See TracBrowser for help on using the repository browser.