doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / gameengine / SceneGraph / SG_BBox.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * Bounding Box
29  */
30
31 #include <math.h>
32  
33  #include "SG_BBox.h"
34  #include "SG_Node.h"
35  
36 SG_BBox::SG_BBox() :
37         m_min(0., 0., 0.),
38         m_max(0., 0., 0.)
39 {
40 }
41
42 SG_BBox::SG_BBox(const MT_Point3 &min, const MT_Point3 &max) :
43         m_min(min),
44         m_max(max)
45 {
46 }
47
48 SG_BBox::SG_BBox(const SG_BBox &other, const MT_Transform &world) :
49         m_min(world(other.m_min)),
50         m_max(world(other.m_max))
51 {
52         *this += world(MT_Point3(m_min[0], m_min[1], m_max[2]));
53         *this += world(MT_Point3(m_min[0], m_max[1], m_min[2]));
54         *this += world(MT_Point3(m_min[0], m_max[1], m_max[2]));
55         *this += world(MT_Point3(m_max[0], m_min[1], m_min[2]));
56         *this += world(MT_Point3(m_max[0], m_min[1], m_max[2]));
57         *this += world(MT_Point3(m_max[0], m_max[1], m_min[2]));
58 }
59
60 SG_BBox::SG_BBox(const SG_BBox &other) :
61         m_min(other.m_min),
62         m_max(other.m_max)
63 {
64 }
65
66 SG_BBox::~ SG_BBox()
67 {
68 }
69
70 SG_BBox& SG_BBox::operator +=(const MT_Point3 &point)
71 {
72         if (point[0] < m_min[0])
73                 m_min[0] = point[0];
74         else if (point[0] > m_max[0])
75                 m_max[0] = point[0];
76
77         if (point[1] < m_min[1])
78                 m_min[1] = point[1];
79         else if (point[1] > m_max[1])
80                 m_max[1] = point[1];
81         
82         if (point[2] < m_min[2])
83                 m_min[2] = point[2];
84         else if (point[2] > m_max[2])
85                 m_max[2] = point[2];
86                 
87         return *this;
88 }
89
90 SG_BBox& SG_BBox::operator += (const SG_BBox &bbox)
91 {
92         *this += bbox.m_min;
93         *this += bbox.m_max;
94         
95         return *this;
96 }
97
98 SG_BBox SG_BBox::operator +(const SG_BBox &bbox2) const
99 {
100         SG_BBox ret = *this;
101         ret += bbox2;
102         return ret;
103 }
104
105 MT_Scalar SG_BBox::volume() const
106 {
107         MT_Vector3 size = m_max - m_min;
108         return size[0]*size[1]*size[2];
109 }
110 #if 0
111 void SG_BBox::translate(const MT_Vector3& dx)
112 {
113         m_min += dx;
114         m_max += dx;
115 }
116
117 void SG_BBox::scale(const MT_Vector3& size, const MT_Point3& point)
118 {
119         MT_Vector3 center = (m_max - m_min)/2. + point;
120         m_max = (m_max - center)*size;
121         m_min = (m_min - center)*size;
122 }
123 #endif
124
125 SG_BBox SG_BBox::transform(const MT_Transform &world) const
126 {
127         SG_BBox bbox(world(m_min), world(m_max));
128         bbox += world(MT_Point3(m_min[0], m_min[1], m_max[2]));
129         bbox += world(MT_Point3(m_min[0], m_max[1], m_min[2]));
130         bbox += world(MT_Point3(m_min[0], m_max[1], m_max[2]));
131         bbox += world(MT_Point3(m_max[0], m_min[1], m_min[2]));
132         bbox += world(MT_Point3(m_max[0], m_min[1], m_max[2]));
133         bbox += world(MT_Point3(m_max[0], m_max[1], m_min[2]));
134         return bbox;
135 }
136
137 bool SG_BBox::inside(const MT_Point3 &point) const
138 {
139         return point[0] >= m_min[0] && point[0] <= m_max[0] &&
140             point[1] >= m_min[1] && point[1] <= m_max[1] &&
141             point[2] >= m_min[2] && point[2] <= m_max[2];
142 }
143
144 bool SG_BBox::inside(const SG_BBox& other) const
145 {
146         return inside(other.m_min) && inside(other.m_max);
147 }
148
149 bool SG_BBox::intersects(const SG_BBox& other) const
150 {
151         return inside(other.m_min) != inside(other.m_max);
152 }
153
154 bool SG_BBox::outside(const SG_BBox& other) const
155 {
156         return !inside(other.m_min) && !inside(other.m_max);
157 }
158
159 SG_BBox::intersect SG_BBox::test(const SG_BBox& other) const
160 {
161         bool point1(inside(other.m_min)), point2(inside(other.m_max));
162         
163         return point1?(point2?INSIDE:INTERSECT):(point2?INTERSECT:OUTSIDE);
164 }
165
166 void SG_BBox::get(MT_Point3 *box, const MT_Transform &world) const
167 {
168         *box++ = world(m_min);
169         *box++ = world(MT_Point3(m_min[0], m_min[1], m_max[2]));
170         *box++ = world(MT_Point3(m_min[0], m_max[1], m_min[2]));
171         *box++ = world(MT_Point3(m_min[0], m_max[1], m_max[2]));
172         *box++ = world(MT_Point3(m_max[0], m_min[1], m_min[2]));
173         *box++ = world(MT_Point3(m_max[0], m_min[1], m_max[2]));
174         *box++ = world(MT_Point3(m_max[0], m_max[1], m_min[2]));
175         *box++ = world(m_max);
176 }
177
178 void SG_BBox::getaa(MT_Point3 *box, const MT_Transform &world) const
179 {
180         const MT_Point3 min(world(m_min)), max(world(m_max));
181         *box++ = min;
182         *box++ = MT_Point3(min[0], min[1], max[2]);
183         *box++ = MT_Point3(min[0], max[1], min[2]);
184         *box++ = MT_Point3(min[0], max[1], max[2]);
185         *box++ = MT_Point3(max[0], min[1], min[2]);
186         *box++ = MT_Point3(max[0], min[1], max[2]);
187         *box++ = MT_Point3(max[0], max[1], min[2]);
188         *box++ = max;
189 }
190
191 void SG_BBox::getmm(MT_Point3 *box, const MT_Transform &world) const
192 {
193         const MT_Point3 min(world(m_min)), max(world(m_max));
194         *box++ = min;
195         *box++ = max;
196 }
197
198 void SG_BBox::split(SG_BBox &left, SG_BBox &right) const
199 {
200         MT_Scalar sizex = m_max[0] - m_min[0];
201         MT_Scalar sizey = m_max[1] - m_min[1];
202         MT_Scalar sizez = m_max[2] - m_min[2];
203         if (sizex < sizey)
204         {
205                 if (sizey > sizez)
206                 {
207                         left.m_min = m_min;
208                         left.m_max[0] = m_max[0];
209                         left.m_max[1] = m_min[1] + sizey/2.0;
210                         left.m_max[2] = m_max[2];
211                         
212                         right.m_min[0] = m_min[0];
213                         right.m_min[1] = m_min[1] + sizey/2.0;
214                         right.m_min[2] = m_min[2];
215                         right.m_max = m_max;
216                         std::cout << "splity" << std::endl;
217                 } else {
218                         left.m_min = m_min;
219                         left.m_max[0] = m_max[0];
220                         left.m_max[1] = m_max[1];
221                         left.m_max[2] = m_min[2] + sizez/2.0;
222                 
223                         right.m_min[0] = m_min[0];
224                         right.m_min[1] = m_min[1];
225                         right.m_min[2] = m_min[2] + sizez/2.0;
226                         right.m_max = m_max;
227                         std::cout << "splitz" << std::endl;
228                 }
229         } else {
230                 if (sizex > sizez)
231                 {
232                         left.m_min = m_min;
233                         left.m_max[0] = m_min[0] + sizex/2.0;
234                         left.m_max[1] = m_max[1];
235                         left.m_max[2] = m_max[2];
236                         
237                         right.m_min[0] = m_min[0] + sizex/2.0;
238                         right.m_min[1] = m_min[1];
239                         right.m_min[2] = m_min[2];
240                         right.m_max = m_max;
241                         std::cout << "splitx" << std::endl;
242                 } else {
243                         left.m_min = m_min;
244                         left.m_max[0] = m_max[0];
245                         left.m_max[1] = m_max[1];
246                         left.m_max[2] = m_min[2] + sizez/2.0;
247                 
248                         right.m_min[0] = m_min[0];
249                         right.m_min[1] = m_min[1];
250                         right.m_min[2] = m_min[2] + sizez/2.0;
251                         right.m_max = m_max;
252                         std::cout << "splitz" << std::endl;
253                 }
254         }
255         
256         //std::cout << "Left: " << left.m_min << " -> " << left.m_max << " Right: " << right.m_min << " -> " << right.m_max << std::endl;
257 }