Blender  V2.59
SG_Tree.cpp
Go to the documentation of this file.
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