Blender  V2.59
SG_BBox.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: SG_BBox.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_Node.h"
00040  
00041 SG_BBox::SG_BBox() :
00042         m_min(0., 0., 0.),
00043         m_max(0., 0., 0.)
00044 {
00045 }
00046 
00047 SG_BBox::SG_BBox(const MT_Point3 &min, const MT_Point3 &max) :
00048         m_min(min),
00049         m_max(max)
00050 {
00051 }
00052 
00053 SG_BBox::SG_BBox(const SG_BBox &other, const MT_Transform &world) :
00054         m_min(world(other.m_min)),
00055         m_max(world(other.m_max))
00056 {
00057         *this += world(MT_Point3(m_min[0], m_min[1], m_max[2]));
00058         *this += world(MT_Point3(m_min[0], m_max[1], m_min[2]));
00059         *this += world(MT_Point3(m_min[0], m_max[1], m_max[2]));
00060         *this += world(MT_Point3(m_max[0], m_min[1], m_min[2]));
00061         *this += world(MT_Point3(m_max[0], m_min[1], m_max[2]));
00062         *this += world(MT_Point3(m_max[0], m_max[1], m_min[2]));
00063 }
00064 
00065 SG_BBox::SG_BBox(const SG_BBox &other) :
00066         m_min(other.m_min),
00067         m_max(other.m_max)
00068 {
00069 }
00070 
00071 SG_BBox::~ SG_BBox()
00072 {
00073 }
00074 
00075 SG_BBox& SG_BBox::operator +=(const MT_Point3 &point)
00076 {
00077         if (point[0] < m_min[0])
00078                 m_min[0] = point[0];
00079         else if (point[0] > m_max[0])
00080                 m_max[0] = point[0];
00081 
00082         if (point[1] < m_min[1])
00083                 m_min[1] = point[1];
00084         else if (point[1] > m_max[1])
00085                 m_max[1] = point[1];
00086         
00087         if (point[2] < m_min[2])
00088                 m_min[2] = point[2];
00089         else if (point[2] > m_max[2])
00090                 m_max[2] = point[2];
00091                 
00092         return *this;
00093 }
00094 
00095 SG_BBox& SG_BBox::operator += (const SG_BBox &bbox)
00096 {
00097         *this += bbox.m_min;
00098         *this += bbox.m_max;
00099         
00100         return *this;
00101 }
00102 
00103 SG_BBox SG_BBox::operator +(const SG_BBox &bbox2) const
00104 {
00105         SG_BBox ret = *this;
00106         ret += bbox2;
00107         return ret;
00108 }
00109 
00110 MT_Scalar SG_BBox::volume() const
00111 {
00112         MT_Vector3 size = m_max - m_min;
00113         return size[0]*size[1]*size[2];
00114 }
00115 #if 0
00116 void SG_BBox::translate(const MT_Vector3& dx)
00117 {
00118         m_min += dx;
00119         m_max += dx;
00120 }
00121 
00122 void SG_BBox::scale(const MT_Vector3& size, const MT_Point3& point)
00123 {
00124         MT_Vector3 center = (m_max - m_min)/2. + point;
00125         m_max = (m_max - center)*size;
00126         m_min = (m_min - center)*size;
00127 }
00128 #endif
00129 
00130 SG_BBox SG_BBox::transform(const MT_Transform &world) const
00131 {
00132         SG_BBox bbox(world(m_min), world(m_max));
00133         bbox += world(MT_Point3(m_min[0], m_min[1], m_max[2]));
00134         bbox += world(MT_Point3(m_min[0], m_max[1], m_min[2]));
00135         bbox += world(MT_Point3(m_min[0], m_max[1], m_max[2]));
00136         bbox += world(MT_Point3(m_max[0], m_min[1], m_min[2]));
00137         bbox += world(MT_Point3(m_max[0], m_min[1], m_max[2]));
00138         bbox += world(MT_Point3(m_max[0], m_max[1], m_min[2]));
00139         return bbox;
00140 }
00141 
00142 bool SG_BBox::inside(const MT_Point3 &point) const
00143 {
00144         return point[0] >= m_min[0] && point[0] <= m_max[0] &&
00145             point[1] >= m_min[1] && point[1] <= m_max[1] &&
00146             point[2] >= m_min[2] && point[2] <= m_max[2];
00147 }
00148 
00149 bool SG_BBox::inside(const SG_BBox& other) const
00150 {
00151         return inside(other.m_min) && inside(other.m_max);
00152 }
00153 
00154 bool SG_BBox::intersects(const SG_BBox& other) const
00155 {
00156         return inside(other.m_min) != inside(other.m_max);
00157 }
00158 
00159 bool SG_BBox::outside(const SG_BBox& other) const
00160 {
00161         return !inside(other.m_min) && !inside(other.m_max);
00162 }
00163 
00164 SG_BBox::intersect SG_BBox::test(const SG_BBox& other) const
00165 {
00166         bool point1(inside(other.m_min)), point2(inside(other.m_max));
00167         
00168         return point1?(point2?INSIDE:INTERSECT):(point2?INTERSECT:OUTSIDE);
00169 }
00170 
00171 void SG_BBox::get(MT_Point3 *box, const MT_Transform &world) const
00172 {
00173         *box++ = world(m_min);
00174         *box++ = world(MT_Point3(m_min[0], m_min[1], m_max[2]));
00175         *box++ = world(MT_Point3(m_min[0], m_max[1], m_min[2]));
00176         *box++ = world(MT_Point3(m_min[0], m_max[1], m_max[2]));
00177         *box++ = world(MT_Point3(m_max[0], m_min[1], m_min[2]));
00178         *box++ = world(MT_Point3(m_max[0], m_min[1], m_max[2]));
00179         *box++ = world(MT_Point3(m_max[0], m_max[1], m_min[2]));
00180         *box++ = world(m_max);
00181 }
00182 
00183 void SG_BBox::getaa(MT_Point3 *box, const MT_Transform &world) const
00184 {
00185         const MT_Point3 min(world(m_min)), max(world(m_max));
00186         *box++ = min;
00187         *box++ = MT_Point3(min[0], min[1], max[2]);
00188         *box++ = MT_Point3(min[0], max[1], min[2]);
00189         *box++ = MT_Point3(min[0], max[1], max[2]);
00190         *box++ = MT_Point3(max[0], min[1], min[2]);
00191         *box++ = MT_Point3(max[0], min[1], max[2]);
00192         *box++ = MT_Point3(max[0], max[1], min[2]);
00193         *box++ = max;
00194 }
00195 
00196 void SG_BBox::getmm(MT_Point3 *box, const MT_Transform &world) const
00197 {
00198         const MT_Point3 min(world(m_min)), max(world(m_max));
00199         *box++ = min;
00200         *box++ = max;
00201 }
00202 
00203 void SG_BBox::split(SG_BBox &left, SG_BBox &right) const
00204 {
00205         MT_Scalar sizex = m_max[0] - m_min[0];
00206         MT_Scalar sizey = m_max[1] - m_min[1];
00207         MT_Scalar sizez = m_max[2] - m_min[2];
00208         if (sizex < sizey)
00209         {
00210                 if (sizey > sizez)
00211                 {
00212                         left.m_min = m_min;
00213                         left.m_max[0] = m_max[0];
00214                         left.m_max[1] = m_min[1] + sizey/2.0;
00215                         left.m_max[2] = m_max[2];
00216                         
00217                         right.m_min[0] = m_min[0];
00218                         right.m_min[1] = m_min[1] + sizey/2.0;
00219                         right.m_min[2] = m_min[2];
00220                         right.m_max = m_max;
00221                         std::cout << "splity" << std::endl;
00222                 } else {
00223                         left.m_min = m_min;
00224                         left.m_max[0] = m_max[0];
00225                         left.m_max[1] = m_max[1];
00226                         left.m_max[2] = m_min[2] + sizez/2.0;
00227                 
00228                         right.m_min[0] = m_min[0];
00229                         right.m_min[1] = m_min[1];
00230                         right.m_min[2] = m_min[2] + sizez/2.0;
00231                         right.m_max = m_max;
00232                         std::cout << "splitz" << std::endl;
00233                 }
00234         } else {
00235                 if (sizex > sizez)
00236                 {
00237                         left.m_min = m_min;
00238                         left.m_max[0] = m_min[0] + sizex/2.0;
00239                         left.m_max[1] = m_max[1];
00240                         left.m_max[2] = m_max[2];
00241                         
00242                         right.m_min[0] = m_min[0] + sizex/2.0;
00243                         right.m_min[1] = m_min[1];
00244                         right.m_min[2] = m_min[2];
00245                         right.m_max = m_max;
00246                         std::cout << "splitx" << std::endl;
00247                 } else {
00248                         left.m_min = m_min;
00249                         left.m_max[0] = m_max[0];
00250                         left.m_max[1] = m_max[1];
00251                         left.m_max[2] = m_min[2] + sizez/2.0;
00252                 
00253                         right.m_min[0] = m_min[0];
00254                         right.m_min[1] = m_min[1];
00255                         right.m_min[2] = m_min[2] + sizez/2.0;
00256                         right.m_max = m_max;
00257                         std::cout << "splitz" << std::endl;
00258                 }
00259         }
00260         
00261         //std::cout << "Left: " << left.m_min << " -> " << left.m_max << " Right: " << right.m_min << " -> " << right.m_max << std::endl;
00262 }