doxygen: gameengine/SceneGraph tagged.
[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 /** \file gameengine/SceneGraph/SG_BBox.cpp
32  *  \ingroup bgesg
33  */
34
35
36 #include <math.h>
37  
38  #include "SG_BBox.h"
39  #include "SG_Node.h"
40  
41 SG_BBox::SG_BBox() :
42         m_min(0., 0., 0.),
43         m_max(0., 0., 0.)
44 {
45 }
46
47 SG_BBox::SG_BBox(const MT_Point3 &min, const MT_Point3 &max) :
48         m_min(min),
49         m_max(max)
50 {
51 }
52
53 SG_BBox::SG_BBox(const SG_BBox &other, const MT_Transform &world) :
54         m_min(world(other.m_min)),
55         m_max(world(other.m_max))
56 {
57         *this += world(MT_Point3(m_min[0], m_min[1], m_max[2]));
58         *this += world(MT_Point3(m_min[0], m_max[1], m_min[2]));
59         *this += world(MT_Point3(m_min[0], m_max[1], m_max[2]));
60         *this += world(MT_Point3(m_max[0], m_min[1], m_min[2]));
61         *this += world(MT_Point3(m_max[0], m_min[1], m_max[2]));
62         *this += world(MT_Point3(m_max[0], m_max[1], m_min[2]));
63 }
64
65 SG_BBox::SG_BBox(const SG_BBox &other) :
66         m_min(other.m_min),
67         m_max(other.m_max)
68 {
69 }
70
71 SG_BBox::~ SG_BBox()
72 {
73 }
74
75 SG_BBox& SG_BBox::operator +=(const MT_Point3 &point)
76 {
77         if (point[0] < m_min[0])
78                 m_min[0] = point[0];
79         else if (point[0] > m_max[0])
80                 m_max[0] = point[0];
81
82         if (point[1] < m_min[1])
83                 m_min[1] = point[1];
84         else if (point[1] > m_max[1])
85                 m_max[1] = point[1];
86         
87         if (point[2] < m_min[2])
88                 m_min[2] = point[2];
89         else if (point[2] > m_max[2])
90                 m_max[2] = point[2];
91                 
92         return *this;
93 }
94
95 SG_BBox& SG_BBox::operator += (const SG_BBox &bbox)
96 {
97         *this += bbox.m_min;
98         *this += bbox.m_max;
99         
100         return *this;
101 }
102
103 SG_BBox SG_BBox::operator +(const SG_BBox &bbox2) const
104 {
105         SG_BBox ret = *this;
106         ret += bbox2;
107         return ret;
108 }
109
110 MT_Scalar SG_BBox::volume() const
111 {
112         MT_Vector3 size = m_max - m_min;
113         return size[0]*size[1]*size[2];
114 }
115 #if 0
116 void SG_BBox::translate(const MT_Vector3& dx)
117 {
118         m_min += dx;
119         m_max += dx;
120 }
121
122 void SG_BBox::scale(const MT_Vector3& size, const MT_Point3& point)
123 {
124         MT_Vector3 center = (m_max - m_min)/2. + point;
125         m_max = (m_max - center)*size;
126         m_min = (m_min - center)*size;
127 }
128 #endif
129
130 SG_BBox SG_BBox::transform(const MT_Transform &world) const
131 {
132         SG_BBox bbox(world(m_min), world(m_max));
133         bbox += world(MT_Point3(m_min[0], m_min[1], m_max[2]));
134         bbox += world(MT_Point3(m_min[0], m_max[1], m_min[2]));
135         bbox += world(MT_Point3(m_min[0], m_max[1], m_max[2]));
136         bbox += world(MT_Point3(m_max[0], m_min[1], m_min[2]));
137         bbox += world(MT_Point3(m_max[0], m_min[1], m_max[2]));
138         bbox += world(MT_Point3(m_max[0], m_max[1], m_min[2]));
139         return bbox;
140 }
141
142 bool SG_BBox::inside(const MT_Point3 &point) const
143 {
144         return point[0] >= m_min[0] && point[0] <= m_max[0] &&
145             point[1] >= m_min[1] && point[1] <= m_max[1] &&
146             point[2] >= m_min[2] && point[2] <= m_max[2];
147 }
148
149 bool SG_BBox::inside(const SG_BBox& other) const
150 {
151         return inside(other.m_min) && inside(other.m_max);
152 }
153
154 bool SG_BBox::intersects(const SG_BBox& other) const
155 {
156         return inside(other.m_min) != inside(other.m_max);
157 }
158
159 bool SG_BBox::outside(const SG_BBox& other) const
160 {
161         return !inside(other.m_min) && !inside(other.m_max);
162 }
163
164 SG_BBox::intersect SG_BBox::test(const SG_BBox& other) const
165 {
166         bool point1(inside(other.m_min)), point2(inside(other.m_max));
167         
168         return point1?(point2?INSIDE:INTERSECT):(point2?INTERSECT:OUTSIDE);
169 }
170
171 void SG_BBox::get(MT_Point3 *box, const MT_Transform &world) const
172 {
173         *box++ = world(m_min);
174         *box++ = world(MT_Point3(m_min[0], m_min[1], m_max[2]));
175         *box++ = world(MT_Point3(m_min[0], m_max[1], m_min[2]));
176         *box++ = world(MT_Point3(m_min[0], m_max[1], m_max[2]));
177         *box++ = world(MT_Point3(m_max[0], m_min[1], m_min[2]));
178         *box++ = world(MT_Point3(m_max[0], m_min[1], m_max[2]));
179         *box++ = world(MT_Point3(m_max[0], m_max[1], m_min[2]));
180         *box++ = world(m_max);
181 }
182
183 void SG_BBox::getaa(MT_Point3 *box, const MT_Transform &world) const
184 {
185         const MT_Point3 min(world(m_min)), max(world(m_max));
186         *box++ = min;
187         *box++ = MT_Point3(min[0], min[1], max[2]);
188         *box++ = MT_Point3(min[0], max[1], min[2]);
189         *box++ = MT_Point3(min[0], max[1], max[2]);
190         *box++ = MT_Point3(max[0], min[1], min[2]);
191         *box++ = MT_Point3(max[0], min[1], max[2]);
192         *box++ = MT_Point3(max[0], max[1], min[2]);
193         *box++ = max;
194 }
195
196 void SG_BBox::getmm(MT_Point3 *box, const MT_Transform &world) const
197 {
198         const MT_Point3 min(world(m_min)), max(world(m_max));
199         *box++ = min;
200         *box++ = max;
201 }
202
203 void SG_BBox::split(SG_BBox &left, SG_BBox &right) const
204 {
205         MT_Scalar sizex = m_max[0] - m_min[0];
206         MT_Scalar sizey = m_max[1] - m_min[1];
207         MT_Scalar sizez = m_max[2] - m_min[2];
208         if (sizex < sizey)
209         {
210                 if (sizey > sizez)
211                 {
212                         left.m_min = m_min;
213                         left.m_max[0] = m_max[0];
214                         left.m_max[1] = m_min[1] + sizey/2.0;
215                         left.m_max[2] = m_max[2];
216                         
217                         right.m_min[0] = m_min[0];
218                         right.m_min[1] = m_min[1] + sizey/2.0;
219                         right.m_min[2] = m_min[2];
220                         right.m_max = m_max;
221                         std::cout << "splity" << std::endl;
222                 } else {
223                         left.m_min = m_min;
224                         left.m_max[0] = m_max[0];
225                         left.m_max[1] = m_max[1];
226                         left.m_max[2] = m_min[2] + sizez/2.0;
227                 
228                         right.m_min[0] = m_min[0];
229                         right.m_min[1] = m_min[1];
230                         right.m_min[2] = m_min[2] + sizez/2.0;
231                         right.m_max = m_max;
232                         std::cout << "splitz" << std::endl;
233                 }
234         } else {
235                 if (sizex > sizez)
236                 {
237                         left.m_min = m_min;
238                         left.m_max[0] = m_min[0] + sizex/2.0;
239                         left.m_max[1] = m_max[1];
240                         left.m_max[2] = m_max[2];
241                         
242                         right.m_min[0] = m_min[0] + sizex/2.0;
243                         right.m_min[1] = m_min[1];
244                         right.m_min[2] = m_min[2];
245                         right.m_max = m_max;
246                         std::cout << "splitx" << std::endl;
247                 } else {
248                         left.m_min = m_min;
249                         left.m_max[0] = m_max[0];
250                         left.m_max[1] = m_max[1];
251                         left.m_max[2] = m_min[2] + sizez/2.0;
252                 
253                         right.m_min[0] = m_min[0];
254                         right.m_min[1] = m_min[1];
255                         right.m_min[2] = m_min[2] + sizez/2.0;
256                         right.m_max = m_max;
257                         std::cout << "splitz" << std::endl;
258                 }
259         }
260         
261         //std::cout << "Left: " << left.m_min << " -> " << left.m_max << " Right: " << right.m_min << " -> " << right.m_max << std::endl;
262 }