Blender V2.61 - r43446

SG_Tree.cpp

Go to the documentation of this file.
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