BoundingBox 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSG_BOUNDINGBOX
  14. #define OSG_BOUNDINGBOX 1
  15. #include <osg/Config>
  16. #include <osg/Export>
  17. #include <osg/Vec3>
  18. #include <osg/Vec3d>
  19. #include <float.h>
  20. namespace osg {
  21. template<typename VT>
  22. class BoundingSphereImpl;
  23. /** General purpose axis-aligned bounding box class for enclosing objects/vertices.
  24. * Bounds leaf objects in a scene such as osg::Drawable objects. Used for frustum
  25. * culling etc.
  26. */
  27. template<typename VT>
  28. class BoundingBoxImpl
  29. {
  30. public:
  31. typedef VT vec_type;
  32. typedef typename VT::value_type value_type;
  33. /** Minimum extent. (Smallest X, Y, and Z values of all coordinates.) */
  34. vec_type _min;
  35. /** Maximum extent. (Greatest X, Y, and Z values of all coordinates.) */
  36. vec_type _max;
  37. /** Creates an uninitialized bounding box. */
  38. inline BoundingBoxImpl() :
  39. _min(FLT_MAX,
  40. FLT_MAX,
  41. FLT_MAX),
  42. _max(-FLT_MAX,
  43. -FLT_MAX,
  44. -FLT_MAX)
  45. {}
  46. template<typename BT>
  47. inline BoundingBoxImpl(const BoundingBoxImpl<BT>& bb) :
  48. _min(bb._min),
  49. _max(bb._max)
  50. {}
  51. /** Creates a bounding box initialized to the given extents. */
  52. inline BoundingBoxImpl(value_type xmin, value_type ymin, value_type zmin,
  53. value_type xmax, value_type ymax, value_type zmax) :
  54. _min(xmin,ymin,zmin),
  55. _max(xmax,ymax,zmax) {}
  56. /** Creates a bounding box initialized to the given extents. */
  57. inline BoundingBoxImpl(const vec_type& min,const vec_type& max) :
  58. _min(min),
  59. _max(max) {}
  60. /** Clear the bounding box. Erases existing minimum and maximum extents. */
  61. inline void init()
  62. {
  63. _min.set(FLT_MAX,
  64. FLT_MAX,
  65. FLT_MAX);
  66. _max.set(-FLT_MAX,
  67. -FLT_MAX,
  68. -FLT_MAX);
  69. }
  70. inline bool operator == (const BoundingBoxImpl& rhs) const { return _min==rhs._min && _max==rhs._max; }
  71. inline bool operator != (const BoundingBoxImpl& rhs) const { return _min!=rhs._min || _max!=rhs._max; }
  72. /** Returns true if the bounding box extents are valid, false otherwise. */
  73. inline bool valid() const
  74. {
  75. return _max.x()>=_min.x() && _max.y()>=_min.y() && _max.z()>=_min.z();
  76. }
  77. /** Sets the bounding box extents. */
  78. inline void set (value_type xmin, value_type ymin, value_type zmin,
  79. value_type xmax, value_type ymax, value_type zmax)
  80. {
  81. _min.set(xmin,ymin,zmin);
  82. _max.set(xmax,ymax,zmax);
  83. }
  84. /** Sets the bounding box extents. */
  85. inline void set(const vec_type& min,const vec_type& max)
  86. {
  87. _min = min;
  88. _max = max;
  89. }
  90. inline value_type& xMin() { return _min.x(); }
  91. inline value_type xMin() const { return _min.x(); }
  92. inline value_type& yMin() { return _min.y(); }
  93. inline value_type yMin() const { return _min.y(); }
  94. inline value_type& zMin() { return _min.z(); }
  95. inline value_type zMin() const { return _min.z(); }
  96. inline value_type& xMax() { return _max.x(); }
  97. inline value_type xMax() const { return _max.x(); }
  98. inline value_type& yMax() { return _max.y(); }
  99. inline value_type yMax() const { return _max.y(); }
  100. inline value_type& zMax() { return _max.z(); }
  101. inline value_type zMax() const { return _max.z(); }
  102. /** Calculates and returns the bounding box center. */
  103. inline const vec_type center() const
  104. {
  105. return (_min+_max)*0.5;
  106. }
  107. /** Calculates and returns the bounding box radius. */
  108. inline value_type radius() const
  109. {
  110. return sqrt(radius2());
  111. }
  112. /** Calculates and returns the squared length of the bounding box radius.
  113. * Note, radius2() is faster to calculate than radius(). */
  114. inline value_type radius2() const
  115. {
  116. return 0.25*((_max-_min).length2());
  117. }
  118. /** Returns a specific corner of the bounding box.
  119. * pos specifies the corner as a number between 0 and 7.
  120. * Each bit selects an axis, X, Y, or Z from least- to
  121. * most-significant. Unset bits select the minimum value
  122. * for that axis, and set bits select the maximum. */
  123. inline const vec_type corner(unsigned int pos) const
  124. {
  125. return vec_type(pos&1?_max.x():_min.x(),pos&2?_max.y():_min.y(),pos&4?_max.z():_min.z());
  126. }
  127. /** Expands the bounding box to include the given coordinate.
  128. * If the box is uninitialized, set its min and max extents to v. */
  129. inline void expandBy(const vec_type& v)
  130. {
  131. if(v.x()<_min.x()) _min.x() = v.x();
  132. if(v.x()>_max.x()) _max.x() = v.x();
  133. if(v.y()<_min.y()) _min.y() = v.y();
  134. if(v.y()>_max.y()) _max.y() = v.y();
  135. if(v.z()<_min.z()) _min.z() = v.z();
  136. if(v.z()>_max.z()) _max.z() = v.z();
  137. }
  138. /** Expands the bounding box to include the given coordinate.
  139. * If the box is uninitialized, set its min and max extents to
  140. * Vec3(x,y,z). */
  141. inline void expandBy(value_type x,value_type y,value_type z)
  142. {
  143. if(x<_min.x()) _min.x() = x;
  144. if(x>_max.x()) _max.x() = x;
  145. if(y<_min.y()) _min.y() = y;
  146. if(y>_max.y()) _max.y() = y;
  147. if(z<_min.z()) _min.z() = z;
  148. if(z>_max.z()) _max.z() = z;
  149. }
  150. /** Expands this bounding box to include the given bounding box.
  151. * If this box is uninitialized, set it equal to bb. */
  152. void expandBy(const BoundingBoxImpl& bb)
  153. {
  154. if (!bb.valid()) return;
  155. if(bb._min.x()<_min.x()) _min.x() = bb._min.x();
  156. if(bb._max.x()>_max.x()) _max.x() = bb._max.x();
  157. if(bb._min.y()<_min.y()) _min.y() = bb._min.y();
  158. if(bb._max.y()>_max.y()) _max.y() = bb._max.y();
  159. if(bb._min.z()<_min.z()) _min.z() = bb._min.z();
  160. if(bb._max.z()>_max.z()) _max.z() = bb._max.z();
  161. }
  162. /** Expands this bounding box to include the given sphere.
  163. * If this box is uninitialized, set it to include sh. */
  164. template<typename BST>
  165. void expandBy(const BoundingSphereImpl<BST>& sh)
  166. {
  167. if (!sh.valid()) return;
  168. if(sh._center.x()-sh._radius<_min.x()) _min.x() = sh._center.x()-sh._radius;
  169. if(sh._center.x()+sh._radius>_max.x()) _max.x() = sh._center.x()+sh._radius;
  170. if(sh._center.y()-sh._radius<_min.y()) _min.y() = sh._center.y()-sh._radius;
  171. if(sh._center.y()+sh._radius>_max.y()) _max.y() = sh._center.y()+sh._radius;
  172. if(sh._center.z()-sh._radius<_min.z()) _min.z() = sh._center.z()-sh._radius;
  173. if(sh._center.z()+sh._radius>_max.z()) _max.z() = sh._center.z()+sh._radius;
  174. }
  175. /** Returns the intersection of this bounding box and the specified bounding box. */
  176. BoundingBoxImpl intersect(const BoundingBoxImpl& bb) const
  177. { return BoundingBoxImpl(osg::maximum(xMin(),bb.xMin()),osg::maximum(yMin(),bb.yMin()),osg::maximum(zMin(),bb.zMin()),
  178. osg::minimum(xMax(),bb.xMax()),osg::minimum(yMax(),bb.yMax()),osg::minimum(zMax(),bb.zMax()));
  179. }
  180. /** Return true if this bounding box intersects the specified bounding box. */
  181. bool intersects(const BoundingBoxImpl& bb) const
  182. { return osg::maximum(xMin(),bb.xMin()) <= osg::minimum(xMax(),bb.xMax()) &&
  183. osg::maximum(yMin(),bb.yMin()) <= osg::minimum(yMax(),bb.yMax()) &&
  184. osg::maximum(zMin(),bb.zMin()) <= osg::minimum(zMax(),bb.zMax());
  185. }
  186. /** Returns true if this bounding box contains the specified coordinate. */
  187. inline bool contains(const vec_type& v) const
  188. {
  189. return valid() &&
  190. (v.x()>=_min.x() && v.x()<=_max.x()) &&
  191. (v.y()>=_min.y() && v.y()<=_max.y()) &&
  192. (v.z()>=_min.z() && v.z()<=_max.z());
  193. }
  194. /** Returns true if this bounding box contains the specified coordinate allowing for specific epsilon. */
  195. inline bool contains(const vec_type& v, value_type epsilon) const
  196. {
  197. return valid() &&
  198. ((v.x()+epsilon)>=_min.x() && (v.x()-epsilon)<=_max.x()) &&
  199. ((v.y()+epsilon)>=_min.y() && (v.y()-epsilon)<=_max.y()) &&
  200. ((v.z()+epsilon)>=_min.z() && (v.z()-epsilon)<=_max.z());
  201. }
  202. };
  203. typedef BoundingBoxImpl<Vec3f> BoundingBoxf;
  204. typedef BoundingBoxImpl<Vec3d> BoundingBoxd;
  205. #ifdef OSG_USE_FLOAT_BOUNDINGBOX
  206. typedef BoundingBoxf BoundingBox;
  207. #else
  208. typedef BoundingBoxd BoundingBox;
  209. #endif
  210. }
  211. #endif