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