voxelTerrain
 All Classes Functions Variables Typedefs Enumerations Pages
axisAlignedBox.hpp
1 #ifndef AXISALIGNEDBOX_HPP
2 #define AXISALIGNEDBOX_HPP
3 
4 #include "blub/core/classVersion.hpp"
5 #include "blub/math/vector3.hpp"
6 #include "blub/serialization/nameValuePair.hpp"
7 #include "blub/serialization/saveLoad.hpp"
8 
9 
10 namespace Ogre
11 {
12  class AxisAlignedBox;
13 }
14 
15 
16 namespace blub
17 {
18 
19 
21 {
22 public:
23  enum Extent
24  {
25  EXTENT_NULL,
26  EXTENT_FINITE,
27  EXTENT_INFINITE
28  };
29 protected:
30 
31  vector3 mMinimum;
32  vector3 mMaximum;
33  Extent mExtent;
34 
35 public:
36  /*
37  1-----2
38  /| /|
39  / | / |
40  5-----4 |
41  | 0--|--3
42  | / | /
43  |/ |/
44  6-----7
45  */
46  typedef enum {
47  FAR_LEFT_BOTTOM = 0,
48  FAR_LEFT_TOP = 1,
49  FAR_RIGHT_TOP = 2,
50  FAR_RIGHT_BOTTOM = 3,
51  NEAR_RIGHT_BOTTOM = 7,
52  NEAR_LEFT_BOTTOM = 6,
53  NEAR_LEFT_TOP = 5,
54  NEAR_RIGHT_TOP = 4
55  } CornerEnum;
56 
57  axisAlignedBox(const axisAlignedBoxInt32 &toCast);
58 #ifndef BLUB_NO_OGRE3D
59  axisAlignedBox(const Ogre::AxisAlignedBox &vec);
60  operator Ogre::AxisAlignedBox() const;
61 #endif
62 
63  inline axisAlignedBox() : mMinimum(vector3::ZERO), mMaximum(vector3::UNIT_SCALE)
64  {
65  // Default to a null box
66  setMinimum( -0.5, -0.5, -0.5 );
67  setMaximum( 0.5, 0.5, 0.5 );
68  mExtent = EXTENT_NULL;
69  }
70  inline axisAlignedBox(Extent e) : mMinimum(vector3::ZERO), mMaximum(vector3::UNIT_SCALE)
71  {
72  setMinimum( -0.5, -0.5, -0.5 );
73  setMaximum( 0.5, 0.5, 0.5 );
74  mExtent = e;
75  }
76 
77 
78  inline axisAlignedBox(const axisAlignedBox & rkBox) : mMinimum(vector3::ZERO), mMaximum(vector3::UNIT_SCALE)
79 
80  {
81  if (rkBox.isNull())
82  setNull();
83  else if (rkBox.isInfinite())
84  setInfinite();
85  else
86  setExtents( rkBox.mMinimum, rkBox.mMaximum );
87  }
88 
89  inline axisAlignedBox( const vector3& min, const vector3& max )
90  : mMinimum(vector3::ZERO), mMaximum(vector3::UNIT_SCALE)
91  {
92  setExtents( min, max );
93  }
94 
95  inline axisAlignedBox(
96  real mx, real my, real mz,
97  real Mx, real My, real Mz)
98  : mMinimum(vector3::ZERO), mMaximum(vector3::UNIT_SCALE)
99  {
100  setExtents( mx, my, mz, Mx, My, Mz );
101  }
102 
103 
104  axisAlignedBox& operator=(const axisAlignedBox& rhs)
105  {
106  // Specifically override to avoid copying mCorners
107  if (rhs.isNull())
108  setNull();
109  else if (rhs.isInfinite())
110  setInfinite();
111  else
112  setExtents(rhs.mMinimum, rhs.mMaximum);
113 
114  return *this;
115  }
116 
117  ~axisAlignedBox()
118  {
119  //if (mCorners)
120  // OGRE_FREE(mCorners, MEMCATEGORY_SCENE_CONTROL);
121  }
122 
123 
126  inline const vector3& getMinimum(void) const
127  {
128  return mMinimum;
129  }
130 
134  inline vector3& getMinimum(void)
135  {
136  return mMinimum;
137  }
138 
141  inline const vector3& getMaximum(void) const
142  {
143  return mMaximum;
144  }
145 
149  inline vector3& getMaximum(void)
150  {
151  return mMaximum;
152  }
153 
154 
157  inline void setMinimum( const vector3& vec )
158  {
159  mExtent = EXTENT_FINITE;
160  mMinimum = vec;
161  }
162 
163  inline void setMinimum( real x, real y, real z )
164  {
165  mExtent = EXTENT_FINITE;
166  mMinimum.x = x;
167  mMinimum.y = y;
168  mMinimum.z = z;
169  }
170 
174  inline void setMinimumX(real x)
175  {
176  mMinimum.x = x;
177  }
178 
179  inline void setMinimumY(real y)
180  {
181  mMinimum.y = y;
182  }
183 
184  inline void setMinimumZ(real z)
185  {
186  mMinimum.z = z;
187  }
188 
191  inline void setMaximum( const vector3& vec )
192  {
193  mExtent = EXTENT_FINITE;
194  mMaximum = vec;
195  }
196 
197  inline void setMaximum( real x, real y, real z )
198  {
199  mExtent = EXTENT_FINITE;
200  mMaximum.x = x;
201  mMaximum.y = y;
202  mMaximum.z = z;
203  }
204 
208  inline void setMaximumX( real x )
209  {
210  mMaximum.x = x;
211  }
212 
213  inline void setMaximumY( real y )
214  {
215  mMaximum.y = y;
216  }
217 
218  inline void setMaximumZ( real z )
219  {
220  mMaximum.z = z;
221  }
222 
225  inline void setExtents( const vector3& min, const vector3& max )
226  {
227  BASSERT( (min.x <= max.x && min.y <= max.y && min.z <= max.z) &&
228  "The minimum corner of the box must be less than or equal to maximum corner" );
229 
230  mExtent = EXTENT_FINITE;
231  mMinimum = min;
232  mMaximum = max;
233  }
234 
235  inline void setExtents(
236  real mx, real my, real mz,
237  real Mx, real My, real Mz )
238  {
239  BASSERT( (mx <= Mx && my <= My && mz <= Mz) &&
240  "The minimum corner of the box must be less than or equal to maximum corner" );
241 
242  mExtent = EXTENT_FINITE;
243 
244  mMinimum.x = mx;
245  mMinimum.y = my;
246  mMinimum.z = mz;
247 
248  mMaximum.x = Mx;
249  mMaximum.y = My;
250  mMaximum.z = Mz;
251 
252  }
253 
256  vector3 getCorner(CornerEnum cornerToGet) const
257  {
258  switch(cornerToGet)
259  {
260  case FAR_LEFT_BOTTOM:
261  return mMinimum;
262  case FAR_LEFT_TOP:
263  return vector3(mMinimum.x, mMaximum.y, mMinimum.z);
264  case FAR_RIGHT_TOP:
265  return vector3(mMaximum.x, mMaximum.y, mMinimum.z);
266  case FAR_RIGHT_BOTTOM:
267  return vector3(mMaximum.x, mMinimum.y, mMinimum.z);
268  case NEAR_RIGHT_BOTTOM:
269  return vector3(mMaximum.x, mMinimum.y, mMaximum.z);
270  case NEAR_LEFT_BOTTOM:
271  return vector3(mMinimum.x, mMinimum.y, mMaximum.z);
272  case NEAR_LEFT_TOP:
273  return vector3(mMinimum.x, mMaximum.y, mMaximum.z);
274  case NEAR_RIGHT_TOP:
275  return mMaximum;
276  default:
277  return vector3();
278  }
279  }
280 
284  void merge( const axisAlignedBox& rhs )
285  {
286  // Do nothing if rhs null, or this is infinite
287  if ((rhs.mExtent == EXTENT_NULL) || (mExtent == EXTENT_INFINITE))
288  {
289  return;
290  }
291  // Otherwise if rhs is infinite, make this infinite, too
292  else if (rhs.mExtent == EXTENT_INFINITE)
293  {
294  mExtent = EXTENT_INFINITE;
295  }
296  // Otherwise if current null, just take rhs
297  else if (mExtent == EXTENT_NULL)
298  {
299  setExtents(rhs.mMinimum, rhs.mMaximum);
300  }
301  // Otherwise merge
302  else
303  {
304  vector3 min = mMinimum;
305  vector3 max = mMaximum;
306  max.makeCeil(rhs.mMaximum);
307  min.makeFloor(rhs.mMinimum);
308 
309  setExtents(min, max);
310  }
311 
312  }
313 
316  inline void merge( const vector3& point )
317  {
318  switch (mExtent)
319  {
320  case EXTENT_NULL: // if null, use this point
321  setExtents(point, point);
322  return;
323 
324  case EXTENT_FINITE:
325  mMaximum.makeCeil(point);
326  mMinimum.makeFloor(point);
327  return;
328 
329  case EXTENT_INFINITE: // if infinite, makes no difference
330  return;
331  }
332 
333  BASSERT( false && "Never reached" );
334  }
335 
338  inline void setNull()
339  {
340  mExtent = EXTENT_NULL;
341  }
342 
345  inline bool isNull(void) const
346  {
347  return (mExtent == EXTENT_NULL);
348  }
349 
352  bool isFinite(void) const
353  {
354  return (mExtent == EXTENT_FINITE);
355  }
356 
359  inline void setInfinite()
360  {
361  mExtent = EXTENT_INFINITE;
362  }
363 
366  bool isInfinite(void) const
367  {
368  return (mExtent == EXTENT_INFINITE);
369  }
370 
372  inline bool intersects(const axisAlignedBox& b2) const
373  {
374  // Early-fail for nulls
375  if (this->isNull() || b2.isNull())
376  return false;
377 
378  // Early-success for infinites
379  if (this->isInfinite() || b2.isInfinite())
380  return true;
381 
382  // Use up to 6 separating planes
383  if (mMaximum.x < b2.mMinimum.x)
384  return false;
385  if (mMaximum.y < b2.mMinimum.y)
386  return false;
387  if (mMaximum.z < b2.mMinimum.z)
388  return false;
389 
390  if (mMinimum.x > b2.mMaximum.x)
391  return false;
392  if (mMinimum.y > b2.mMaximum.y)
393  return false;
394  if (mMinimum.z > b2.mMaximum.z)
395  return false;
396 
397  // otherwise, must be intersecting
398  return true;
399 
400  }
401 
404  {
405  if (this->isNull() || b2.isNull())
406  {
407  return axisAlignedBox();
408  }
409  else if (this->isInfinite())
410  {
411  return b2;
412  }
413  else if (b2.isInfinite())
414  {
415  return *this;
416  }
417 
418  vector3 intMin = mMinimum;
419  vector3 intMax = mMaximum;
420 
421  intMin.makeCeil(b2.getMinimum());
422  intMax.makeFloor(b2.getMaximum());
423 
424  // Check intersection isn't null
425  if (intMin.x < intMax.x &&
426  intMin.y < intMax.y &&
427  intMin.z < intMax.z)
428  {
429  return axisAlignedBox(intMin, intMax);
430  }
431 
432  return axisAlignedBox();
433  }
434 
436  real volume(void) const;
437 
439  inline void scale(const vector3& s)
440  {
441  // Do nothing if current null or infinite
442  if (mExtent != EXTENT_FINITE)
443  return;
444 
445  // NB assumes centered on origin
446  vector3 min = mMinimum * s;
447  vector3 max = mMaximum * s;
448  setExtents(min, max);
449  }
450 
452  bool intersects(const sphere& s) const;
453 
455  bool intersects(const plane& p) const;
456 
458  bool intersects(const vector3& v) const
459  {
460  switch (mExtent)
461  {
462  case EXTENT_NULL:
463  return false;
464 
465  case EXTENT_FINITE:
466  return(v.x >= mMinimum.x && v.x <= mMaximum.x &&
467  v.y >= mMinimum.y && v.y <= mMaximum.y &&
468  v.z >= mMinimum.z && v.z <= mMaximum.z);
469 
470  case EXTENT_INFINITE:
471  return true;
472 
473  default: // shut up compiler
474  BASSERT( false && "Never reached" );
475  return false;
476  }
477  }
479  vector3 getCenter(void) const
480  {
481  BASSERT( (mExtent == EXTENT_FINITE) && "Can't get center of a null or infinite AAB" );
482 
483  return vector3(
484  (mMaximum.x + mMinimum.x) * 0.5f,
485  (mMaximum.y + mMinimum.y) * 0.5f,
486  (mMaximum.z + mMinimum.z) * 0.5f);
487  }
489  vector3 getSize(void) const;
490 
492  vector3 getHalfSize(void) const;
493 
496  bool contains(const vector3& v) const
497  {
498  if (isNull())
499  return false;
500  if (isInfinite())
501  return true;
502 
503  return mMinimum.x <= v.x && v.x <= mMaximum.x &&
504  mMinimum.y <= v.y && v.y <= mMaximum.y &&
505  mMinimum.z <= v.z && v.z <= mMaximum.z;
506  }
507 
509  real distance(const vector3& v) const;
510 
513  bool contains(const axisAlignedBox& other) const
514  {
515  if (other.isNull() || this->isInfinite())
516  return true;
517 
518  if (this->isNull() || other.isInfinite())
519  return false;
520 
521  return this->mMinimum.x <= other.mMinimum.x &&
522  this->mMinimum.y <= other.mMinimum.y &&
523  this->mMinimum.z <= other.mMinimum.z &&
524  other.mMaximum.x <= this->mMaximum.x &&
525  other.mMaximum.y <= this->mMaximum.y &&
526  other.mMaximum.z <= this->mMaximum.z;
527  }
528 
531  bool operator== (const axisAlignedBox& rhs) const
532  {
533  if (this->mExtent != rhs.mExtent)
534  return false;
535 
536  if (!this->isFinite())
537  return true;
538 
539  return this->mMinimum == rhs.mMinimum &&
540  this->mMaximum == rhs.mMaximum;
541  }
542 
545  bool operator!= (const axisAlignedBox& rhs) const
546  {
547  return !(*this == rhs);
548  }
549 
550  // special values
551  static const axisAlignedBox BOX_NULL;
552  static const axisAlignedBox BOX_INFINITE;
553 
554 
555  axisAlignedBox move(const vector3& vec) const {return axisAlignedBox(getMinimum()+vec, getMaximum()+vec);}
556 
557  axisAlignedBox operator * (const real& mul) const
558  {
559  return axisAlignedBox(getMinimum()*mul, getMaximum()*mul);
560  }
561  axisAlignedBox& operator *= (const real& mul)
562  {
563  mMinimum*=mul;
564  mMaximum*=mul;
565  return *this;
566  }
567  axisAlignedBox operator / (const real& mul) const
568  {
569  return axisAlignedBox(getMinimum()/mul, getMaximum()/mul);
570  }
571 
572  void setMinimumAndMaximum(const vector3& min, const vector3& max)
573  {
574  setMinimum(min);
575  setMaximum(max);
576  }
577 
578 private:
579  BLUB_SERIALIZATION_ACCESS
580 
581  template <class formatType>
582  void save(formatType & readWrite, const uint32& version) const
583  {
584  (void)version;
585 
586  const vector3 minumum(mMinimum);
587  const vector3 maximum(mMaximum);
588  readWrite & serialization::nameValuePair::create("minimum", minumum);
589  readWrite & serialization::nameValuePair::create("maximum", maximum);
590  readWrite & serialization::nameValuePair::create("extend", mExtent);
591  }
592  template <class formatType>
593  void load(formatType & readWrite, const uint32& version)
594  {
595  (void)version;
596 
597  vector3 minumum;
598  vector3 maximum;
599  readWrite & serialization::nameValuePair::create("minimum", minumum);
600  readWrite & serialization::nameValuePair::create("maximum", maximum);
601  setMinimumAndMaximum(minumum, maximum);
602  readWrite & serialization::nameValuePair::create("extend", mExtent);
603  }
604  BLUB_SERIALIZATION_SAVELOAD()
605 
606 };
607 
608 std::ostream& operator<< (std::ostream& ostr, const axisAlignedBox& toCast);
609 
610 
611 }
612 BLUB_CLASSVERSION(blub::axisAlignedBox, 1)
613 
614 #endif // AXISALIGNEDBOX_HPP
real volume(void) const
Calculate the volume of this box.
Definition: axisAlignedBox.cpp:35
vector3 getCorner(CornerEnum cornerToGet) const
Definition: axisAlignedBox.hpp:256
vector3 getCenter(void) const
Gets the centre of the box.
Definition: axisAlignedBox.hpp:479
void setMinimum(const vector3 &vec)
Definition: axisAlignedBox.hpp:157
vector3 & getMinimum(void)
Definition: axisAlignedBox.hpp:134
axisAlignedBox intersection(const axisAlignedBox &b2) const
Calculate the area of intersection of this box and another.
Definition: axisAlignedBox.hpp:403
vector3 getSize(void) const
Gets the size of the box.
Definition: axisAlignedBox.cpp:57
void setExtents(const vector3 &min, const vector3 &max)
Definition: axisAlignedBox.hpp:225
bool operator==(const axisAlignedBox &rhs) const
Definition: axisAlignedBox.hpp:531
void makeCeil(const vector3 &cmp)
Definition: vector3.hpp:538
void scale(const vector3 &s)
Definition: axisAlignedBox.hpp:439
bool intersects(const vector3 &v) const
Definition: axisAlignedBox.hpp:458
bool isInfinite(void) const
Definition: axisAlignedBox.hpp:366
vector3 getHalfSize(void) const
Gets the half-size of the box.
Definition: axisAlignedBox.cpp:79
Definition: axisAlignedBoxInt32.hpp:12
void merge(const axisAlignedBox &rhs)
Definition: axisAlignedBox.hpp:284
bool isNull(void) const
Definition: axisAlignedBox.hpp:345
bool contains(const vector3 &v) const
Definition: axisAlignedBox.hpp:496
void setMaximum(const vector3 &vec)
Definition: axisAlignedBox.hpp:191
bool intersects(const axisAlignedBox &b2) const
Definition: axisAlignedBox.hpp:372
void makeFloor(const vector3 &cmp)
Definition: vector3.hpp:524
void setMinimumX(real x)
Definition: axisAlignedBox.hpp:174
Definition: vector3.hpp:26
Definition: axisAlignedBox.hpp:20
vector3 & getMaximum(void)
Definition: axisAlignedBox.hpp:149
bool operator!=(const axisAlignedBox &rhs) const
Definition: axisAlignedBox.hpp:545
void setMaximumX(real x)
Definition: axisAlignedBox.hpp:208
Definition: plane.hpp:16
const vector3 & getMinimum(void) const
Definition: axisAlignedBox.hpp:126
void setNull()
Definition: axisAlignedBox.hpp:338
const vector3 & getMaximum(void) const
Definition: axisAlignedBox.hpp:141
void setInfinite()
Definition: axisAlignedBox.hpp:359
bool contains(const axisAlignedBox &other) const
Definition: axisAlignedBox.hpp:513
void merge(const vector3 &point)
Definition: axisAlignedBox.hpp:316
Definition: deadlineTimer.hpp:10
Definition: axisAlignedBox.hpp:10
bool isFinite(void) const
Definition: axisAlignedBox.hpp:352
real distance(const vector3 &v) const
Definition: axisAlignedBox.cpp:101
Definition: sphere.hpp:10