1 //------------------------------------------------------------------------
2 // EPI Bounding Boxes
3 //------------------------------------------------------------------------
4 //
5 // Copyright (c) 2003-2008 The EDGE Team.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 //------------------------------------------------------------------------
18
19 #ifndef __EPI_MATH_BBOX_H__
20 #define __EPI_MATH_BBOX_H__
21
22 #include "math_vector.h"
23
24 namespace epi
25 {
26
27 class bbox2_c
28 {
29 /* sealed, value semantics */
30
31 friend class bbox3_c;
32
33 private:
34 vec2_c lo;
35 vec2_c hi;
36
37 public:
bbox2_c()38 bbox2_c() : lo(), hi() { }
bbox2_c(const bbox2_c & rhs)39 bbox2_c(const bbox2_c& rhs) : lo(rhs.lo), hi(rhs.hi) { }
40
41 explicit bbox2_c(const vec2_c& point);
42 explicit bbox2_c(const vec2_c& p1, const vec2_c& p2);
43 explicit bbox2_c(const vec2_c& p1, const vec2_c& p2, const vec2_c& p3);
44
45 /* ---- read-only operations ---- */
46
47 inline bool Contains(vec2_c point) const;
48 // checks if the point lies inside the bounding box.
49
50 inline bool DoesIntersect(const bbox2_c& other) const;
51 // checks if two bounding boxes intersect. Returns false when only
52 // touching, i.e. the intersected volume must be > 0.
53
54 /* ---- modifying operations ---- */
55
56 bbox2_c& operator= (const bbox2_c& rhs);
57
58 bbox2_c& operator+= (const vec2_c& offset);
59 bbox2_c& operator-= (const vec2_c& offset);
60 // move the whole bbox by the given offset.
61
62 inline bbox2_c& Insert(const vec2_c& point);
63 // enlarge the bbox (if needed) to include the given point.
64
65 inline bbox2_c& Merge(const bbox2_c& other);
66 // merge the other bbox with this one.
67
68 inline bbox2_c& Enlarge(float radius);
69 // enlarge this bbox by moving each edge by radius.
70 };
71
72 class bbox3_c
73 {
74 /* sealed, value semantics */
75
76 private:
77 vec3_c lo;
78 vec3_c hi;
79
80 public:
bbox3_c()81 bbox3_c() : lo(), hi() { }
bbox3_c(const bbox3_c & rhs)82 bbox3_c(const bbox3_c& rhs) : lo(rhs.lo), hi(rhs.hi) { }
bbox3_c(const bbox2_c & rhs,float z1,float z2)83 bbox3_c(const bbox2_c& rhs, float z1, float z2)
84 : lo(rhs.lo, z1), hi(rhs.hi, z2) { }
85
86 explicit bbox3_c(const vec3_c& point);
87 explicit bbox3_c(const vec3_c& p1, const vec3_c& p2);
88 explicit bbox3_c(const vec3_c& p1, const vec3_c& p2, const vec3_c& p3);
89
90 /* ---- read-only operations ---- */
91
92 inline bool Contains(vec3_c point) const;
93 // checks if the point lies inside the bounding box.
94
95 inline bool DoesIntersect(const bbox3_c& other) const;
96 // checks if two bounding boxes intersect. Returns false when only
97 // touching, i.e. the intersected volume must be > 0.
98
99 enum
100 {
101 HIT_OUTSIDE = 0, // fully outside the plane (back side)
102 HIT_PARTIAL, // intersects the plane
103 HIT_INSIDE, // fully inside the plane (front side)
104 };
105
106 int IntersectPlane(vec3_c loc, vec3_c face) const;
107 // check if this bounding box intersects the given plane,
108 // returning one of the HIT_XXX values above.
109 // NOTE: face vector must be unit length.
110
111 /* ---- modifying operations ---- */
112
113 bbox3_c& operator= (const bbox3_c& rhs);
114
115 bbox3_c& operator+= (const vec3_c& offset);
116 bbox3_c& operator-= (const vec3_c& offset);
117 // move the whole bbox by the given offset.
118
119 inline bbox3_c& Insert(const vec3_c& point);
120 // enlarge the bbox (if needed) to include the given point.
121
122 inline bbox3_c& Merge(const bbox3_c& other);
123 // merge the other bbox with this one.
124
125 inline bbox3_c& Enlarge(float radius);
126 inline bbox3_c& Enlarge(float horiz_R, float vert_R);
127 // enlarge this bbox by moving each edge by radius.
128 };
129
130
131 //------------------------------------------------------------------------
132 // IMPLEMENTATION
133 //------------------------------------------------------------------------
134
bbox2_c(const vec2_c & point)135 inline bbox2_c::bbox2_c(const vec2_c& point) : lo(point), hi(point)
136 { }
137
bbox2_c(const vec2_c & p1,const vec2_c & p2)138 inline bbox2_c::bbox2_c(const vec2_c& p1, const vec2_c& p2) : lo(p1), hi(p1)
139 {
140 Insert(p2);
141 }
142
bbox2_c(const vec2_c & p1,const vec2_c & p2,const vec2_c & p3)143 inline bbox2_c::bbox2_c(const vec2_c& p1, const vec2_c& p2, const vec2_c& p3)
144 : lo(p1), hi(p1)
145 {
146 Insert(p2);
147 Insert(p3);
148 }
149
Contains(vec2_c point)150 inline bool bbox2_c::Contains(vec2_c point) const
151 {
152 return (lo.x <= point.x && point.x <= hi.x &&
153 lo.y <= point.y && point.y <= hi.y);
154 }
155
DoesIntersect(const bbox2_c & other)156 inline bool bbox2_c::DoesIntersect(const bbox2_c& other) const
157 {
158 return (other.hi.x > lo.x && other.lo.x < hi.x &&
159 other.hi.y > lo.y && other.lo.y < hi.y);
160 }
161
162 inline bbox2_c& bbox2_c::operator= (const bbox2_c& rhs)
163 {
164 // no need to check for self assignment
165 lo = rhs.lo;
166 hi = rhs.hi;
167
168 return *this;
169 }
170
171 inline bbox2_c& bbox2_c::operator+= (const vec2_c& offset)
172 {
173 lo += offset;
174 hi += offset;
175
176 return *this;
177 }
178
179 inline bbox2_c& bbox2_c::operator-= (const vec2_c& offset)
180 {
181 lo -= offset;
182 hi -= offset;
183
184 return *this;
185 }
186
Insert(const vec2_c & point)187 inline bbox2_c& bbox2_c::Insert(const vec2_c& point)
188 {
189 if (point.x < lo.x) lo.x = point.x;
190 if (point.y < lo.y) lo.y = point.y;
191 if (point.x > hi.x) hi.x = point.x;
192 if (point.y > hi.y) hi.y = point.y;
193
194 return *this;
195 }
196
Merge(const bbox2_c & other)197 inline bbox2_c& bbox2_c::Merge(const bbox2_c& other)
198 {
199 Insert(other.lo);
200 Insert(other.hi);
201
202 return *this;
203 }
204
Enlarge(float radius)205 inline bbox2_c& bbox2_c::Enlarge(float radius)
206 {
207 lo.x -= radius; lo.y -= radius;
208 hi.x += radius; hi.y += radius;
209
210 return *this;
211 }
212
213 //------------------------------------------------------------------------
214
bbox3_c(const vec3_c & point)215 inline bbox3_c::bbox3_c(const vec3_c& point) : lo(point), hi(point)
216 { }
217
bbox3_c(const vec3_c & p1,const vec3_c & p2)218 inline bbox3_c::bbox3_c(const vec3_c& p1, const vec3_c& p2) : lo(p1), hi(p1)
219 {
220 Insert(p2);
221 }
222
bbox3_c(const vec3_c & p1,const vec3_c & p2,const vec3_c & p3)223 inline bbox3_c::bbox3_c(const vec3_c& p1, const vec3_c& p2, const vec3_c& p3)
224 : lo(p1), hi(p1)
225 {
226 Insert(p2);
227 Insert(p3);
228 }
229
Contains(vec3_c point)230 inline bool bbox3_c::Contains(vec3_c point) const
231 {
232 return (lo.x <= point.x && point.x <= hi.x &&
233 lo.y <= point.y && point.y <= hi.y &&
234 lo.z <= point.z && point.z <= hi.z);
235 }
236
DoesIntersect(const bbox3_c & other)237 inline bool bbox3_c::DoesIntersect(const bbox3_c& other) const
238 {
239 return (other.hi.x > lo.x && other.lo.x < hi.x &&
240 other.hi.y > lo.y && other.lo.y < hi.y &&
241 other.hi.z > lo.z && other.lo.z < hi.z);
242 }
243
244 inline bbox3_c& bbox3_c::operator= (const bbox3_c& rhs)
245 {
246 // no need to check for self assignment
247 lo = rhs.lo;
248 hi = rhs.hi;
249
250 return *this;
251 }
252
253 inline bbox3_c& bbox3_c::operator+= (const vec3_c& offset)
254 {
255 lo += offset;
256 hi += offset;
257
258 return *this;
259 }
260
261 inline bbox3_c& bbox3_c::operator-= (const vec3_c& offset)
262 {
263 lo -= offset;
264 hi -= offset;
265
266 return *this;
267 }
268
Insert(const vec3_c & point)269 inline bbox3_c& bbox3_c::Insert(const vec3_c& point)
270 {
271 if (point.x < lo.x) lo.x = point.x;
272 if (point.y < lo.y) lo.y = point.y;
273 if (point.z < lo.z) lo.z = point.z;
274
275 if (point.x > hi.x) hi.x = point.x;
276 if (point.y > hi.y) hi.y = point.y;
277 if (point.z > hi.z) hi.z = point.z;
278
279 return *this;
280 }
281
Merge(const bbox3_c & other)282 inline bbox3_c& bbox3_c::Merge(const bbox3_c& other)
283 {
284 Insert(other.lo);
285 Insert(other.hi);
286
287 return *this;
288 }
289
Enlarge(float radius)290 inline bbox3_c& bbox3_c::Enlarge(float radius)
291 {
292 lo.x -= radius; lo.y -= radius; lo.z -= radius;
293 hi.x += radius; hi.y += radius; hi.z += radius;
294
295 return *this;
296 }
297
Enlarge(float horiz_R,float vert_R)298 inline bbox3_c& bbox3_c::Enlarge(float horiz_R, float vert_R)
299 {
300 lo.x -= horiz_R; lo.y -= horiz_R;
301 hi.x += horiz_R; hi.y += horiz_R;
302
303 lo.z -= vert_R;
304 hi.z += vert_R;
305
306 return *this;
307 }
308
309 } // namespace epi
310
311 #endif /* __EPI_MATH_BBOX_H__ */
312
313 //--- editor settings ---
314 // vi:ts=4:sw=4:noexpandtab
315