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