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