diff --git a/include/osg/BoundingBox b/include/osg/BoundingBox index f4ca8e0d8..47b7d9c5a 100644 --- a/include/osg/BoundingBox +++ b/include/osg/BoundingBox @@ -22,24 +22,19 @@ namespace osg { -class BoundingSphere; +template +class BoundingSphereImpl; /** General purpose axis-aligned bounding box class for enclosing objects/vertices. * Bounds leaf objects in a scene such as osg::Drawable objects. Used for frustum * culling etc. */ -class OSG_EXPORT BoundingBox +template +class BoundingBoxImpl { public: - -#ifdef OSG_USE_FLOAT_BOUNDINGBOX - typedef Vec3f vec_type; - typedef float value_type; -#else - typedef Vec3d vec_type; - typedef double value_type; -#endif - + typedef VT vec_type; + typedef typename VT::value_type value_type; /** Minimum extent. (Smallest X, Y, and Z values of all coordinates.) */ vec_type _min; @@ -47,25 +42,35 @@ class OSG_EXPORT BoundingBox vec_type _max; /** Creates an uninitialized bounding box. */ - inline BoundingBox() : _min(FLT_MAX,FLT_MAX,FLT_MAX), - _max(-FLT_MAX,-FLT_MAX,-FLT_MAX) {} + inline BoundingBoxImpl() : + _min(FLT_MAX, + FLT_MAX, + FLT_MAX), + _max(-FLT_MAX, + -FLT_MAX, + -FLT_MAX) + {} /** Creates a bounding box initialized to the given extents. */ - inline BoundingBox(value_type xmin, value_type ymin, value_type zmin, + inline BoundingBoxImpl(value_type xmin, value_type ymin, value_type zmin, value_type xmax, value_type ymax, value_type zmax) : _min(xmin,ymin,zmin), _max(xmax,ymax,zmax) {} /** Creates a bounding box initialized to the given extents. */ - inline BoundingBox(const vec_type& min,const vec_type& max) : + inline BoundingBoxImpl(const vec_type& min,const vec_type& max) : _min(min), _max(max) {} /** Clear the bounding box. Erases existing minimum and maximum extents. */ inline void init() { - _min.set(FLT_MAX,FLT_MAX,FLT_MAX); - _max.set(-FLT_MAX,-FLT_MAX,-FLT_MAX); + _min.set(FLT_MAX, + FLT_MAX, + FLT_MAX); + _max.set(-FLT_MAX, + -FLT_MAX, + -FLT_MAX); } /** Returns true if the bounding box extents are valid, false otherwise. */ @@ -168,22 +173,22 @@ class OSG_EXPORT BoundingBox /** Expands this bounding box to include the given bounding box. * If this box is uninitialized, set it equal to bb. */ - void expandBy(const BoundingBox& bb); + void expandBy(const BoundingBoxImpl& bb); /** Expands this bounding box to include the given sphere. * If this box is uninitialized, set it to include sh. */ - void expandBy(const BoundingSphere& sh); + void expandBy(const BoundingSphereImpl& sh); /** Returns the intersection of this bounding box and the specified bounding box. */ - BoundingBox intersect(const BoundingBox& bb) const - { return osg::BoundingBox(osg::maximum(xMin(),bb.xMin()),osg::maximum(yMin(),bb.yMin()),osg::maximum(zMin(),bb.zMin()), + BoundingBoxImpl intersect(const BoundingBoxImpl& bb) const + { return BoundingBoxImpl(osg::maximum(xMin(),bb.xMin()),osg::maximum(yMin(),bb.yMin()),osg::maximum(zMin(),bb.zMin()), osg::minimum(xMax(),bb.xMax()),osg::minimum(yMax(),bb.yMax()),osg::minimum(zMax(),bb.zMax())); } /** Return true if this bounding box intersects the specified bounding box. */ - bool intersects(const BoundingBox& bb) const + bool intersects(const BoundingBoxImpl& bb) const { return osg::maximum(xMin(),bb.xMin()) <= osg::minimum(xMax(),bb.xMax()) && osg::maximum(yMin(),bb.yMin()) <= osg::minimum(yMax(),bb.yMax()) && osg::maximum(zMin(),bb.zMin()) <= osg::minimum(zMax(),bb.zMax()); @@ -200,6 +205,45 @@ class OSG_EXPORT BoundingBox } }; +template +void BoundingBoxImpl::expandBy(const BoundingBoxImpl& bb) +{ + if (!bb.valid()) return; + + if(bb._min.x()<_min.x()) _min.x() = bb._min.x(); + if(bb._max.x()>_max.x()) _max.x() = bb._max.x(); + + if(bb._min.y()<_min.y()) _min.y() = bb._min.y(); + if(bb._max.y()>_max.y()) _max.y() = bb._max.y(); + + if(bb._min.z()<_min.z()) _min.z() = bb._min.z(); + if(bb._max.z()>_max.z()) _max.z() = bb._max.z(); +} + +template +void BoundingBoxImpl::expandBy(const BoundingSphereImpl& sh) +{ + if (!sh.valid()) return; + + if(sh._center.x()-sh._radius<_min.x()) _min.x() = sh._center.x()-sh._radius; + if(sh._center.x()+sh._radius>_max.x()) _max.x() = sh._center.x()+sh._radius; + + if(sh._center.y()-sh._radius<_min.y()) _min.y() = sh._center.y()-sh._radius; + if(sh._center.y()+sh._radius>_max.y()) _max.y() = sh._center.y()+sh._radius; + + if(sh._center.z()-sh._radius<_min.z()) _min.z() = sh._center.z()-sh._radius; + if(sh._center.z()+sh._radius>_max.z()) _max.z() = sh._center.z()+sh._radius; +} + +typedef BoundingBoxImpl BoundingBoxf; +typedef BoundingBoxImpl BoundingBoxd; + +#ifdef OSG_USE_FLOAT_BOUNDINGBOX +typedef BoundingBoxf BoundingBox; +#else +typedef BoundingBoxd BoundingBox; +#endif + } #endif diff --git a/include/osg/BoundingSphere b/include/osg/BoundingSphere index 4a44229f5..035288dcb 100644 --- a/include/osg/BoundingSphere +++ b/include/osg/BoundingSphere @@ -21,7 +21,8 @@ namespace osg { -class BoundingBox; +template +class BoundingBoxImpl; /** General purpose bounding sphere class for enclosing nodes/objects/vertices. * Bounds internal osg::Nodes in the scene, assists in view frustum culling, @@ -29,32 +30,27 @@ class BoundingBox; * culling but generally will not cull as aggressively because it encloses a * greater volume. */ -class OSG_EXPORT BoundingSphere +template +class BoundingSphereImpl { public: + typedef VT vec_type; + typedef typename vec_type::value_type value_type; -#ifdef OSG_USE_FLOAT_BOUNDINGSPHERE - typedef Vec3f vec_type; - typedef float value_type; -#else - typedef Vec3d vec_type; - typedef double value_type; -#endif - vec_type _center; value_type _radius; /** Construct a default bounding sphere with radius to -1.0f, representing an invalid/unset bounding sphere.*/ - BoundingSphere() : _center(0.0,0.0,0.0),_radius(-1.0) {} + BoundingSphereImpl() : _center(0.0,0.0,0.0),_radius(-1.0) {} /** Creates a bounding sphere initialized to the given extents. */ - BoundingSphere(const vec_type& center,value_type radius) : _center(center),_radius(radius) {} + BoundingSphereImpl(const vec_type& center,value_type radius) : _center(center),_radius(radius) {} /** Creates a bounding sphere initialized to the given extents. */ - BoundingSphere(const BoundingSphere& bs) : _center(bs._center),_radius(bs._radius) {} + BoundingSphereImpl(const BoundingSphereImpl& bs) : _center(bs._center),_radius(bs._radius) {} /** Creates a bounding sphere initialized to the given extents. */ - BoundingSphere(const BoundingBox& bb) : _center(0.0,0.0,0.0),_radius(-1.0) { expandBy(bb); } + BoundingSphereImpl(const BoundingBoxImpl& bb) : _center(0.0,0.0,0.0),_radius(-1.0) { expandBy(bb); } /** Clear the bounding sphere. Reset to default values. */ inline void init() @@ -93,40 +89,32 @@ class OSG_EXPORT BoundingSphere /** Expands the sphere to encompass the given point. Repositions the * sphere center to minimize the radius increase. If the sphere is * uninitialized, set its center to v and radius to zero. */ - void expandBy(const Vec3f& v); + template + void expandBy(const vector_type& v); /** Expands the sphere to encompass the given point. Does not * reposition the sphere center. If the sphere is * uninitialized, set its center to v and radius to zero. */ - void expandRadiusBy(const Vec3f& v); - - /** Expands the sphere to encompass the given point. Repositions the - * sphere center to minimize the radius increase. If the sphere is - * uninitialized, set its center to v and radius to zero. */ - void expandBy(const Vec3d& v); - - /** Expands the sphere to encompass the given point. Does not - * reposition the sphere center. If the sphere is - * uninitialized, set its center to v and radius to zero. */ - void expandRadiusBy(const Vec3d& v); + template + void expandRadiusBy(const vector_type& v); /** Expands the sphere to encompass the given sphere. Repositions the * sphere center to minimize the radius increase. If the sphere is * uninitialized, set its center and radius to match sh. */ - void expandBy(const BoundingSphere& sh); + void expandBy(const BoundingSphereImpl& sh); /** Expands the sphere to encompass the given sphere. Does not * repositions the sphere center. If the sphere is * uninitialized, set its center and radius to match sh. */ - void expandRadiusBy(const BoundingSphere& sh); + void expandRadiusBy(const BoundingSphereImpl& sh); /** Expands the sphere to encompass the given box. Repositions the * sphere center to minimize the radius increase. */ - void expandBy(const BoundingBox& bb); + void expandBy(const BoundingBoxImpl& bb); /** Expands the sphere to encompass the given box. Does not * repositions the sphere center. */ - void expandRadiusBy(const BoundingBox& bb); + void expandRadiusBy(const BoundingBoxImpl& bb); /** Returns true if v is within the sphere. */ inline bool contains(const vec_type& v) const @@ -137,14 +125,182 @@ class OSG_EXPORT BoundingSphere /** Returns true if there is a non-empty intersection with the given * bounding sphere. */ - inline bool intersects( const BoundingSphere& bs ) const + inline bool intersects( const BoundingSphereImpl& bs ) const { return valid() && bs.valid() && ((_center - bs._center).length2() <= (_radius + bs._radius)*(_radius + bs._radius)); } - + }; + +template + template +void BoundingSphereImpl::expandBy(const vector_type& v) +{ + if (valid()) + { + vec_type dv = v-_center; + value_type r = dv.length(); + if (r>_radius) + { + value_type dr = (r-_radius)*0.5; + _center += dv*(dr/r); + _radius += dr; + } // else do nothing as vertex is within sphere. + } + else + { + _center = v; + _radius = 0.0; + } +} + +template + template +void BoundingSphereImpl::expandRadiusBy(const vector_type& v) +{ + if (valid()) + { + value_type r = (v-_center).length(); + if (r>_radius) _radius = r; + // else do nothing as vertex is within sphere. + } + else + { + _center = v; + _radius = 0.0; + } +} + +template +void BoundingSphereImpl::expandBy(const BoundingSphereImpl& sh) +{ + // ignore operation if incomming BoundingSphere is invalid. + if (!sh.valid()) return; + + // This sphere is not set so use the inbound sphere + if (!valid()) + { + _center = sh._center; + _radius = sh._radius; + + return; + } + + + // Calculate d == The distance between the sphere centers + double d = ( _center - sh.center() ).length(); + + // New sphere is already inside this one + if ( d + sh.radius() <= _radius ) + { + return; + } + + // New sphere completely contains this one + if ( d + _radius <= sh.radius() ) + { + _center = sh._center; + _radius = sh._radius; + return; + } + + + // Build a new sphere that completely contains the other two: + // + // The center point lies halfway along the line between the furthest + // points on the edges of the two spheres. + // + // Computing those two points is ugly - so we'll use similar triangles + double new_radius = (_radius + d + sh.radius() ) * 0.5; + double ratio = ( new_radius - _radius ) / d ; + + _center[0] += ( sh.center()[0] - _center[0] ) * ratio; + _center[1] += ( sh.center()[1] - _center[1] ) * ratio; + _center[2] += ( sh.center()[2] - _center[2] ) * ratio; + + _radius = new_radius; + +} + +template +void BoundingSphereImpl::expandRadiusBy(const BoundingSphereImpl& sh) +{ + if (sh.valid()) + { + if (valid()) + { + value_type r = (sh._center-_center).length()+sh._radius; + if (r>_radius) _radius = r; + // else do nothing as vertex is within sphere. + } + else + { + _center = sh._center; + _radius = sh._radius; + } + } +} + +template +void BoundingSphereImpl::expandBy(const BoundingBoxImpl& bb) +{ + if (bb.valid()) + { + if (valid()) + { + BoundingBoxImpl newbb(bb); + + for(unsigned int c=0;c<8;++c) + { + vec_type v = bb.corner(c)-_center; // get the direction vector from corner + v.normalize(); // normalise it. + v *= -_radius; // move the vector in the opposite direction distance radius. + v += _center; // move to absolute position. + newbb.expandBy(v); // add it into the new bounding box. + } + + _center = newbb.center(); + _radius = newbb.radius(); + + } + else + { + _center = bb.center(); + _radius = bb.radius(); + } + } +} + +template +void BoundingSphereImpl::expandRadiusBy(const BoundingBoxImpl& bb) +{ + if (bb.valid()) + { + if (valid()) + { + for(unsigned int c=0;c<8;++c) + { + expandRadiusBy(bb.corner(c)); + } + } + else + { + _center = bb.center(); + _radius = bb.radius(); + } + } +} + +typedef BoundingSphereImpl BoundingSpheref; +typedef BoundingSphereImpl BoundingSphered; + +#ifdef OSG_USE_FLOAT_BOUNDINGSPHERE + typedef BoundingSpheref BoundingSphere; +#else + typedef BoundingSphered BoundingSphere; +#endif } #endif diff --git a/src/osg/BoundingBox.cpp b/src/osg/BoundingBox.cpp deleted file mode 100644 index 3f644035f..000000000 --- a/src/osg/BoundingBox.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield - * - * This library is open source and may be redistributed and/or modified under - * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or - * (at your option) any later version. The full license is in LICENSE file - * included with this distribution, and on the openscenegraph.org website. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * OpenSceneGraph Public License for more details. -*/ -#include -#include - -using namespace osg; - -void BoundingBox::expandBy(const BoundingBox& bb) -{ - if (!bb.valid()) return; - - if(bb._min.x()<_min.x()) _min.x() = bb._min.x(); - if(bb._max.x()>_max.x()) _max.x() = bb._max.x(); - - if(bb._min.y()<_min.y()) _min.y() = bb._min.y(); - if(bb._max.y()>_max.y()) _max.y() = bb._max.y(); - - if(bb._min.z()<_min.z()) _min.z() = bb._min.z(); - if(bb._max.z()>_max.z()) _max.z() = bb._max.z(); -} - - -void BoundingBox::expandBy(const BoundingSphere& sh) -{ - if (!sh.valid()) return; - - if(sh._center.x()-sh._radius<_min.x()) _min.x() = sh._center.x()-sh._radius; - if(sh._center.x()+sh._radius>_max.x()) _max.x() = sh._center.x()+sh._radius; - - if(sh._center.y()-sh._radius<_min.y()) _min.y() = sh._center.y()-sh._radius; - if(sh._center.y()+sh._radius>_max.y()) _max.y() = sh._center.y()+sh._radius; - - if(sh._center.z()-sh._radius<_min.z()) _min.z() = sh._center.z()-sh._radius; - if(sh._center.z()+sh._radius>_max.z()) _max.z() = sh._center.z()+sh._radius; -} diff --git a/src/osg/BoundingSphere.cpp b/src/osg/BoundingSphere.cpp deleted file mode 100644 index 558eb150d..000000000 --- a/src/osg/BoundingSphere.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield - * - * This library is open source and may be redistributed and/or modified under - * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or - * (at your option) any later version. The full license is in LICENSE file - * included with this distribution, and on the openscenegraph.org website. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * OpenSceneGraph Public License for more details. -*/ -#include -#include - -using namespace osg; - -void BoundingSphere::expandBy(const Vec3f& v) -{ - if (valid()) - { - vec_type dv = v-_center; - value_type r = dv.length(); - if (r>_radius) - { - value_type dr = (r-_radius)*0.5; - _center += dv*(dr/r); - _radius += dr; - } // else do nothing as vertex is within sphere. - } - else - { - _center = v; - _radius = 0.0; - } -} - - -void BoundingSphere::expandRadiusBy(const Vec3f& v) -{ - if (valid()) - { - value_type r = (v-_center).length(); - if (r>_radius) _radius = r; - // else do nothing as vertex is within sphere. - } - else - { - _center = v; - _radius = 0.0; - } -} - - - -void BoundingSphere::expandBy(const Vec3d& v) -{ - if (valid()) - { - vec_type dv = v-_center; - value_type r = dv.length(); - if (r>_radius) - { - value_type dr = (r-_radius)*0.5; - _center += dv*(dr/r); - _radius += dr; - } // else do nothing as vertex is within sphere. - } - else - { - _center = v; - _radius = 0.0; - } -} - - -void BoundingSphere::expandRadiusBy(const Vec3d& v) -{ - if (valid()) - { - value_type r = (v-_center).length(); - if (r>_radius) _radius = r; - // else do nothing as vertex is within sphere. - } - else - { - _center = v; - _radius = 0.0; - } -} - - - -void BoundingSphere::expandBy(const BoundingSphere& sh) -{ - // ignore operation if incomming BoundingSphere is invalid. - if (!sh.valid()) return; - - // This sphere is not set so use the inbound sphere - if (!valid()) - { - _center = sh._center; - _radius = sh._radius; - - return; - } - - - // Calculate d == The distance between the sphere centers - double d = ( _center - sh.center() ).length(); - - // New sphere is already inside this one - if ( d + sh.radius() <= _radius ) - { - return; - } - - // New sphere completely contains this one - if ( d + _radius <= sh.radius() ) - { - _center = sh._center; - _radius = sh._radius; - return; - } - - - // Build a new sphere that completely contains the other two: - // - // The center point lies halfway along the line between the furthest - // points on the edges of the two spheres. - // - // Computing those two points is ugly - so we'll use similar triangles - double new_radius = (_radius + d + sh.radius() ) * 0.5; - double ratio = ( new_radius - _radius ) / d ; - - _center[0] += ( sh.center()[0] - _center[0] ) * ratio; - _center[1] += ( sh.center()[1] - _center[1] ) * ratio; - _center[2] += ( sh.center()[2] - _center[2] ) * ratio; - - _radius = new_radius; - -} - - -void BoundingSphere::expandRadiusBy(const BoundingSphere& sh) -{ - if (sh.valid()) - { - if (valid()) - { - value_type r = (sh._center-_center).length()+sh._radius; - if (r>_radius) _radius = r; - // else do nothing as vertex is within sphere. - } - else - { - _center = sh._center; - _radius = sh._radius; - } - } -} - -void BoundingSphere::expandBy(const BoundingBox& bb) -{ - if (bb.valid()) - { - if (valid()) - { - BoundingBox newbb(bb); - - for(unsigned int c=0;c<8;++c) - { - Vec3 v = bb.corner(c)-_center; // get the direction vector from corner - v.normalize(); // normalise it. - v *= -_radius; // move the vector in the opposite direction distance radius. - v += _center; // move to absolute position. - newbb.expandBy(v); // add it into the new bounding box. - } - - _center = newbb.center(); - _radius = newbb.radius(); - - } - else - { - _center = bb.center(); - _radius = bb.radius(); - } - } -} - -void BoundingSphere::expandRadiusBy(const BoundingBox& bb) -{ - if (bb.valid()) - { - if (valid()) - { - for(unsigned int c=0;c<8;++c) - { - expandRadiusBy(bb.corner(c)); - } - } - else - { - _center = bb.center(); - _radius = bb.radius(); - } - } -} diff --git a/src/osg/CMakeLists.txt b/src/osg/CMakeLists.txt index 19c682c5c..834e18e66 100644 --- a/src/osg/CMakeLists.txt +++ b/src/osg/CMakeLists.txt @@ -197,8 +197,6 @@ ADD_LIBRARY(${LIB_NAME} BlendColor.cpp BlendEquation.cpp BlendFunc.cpp - BoundingBox.cpp - BoundingSphere.cpp BufferObject.cpp Camera.cpp CameraView.cpp