| [4790] | 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 |  | 
|---|
| [4924] | 11 | ### File Specific: | 
|---|
| [4790] | 12 |    main-programmer: Patrick Boenzli | 
|---|
 | 13 |    co-programmer: ... | 
|---|
 | 14 | */ | 
|---|
 | 15 |  | 
|---|
| [4808] | 16 | #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SPATIAL_SEPARATION | 
|---|
| [4790] | 17 |  | 
|---|
 | 18 | #include "quadtree.h" | 
|---|
| [4923] | 19 |  | 
|---|
| [4845] | 20 | #include "quadtree_node.h" | 
|---|
| [4917] | 21 | #include "vector.h" | 
|---|
| [4790] | 22 |  | 
|---|
| [4924] | 23 | #include "material.h" | 
|---|
| [5075] | 24 | #include "debug.h" | 
|---|
| [4924] | 25 |  | 
|---|
| [4790] | 26 | using namespace std; | 
|---|
| [5218] | 27 | #define QUADTREE_MATERIAL_COUNT       4 | 
|---|
| [4790] | 28 |  | 
|---|
 | 29 | /** | 
|---|
| [4836] | 30 |  *  standard constructor | 
|---|
| [4924] | 31 |  */ | 
|---|
| [5430] | 32 | Quadtree::Quadtree (const modelInfo* pModelInfo, const int treeDepth) | 
|---|
| [4790] | 33 | { | 
|---|
| [4924] | 34 |   this->setClassID(CL_QUADTREE, "Quadtree"); | 
|---|
 | 35 |   this->pModelInfo = pModelInfo; | 
|---|
 | 36 |   this->treeDepth = treeDepth; | 
|---|
| [4845] | 37 |  | 
|---|
| [4924] | 38 |   /* initialize the materials for debug draw */ | 
|---|
| [5218] | 39 |   this->materials = new Material*[QUADTREE_MATERIAL_COUNT]; | 
|---|
 | 40 |   for(int i = 0; i < QUADTREE_MATERIAL_COUNT; ++i) | 
|---|
| [4924] | 41 |   { | 
|---|
 | 42 |     materials[i] = new Material(); | 
|---|
 | 43 |     materials[i]->setIllum(3); | 
|---|
 | 44 |   } | 
|---|
 | 45 |   materials[0]->setAmbient(0.0, 0.3, 0.0); | 
|---|
 | 46 |   materials[1]->setAmbient(0.4, 0.0, 0.2); | 
|---|
 | 47 |   materials[2]->setAmbient(1.0, 0.0, 0.0); | 
|---|
 | 48 |   materials[3]->setAmbient(5.0, 3.0, 1.0); | 
|---|
| [4901] | 49 |  | 
|---|
| [4924] | 50 |   /* build the tree */ | 
|---|
 | 51 |   this->rootNode = new QuadtreeNode(this->pModelInfo, this, this->treeDepth); | 
|---|
| [4901] | 52 |  | 
|---|
| [4924] | 53 |   /* make an array with access to the leafs of the Quad-Tree */ | 
|---|
 | 54 |   this->nodes = new QuadtreeNode*[(int)pow(4, treeDepth)]; | 
|---|
| [5215] | 55 |   int index = 0; //new int; *index = 0; // !!changed by bensch!! | 
|---|
| [4924] | 56 |   for(int i = 0; i < (int)pow(2, treeDepth); ++i) | 
|---|
 | 57 |   { | 
|---|
| [5215] | 58 |     this->rootNode->buildHashTable(this->nodes, &index); | 
|---|
| [4924] | 59 |   } | 
|---|
 | 60 |   /* sort and revert the hash table to fit the right position */ | 
|---|
 | 61 |   this->sortHashTable(this->nodes); | 
|---|
 | 62 |   this->revertHashTable(this->nodes); | 
|---|
| [4920] | 63 |  | 
|---|
| [4924] | 64 |   /* define some important and often used variables */ | 
|---|
 | 65 |   this->quadLength = this->nodes[0]->getDimension()->getAxis() * 2.0f; | 
|---|
 | 66 |   Rectangle* r = this->rootNode->getDimension(); | 
|---|
| [5215] | 67 |   float xOff = r->getCenter().x - r->getAxis(); | 
|---|
 | 68 |   float yOff = r->getCenter().z - r->getAxis(); | 
|---|
| [4925] | 69 |   this->offset = new Vector(); | 
|---|
| [4924] | 70 |   this->offset->x = xOff; | 
|---|
 | 71 |   this->offset->z = yOff; | 
|---|
 | 72 |   this->maxIndex = (int)pow(2, this->treeDepth); | 
|---|
| [4790] | 73 | } | 
|---|
 | 74 |  | 
|---|
 | 75 |  | 
|---|
 | 76 | /** | 
|---|
| [4836] | 77 |  *  standard deconstructor | 
|---|
| [4924] | 78 |  */ | 
|---|
| [4790] | 79 | Quadtree::~Quadtree () | 
|---|
 | 80 | { | 
|---|
 | 81 |   // delete what has to be deleted here | 
|---|
| [5218] | 82 |   if (this->materials != NULL) | 
|---|
 | 83 |   { | 
|---|
 | 84 |     for (unsigned int i = 0; i < QUADTREE_MATERIAL_COUNT; i++) | 
|---|
 | 85 |       delete this->materials[i]; | 
|---|
| [5219] | 86 |     delete[] this->materials; | 
|---|
| [5218] | 87 |   } | 
|---|
 | 88 |  | 
|---|
| [5233] | 89 |   delete this->offset; | 
|---|
 | 90 |  | 
|---|
| [4907] | 91 |   delete this->rootNode; | 
|---|
| [5234] | 92 |   delete [] this->nodes; | 
|---|
| [4790] | 93 | } | 
|---|
| [4812] | 94 |  | 
|---|
 | 95 |  | 
|---|
 | 96 | /** | 
|---|
| [4924] | 97 |  *  this function rotates the array and mirrors it in the middle | 
|---|
 | 98 |  * @param nodes: the nodes to translate | 
|---|
| [4915] | 99 |  | 
|---|
 | 100 |   since the original matrix is counted from the right upper edge to the right lower one, we have to reorganize the elements | 
|---|
 | 101 |   to be able to easily correlate the hashtable array indexes with the coorindates. | 
|---|
 | 102 |  */ | 
|---|
 | 103 | void Quadtree::revertHashTable(QuadtreeNode** nodes) | 
|---|
 | 104 | { | 
|---|
 | 105 |   int                  len         = (int)pow(2, this->treeDepth);          //!< the length of a quadtree side | 
|---|
 | 106 |   int                  iterator    = 0;                                     //!< iterator used for mapping | 
|---|
 | 107 |   QuadtreeNode*        tmpNode     = NULL;                                  //!< temp saving place | 
|---|
 | 108 |   int                  offset      = 0;                                     //!< offset used in the calc | 
|---|
 | 109 |  | 
|---|
 | 110 |   for(int i = len - 1; i >= 0; --i) | 
|---|
 | 111 |   { | 
|---|
 | 112 |     for(int j = len - 1; j >= 0; --j) | 
|---|
 | 113 |     { | 
|---|
 | 114 |       offset = j * len + i; | 
|---|
 | 115 |       /* only swap the elements in one direction */ | 
|---|
 | 116 |       if( offset > iterator) | 
|---|
 | 117 |       { | 
|---|
 | 118 |         tmpNode = nodes[offset]; | 
|---|
 | 119 |         nodes[offset] = nodes[iterator]; | 
|---|
 | 120 |         nodes[iterator] = tmpNode; | 
|---|
 | 121 |       } | 
|---|
 | 122 |       ++iterator; | 
|---|
 | 123 |     } | 
|---|
 | 124 |   } | 
|---|
 | 125 | } | 
|---|
 | 126 |  | 
|---|
| [4924] | 127 |  | 
|---|
| [4922] | 128 | /** | 
|---|
| [4924] | 129 |  *  sorts the hash table using their positions | 
|---|
 | 130 |  * @param nodes the nodes to use | 
|---|
| [4922] | 131 |  */ | 
|---|
| [4920] | 132 | void Quadtree::sortHashTable(QuadtreeNode** nodes) | 
|---|
 | 133 | { | 
|---|
 | 134 |   int                  len         = (int)pow(2, this->treeDepth);          //!< the length of a quadtree side | 
|---|
| [4922] | 135 |   float                a;                                                   //!< temp place for float a | 
|---|
 | 136 |   float                b;                                                   //!< temp place for float b | 
|---|
 | 137 |   QuadtreeNode*        tmpNode;                                             //!< tmp place for a QuadtreeNode | 
|---|
| [4920] | 138 |  | 
|---|
| [4922] | 139 |   for( int i = 0; i < len; ++i) | 
|---|
| [4920] | 140 |   { | 
|---|
| [4922] | 141 |     for( int j = 0; j < len; ++j) | 
|---|
| [4920] | 142 |     { | 
|---|
| [4922] | 143 |       for( int k = j + 1; k < len; ++k) | 
|---|
| [4920] | 144 |       { | 
|---|
| [5215] | 145 |         a = this->nodes[i * len + j]->getDimension()->getCenter().z; | 
|---|
 | 146 |         b = this->nodes[i * len + k]->getDimension()->getCenter().z; | 
|---|
| [4920] | 147 |  | 
|---|
 | 148 |         if( b > a) | 
|---|
 | 149 |         { | 
|---|
 | 150 |           tmpNode = this->nodes[i * len + j]; | 
|---|
 | 151 |           this->nodes[i * len + j] = this->nodes[i * len + k]; | 
|---|
 | 152 |           this->nodes[i * len + k] = tmpNode; | 
|---|
 | 153 |         } | 
|---|
 | 154 |       } | 
|---|
 | 155 |     } | 
|---|
| [4922] | 156 |   } | 
|---|
| [4920] | 157 |  | 
|---|
 | 158 | } | 
|---|
 | 159 |  | 
|---|
 | 160 |  | 
|---|
| [4922] | 161 | /** | 
|---|
| [4924] | 162 |  *  maps a position to a quadtree | 
|---|
 | 163 |  * @param position the position so look for | 
|---|
 | 164 |  * @return the quadtree | 
|---|
| [4920] | 165 |  | 
|---|
| [4922] | 166 |   this function will return the quadtree that contains the position | 
|---|
 | 167 |  */ | 
|---|
| [4956] | 168 | QuadtreeNode* Quadtree::getQuadtreeFromPosition(const Vector& position) const | 
|---|
| [4917] | 169 | { | 
|---|
| [4920] | 170 |   /* shift into model space */ | 
|---|
| [4922] | 171 |   Vector v = position - *this->offset; | 
|---|
| [4920] | 172 |   /* map */ | 
|---|
| [4922] | 173 |   int i = (int)(v.x / quadLength); | 
|---|
 | 174 |   int j = (int)(v.z / quadLength); | 
|---|
| [4917] | 175 |  | 
|---|
| [4929] | 176 |   /* check if object is still inside the terrain - this check is not complete @todo check all 4 bounds */ | 
|---|
| [4968] | 177 |   if( i < this->maxIndex && j < this->maxIndex && i >= 0 && j >= 0) | 
|---|
 | 178 |     return this->nodes[i + j * this->maxIndex]; | 
|---|
 | 179 |  | 
|---|
 | 180 |  | 
|---|
 | 181 |   PRINTF(4)("Object has left terrain\n"); | 
|---|
 | 182 |   return NULL; | 
|---|
| [4917] | 183 | } | 
|---|
 | 184 |  | 
|---|
 | 185 |  | 
|---|
| [4915] | 186 | /** | 
|---|
| [4929] | 187 |  *  maps a position to a triangle | 
|---|
 | 188 |  * @param position the position so look for | 
|---|
 | 189 |  * @return the triangle | 
|---|
 | 190 |  | 
|---|
 | 191 |   this function will return the quadtree that contains the position | 
|---|
 | 192 |  */ | 
|---|
| [4956] | 193 | sTriangleExt* Quadtree::getTriangleFromPosition(const Vector& position) const | 
|---|
| [4929] | 194 | { | 
|---|
 | 195 |   QuadtreeNode* q = this->getQuadtreeFromPosition(position); | 
|---|
| [4968] | 196 |  | 
|---|
 | 197 |   if( likely(q != NULL)) | 
|---|
 | 198 |     return q->getTriangle(position - *this->offset); | 
|---|
 | 199 |   return NULL; | 
|---|
| [4929] | 200 | } | 
|---|
 | 201 |  | 
|---|
 | 202 |  | 
|---|
 | 203 | /** | 
|---|
| [4836] | 204 |  *  draws the debug quadtree boxes around the model | 
|---|
| [4812] | 205 |  */ | 
|---|
| [4922] | 206 | void Quadtree::drawTree() const | 
|---|
| [4889] | 207 | { | 
|---|
| [4925] | 208 |   //this->rootNode->drawTree(); | 
|---|
 | 209 |   for(int i = 0; i < (int)pow(4, this->treeDepth); ++i) | 
|---|
 | 210 |   { | 
|---|
 | 211 |     this->nodes[i]->draw(); | 
|---|
 | 212 |   } | 
|---|
| [4889] | 213 | } | 
|---|