|
Blender
V2.59
|
00001 /* 00002 * $Id: SG_Tree.cpp 35175 2011-02-25 13:39:04Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * Bounding Box 00029 */ 00030 00036 #include <math.h> 00037 00038 #include "SG_BBox.h" 00039 #include "SG_Tree.h" 00040 #include "SG_Node.h" 00041 00042 SG_Tree::SG_Tree() 00043 { 00044 } 00045 00046 SG_Tree::SG_Tree(SG_Tree* left, SG_Tree* right) : 00047 m_left(left), 00048 m_right(right), 00049 m_client_object(NULL) 00050 { 00051 if (m_left) 00052 { 00053 m_bbox = m_left->m_bbox; 00054 m_left->m_parent = this; 00055 } 00056 if (m_right) 00057 { 00058 m_bbox += m_right->m_bbox; 00059 m_right->m_parent = this; 00060 } 00061 m_center = (m_bbox.m_min + m_bbox.m_max)/2.0; 00062 m_radius = (m_bbox.m_max - m_bbox.m_min).length(); 00063 } 00064 00065 SG_Tree::SG_Tree(SG_Node* client) : 00066 m_left(NULL), 00067 m_right(NULL), 00068 m_client_object(client) 00069 { 00070 m_bbox = SG_BBox(client->BBox(), client->GetWorldTransform()); 00071 m_center = (m_bbox.m_min + m_bbox.m_max)/2.0; 00072 m_radius = (m_bbox.m_max - m_bbox.m_min).length(); 00073 } 00074 00075 SG_Tree::~SG_Tree() 00076 { 00077 } 00078 00079 MT_Scalar SG_Tree::volume() const 00080 { 00081 return m_bbox.volume(); 00082 } 00083 00084 void SG_Tree::dump() const 00085 { 00086 if (m_left) 00087 m_left->dump(); 00088 if (m_client_object) 00089 std::cout << m_client_object << std::endl; 00090 else 00091 std::cout << this << " "; 00092 if (m_right) 00093 m_right->dump(); 00094 } 00095 00096 SG_Tree* SG_Tree::Left() const 00097 { 00098 return m_left; 00099 } 00100 00101 SG_Tree* SG_Tree::Right() const 00102 { 00103 return m_right; 00104 } 00105 00106 SG_Node* SG_Tree::Client() const 00107 { 00108 return m_client_object; 00109 } 00110 00111 SG_Tree* SG_Tree::Find(SG_Node *node) 00112 { 00113 if (m_client_object == node) 00114 return this; 00115 00116 SG_Tree *left = m_left, *right = m_right; 00117 00118 if (left && right) 00119 { 00120 if (right->m_bbox.intersects(node->BBox())) 00121 std::swap(left, right); 00122 } 00123 00124 if (left) 00125 { 00126 SG_Tree* ret = left->Find(node); 00127 if (ret) return ret; 00128 } 00129 00130 if (right) 00131 { 00132 SG_Tree* ret = right->Find(node); 00133 if (ret) return ret; 00134 } 00135 00136 return NULL; 00137 } 00138 00139 void SG_Tree::get(MT_Point3 *box) const 00140 { 00141 MT_Transform identity; 00142 identity.setIdentity(); 00143 m_bbox.get(box, identity); 00144 } 00145 00146 bool SG_Tree::inside(const MT_Point3 &point) const 00147 { 00148 return m_bbox.inside(point); 00149 } 00150 00151 const SG_BBox& SG_Tree::BBox() const 00152 { 00153 return m_bbox; 00154 } 00155 00156 void SG_Tree::SetLeft(SG_Tree *left) 00157 { 00158 m_left = left; 00159 m_bbox += left->m_bbox; 00160 m_center = (m_bbox.m_min + m_bbox.m_max)/2.0; 00161 m_radius = (m_bbox.m_max - m_bbox.m_min).length(); 00162 } 00163 00164 void SG_Tree::SetRight(SG_Tree *right) 00165 { 00166 m_right = right; 00167 m_bbox += right->m_bbox; 00168 m_center = (m_bbox.m_min + m_bbox.m_max)/2.0; 00169 m_radius = (m_bbox.m_max - m_bbox.m_min).length(); 00170 } 00171 00176 template<typename T> 00177 class HalfArray 00178 { 00179 std::vector<std::vector<T> > m_array; 00180 public: 00181 HalfArray() {} 00182 ~HalfArray() {} 00183 00184 void resize(unsigned int size) 00185 { 00186 m_array.resize(size); 00187 for( unsigned int i = 0; i < size; i++) 00188 { 00189 m_array[i].resize(size - i); 00190 } 00191 } 00192 00193 T& operator() (unsigned int x, unsigned int y) 00194 { 00195 assert(x >= y); 00196 return m_array[y][x - y]; 00197 } 00198 00199 void erase_column (unsigned int x) 00200 { 00201 for (unsigned int y = 0; y <= x; y++) 00202 m_array[y].erase(m_array[y].begin() + x - y); 00203 } 00204 00205 void delete_column (unsigned int x) 00206 { 00207 for (unsigned int y = 0; y < x; y++) 00208 { 00209 delete m_array[y][x - y]; 00210 m_array[y].erase(m_array[y].begin() + x - y); 00211 } 00212 } 00213 00214 void erase_row (unsigned int y) 00215 { 00216 m_array.erase(m_array.begin() + y); 00217 } 00218 }; 00219 00220 SG_TreeFactory::SG_TreeFactory() 00221 { 00222 } 00223 00224 SG_TreeFactory::~SG_TreeFactory() 00225 { 00226 } 00227 00228 void SG_TreeFactory::Add(SG_Node* client) 00229 { 00230 if (client) 00231 m_objects.insert(new SG_Tree(client)); 00232 } 00233 00234 void SG_TreeFactory::Add(SG_Tree* tree) 00235 { 00236 m_objects.insert(tree); 00237 } 00238 00239 SG_Tree* SG_TreeFactory::MakeTreeDown(SG_BBox &bbox) 00240 { 00241 if (m_objects.size() == 0) 00242 return NULL; 00243 if (m_objects.size() == 1) 00244 return *m_objects.begin(); 00245 00246 TreeSet::iterator it = m_objects.begin(); 00247 SG_Tree *root = *it; 00248 if (m_objects.size() == 2) 00249 { 00250 root->SetRight(*(++it)); 00251 return root; 00252 } 00253 00254 if (m_objects.size() == 3) 00255 { 00256 root->SetLeft(*(++it)); 00257 root->SetRight(*(++it)); 00258 return root; 00259 } 00260 00261 if (bbox.volume() < 1.0) 00262 return MakeTreeUp(); 00263 00264 SG_TreeFactory lefttree; 00265 SG_TreeFactory righttree; 00266 00267 SG_BBox left, right; 00268 int hasleft = 0, hasright = 0; 00269 bbox.split(left, right); 00270 00271 if (left.test(root->BBox()) == SG_BBox::INSIDE) 00272 { 00273 lefttree.Add(root); 00274 root = NULL; 00275 } 00276 00277 if (root && right.test(root->BBox()) == SG_BBox::INSIDE) 00278 { 00279 righttree.Add(root); 00280 root = NULL; 00281 } 00282 00283 for (++it; it != m_objects.end(); ++it) 00284 { 00285 switch (left.test((*it)->BBox())) 00286 { 00287 case SG_BBox::INSIDE: 00288 // Object is inside left tree; 00289 lefttree.Add(*it); 00290 hasleft++; 00291 break; 00292 case SG_BBox::OUTSIDE: 00293 righttree.Add(*it); 00294 hasright++; 00295 break; 00296 case SG_BBox::INTERSECT: 00297 if (left.inside((*it)->Client()->GetWorldPosition())) 00298 { 00299 lefttree.Add(*it); 00300 hasleft++; 00301 } else { 00302 righttree.Add(*it); 00303 hasright++; 00304 } 00305 break; 00306 } 00307 } 00308 std::cout << "Left: " << hasleft << " Right: " << hasright << " Count: " << m_objects.size() << std::endl; 00309 00310 SG_Tree *leftnode = NULL; 00311 if (hasleft) 00312 leftnode = lefttree.MakeTreeDown(left); 00313 00314 SG_Tree *rightnode = NULL; 00315 if (hasright) 00316 rightnode = righttree.MakeTreeDown(right); 00317 00318 if (!root) 00319 root = new SG_Tree(leftnode, rightnode); 00320 else 00321 { 00322 if (leftnode) 00323 root->SetLeft(leftnode); 00324 if (rightnode) 00325 root->SetRight(rightnode); 00326 } 00327 00328 return root; 00329 } 00330 00331 SG_Tree* SG_TreeFactory::MakeTree() 00332 { 00333 if (m_objects.size() < 8) 00334 return MakeTreeUp(); 00335 00336 TreeSet::iterator it = m_objects.begin(); 00337 SG_BBox bbox((*it)->BBox()); 00338 for (++it; it != m_objects.end(); ++it) 00339 bbox += (*it)->BBox(); 00340 00341 return MakeTreeDown(bbox); 00342 } 00343 00344 SG_Tree* SG_TreeFactory::MakeTreeUp() 00345 { 00346 unsigned int num_objects = m_objects.size(); 00347 00348 if (num_objects < 1) 00349 return NULL; 00350 if (num_objects < 2) 00351 return *m_objects.begin(); 00352 00353 HalfArray<SG_Tree*> sizes; 00354 sizes.resize(num_objects); 00355 00356 unsigned int x, y; 00357 TreeSet::iterator xit, yit; 00358 for( y = 0, yit = m_objects.begin(); y < num_objects; y++, ++yit) 00359 { 00360 sizes(y, y) = *yit; 00361 xit = yit; 00362 for( x = y+1, ++xit; x < num_objects; x++, ++xit) 00363 { 00364 sizes(x, y) = new SG_Tree(*xit, *yit); 00365 00366 } 00367 } 00368 while (num_objects > 2) 00369 { 00370 /* Find the pair of bboxes that produce the smallest combined bbox. */ 00371 unsigned int minx = UINT_MAX, miny = UINT_MAX; 00372 MT_Scalar min_volume = FLT_MAX; 00373 SG_Tree *min = NULL; 00374 //char temp[16]; 00375 for( y = 0; y < num_objects; y++) 00376 { 00377 for( x = y+1; x < num_objects; x++) 00378 { 00379 if (sizes(x, y)->volume() < min_volume) 00380 { 00381 min = sizes(x, y); 00382 minx = x; 00383 miny = y; 00384 min_volume = sizes(x, y)->volume(); 00385 } 00386 } 00387 } 00388 00389 /* Remove other bboxes that contain the two bboxes */ 00390 sizes.delete_column(miny); 00391 00392 for( x = miny + 1; x < num_objects; x++) 00393 { 00394 if (x == minx) 00395 continue; 00396 delete sizes(x, miny); 00397 } 00398 sizes.erase_row(miny); 00399 00400 num_objects--; 00401 minx--; 00402 sizes(minx, minx) = min; 00403 for( x = minx + 1; x < num_objects; x++) 00404 { 00405 delete sizes(x, minx); 00406 sizes(x, minx) = new SG_Tree(min, sizes(x, x)); 00407 } 00408 for( y = 0; y < minx; y++) 00409 { 00410 delete sizes(minx, y); 00411 sizes(minx, y) = new SG_Tree(sizes(y, y), min); 00412 } 00413 } 00414 return sizes(1, 0); 00415 } 00416