root/OpenSceneGraph/trunk/include/osg/BoundingSphere @ 13041

Revision 13041, 9.4 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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
14#ifndef OSG_BOUNDINGSPHERE
15#define OSG_BOUNDINGSPHERE 1
16
17#include <osg/Config>
18#include <osg/Export>
19#include <osg/Vec3f>
20#include <osg/Vec3d>
21
22namespace osg {
23
24template<typename VT>
25class BoundingBoxImpl;
26
27/** General purpose bounding sphere class for enclosing nodes/objects/vertices.
28  * Bounds internal osg::Nodes in the scene, assists in view frustum culling,
29  * etc. Similar in function to BoundingBox, it's quicker for evaluating
30  * culling but generally will not cull as aggressively because it encloses a
31  * greater volume.
32*/
33template<typename VT>
34class BoundingSphereImpl
35{
36    public:
37        typedef VT vec_type;
38        typedef typename VT::value_type value_type;
39
40        vec_type    _center;
41        value_type  _radius;
42
43        /** Construct a default bounding sphere with radius to -1.0f, representing an invalid/unset bounding sphere.*/
44        BoundingSphereImpl() : _center(0.0,0.0,0.0),_radius(-1.0) {}
45
46        /** Creates a bounding sphere initialized to the given extents. */
47        BoundingSphereImpl(const vec_type& center, value_type radius) : _center(center),_radius(radius) {}
48
49        /** Creates a bounding sphere initialized to the given extents. */
50        BoundingSphereImpl(const BoundingSphereImpl& bs) : _center(bs._center),_radius(bs._radius) {}
51
52        /** Creates a bounding sphere initialized to the given extents. */
53        BoundingSphereImpl(const BoundingBoxImpl<VT>& bb) : _center(0.0,0.0,0.0),_radius(-1.0) { expandBy(bb); }
54
55        /** Clear the bounding sphere. Reset to default values. */
56        inline void init()
57        {
58            _center.set(0.0,0.0,0.0);
59            _radius = -1.0;
60        }
61
62        /** Returns true of the bounding sphere extents are valid, false
63          * otherwise. */
64        inline bool valid() const { return _radius>=0.0; }
65
66        /** Set the bounding sphere to the given center/radius using floats. */
67        inline void set(const vec_type& center,value_type radius)
68        {
69            _center = center;
70            _radius = radius;
71        }
72
73        /** Returns the center of the bounding sphere. */
74        inline vec_type& center() { return _center; }
75
76        /** Returns the const center of the bounding sphere. */
77        inline const vec_type& center() const { return _center; }
78
79        /** Returns the radius of the bounding sphere. */
80        inline value_type& radius() { return _radius; }
81        /** Returns the const radius of the bounding sphere. */
82        inline value_type radius() const { return _radius; }
83
84        /** Returns the squared length of the radius. Note, For performance
85          * reasons, the calling method is responsible for checking to make
86          * sure the sphere is valid. */
87        inline value_type radius2() const { return _radius*_radius; }
88
89        /** Expands the sphere to encompass the given point. Repositions the
90          * sphere center to minimize the radius increase. If the sphere is
91          * uninitialized, set its center to v and radius to zero. */
92        template<typename vector_type>
93        void expandBy(const vector_type& v);
94
95        /** Expands the sphere to encompass the given point. Does not
96          * reposition the sphere center. If the sphere is
97          * uninitialized, set its center to v and radius to zero. */
98        template<typename vector_type>
99        void expandRadiusBy(const vector_type& v);
100
101        /** Expands the sphere to encompass the given sphere. Repositions the
102          * sphere center to minimize the radius increase. If the sphere is
103          * uninitialized, set its center and radius to match sh. */
104        void expandBy(const BoundingSphereImpl& sh);
105
106        /** Expands the sphere to encompass the given sphere. Does not
107          * repositions the sphere center. If the sphere is
108          * uninitialized, set its center and radius to match sh. */
109        void expandRadiusBy(const BoundingSphereImpl& sh);
110
111        /** Expands the sphere to encompass the given box. Repositions the
112          * sphere center to minimize the radius increase. */
113        void expandBy(const BoundingBoxImpl<VT>& bb);
114
115        /** Expands the sphere to encompass the given box. Does not
116          * repositions the sphere center. */
117        void expandRadiusBy(const BoundingBoxImpl<VT>& bb);
118
119        /** Returns true if v is within the sphere. */
120        inline bool contains(const vec_type& v) const
121        {
122            return valid() && ((v-_center).length2()<=radius2());
123        }
124
125
126        /** Returns true if there is a non-empty intersection with the given
127          * bounding sphere. */
128        inline bool intersects( const BoundingSphereImpl& bs ) const
129        {
130            return valid() && bs.valid() &&
131                   ((_center - bs._center).length2() <= (_radius + bs._radius)*(_radius + bs._radius));
132        }
133
134};
135
136
137template<typename VT>
138 template<typename vector_type>
139void BoundingSphereImpl<VT>::expandBy(const vector_type& v)
140{
141    if (valid())
142    {
143        vec_type dv = v-_center;
144        value_type r = dv.length();
145        if (r>_radius)
146        {
147            value_type dr = (r-_radius)*0.5;
148            _center += dv*(dr/r);
149            _radius += dr;
150        } // else do nothing as vertex is within sphere.
151    }
152    else
153    {
154        _center = v;
155        _radius = 0.0;
156    }
157}
158
159template<typename VT>
160 template<typename vector_type>
161void BoundingSphereImpl<VT>::expandRadiusBy(const vector_type& v)
162{
163    if (valid())
164    {
165        value_type r = (v-_center).length();
166        if (r>_radius) _radius = r;
167        // else do nothing as vertex is within sphere.
168    }
169    else
170    {
171        _center = v;
172        _radius = 0.0;
173    }
174}
175
176template<typename VT>
177void BoundingSphereImpl<VT>::expandBy(const BoundingSphereImpl& sh)
178{
179    // ignore operation if incomming BoundingSphere is invalid.
180    if (!sh.valid()) return;
181
182    // This sphere is not set so use the inbound sphere
183    if (!valid())
184    {
185        _center = sh._center;
186        _radius = sh._radius;
187
188        return;
189    }
190
191
192    // Calculate d == The distance between the sphere centers
193    double d = ( _center - sh.center() ).length();
194
195    // New sphere is already inside this one
196    if ( d + sh.radius() <= _radius )
197    {
198        return;
199    }
200
201    //  New sphere completely contains this one
202    if ( d + _radius <= sh.radius() )
203    {
204        _center = sh._center;
205        _radius = sh._radius;
206        return;
207    }
208
209
210    // Build a new sphere that completely contains the other two:
211    //
212    // The center point lies halfway along the line between the furthest
213    // points on the edges of the two spheres.
214    //
215    // Computing those two points is ugly - so we'll use similar triangles
216    double new_radius = (_radius + d + sh.radius() ) * 0.5;
217    double ratio = ( new_radius - _radius ) / d ;
218
219    _center[0] += ( sh.center()[0] - _center[0] ) * ratio;
220    _center[1] += ( sh.center()[1] - _center[1] ) * ratio;
221    _center[2] += ( sh.center()[2] - _center[2] ) * ratio;
222
223    _radius = new_radius;
224
225}
226
227template<typename VT>
228void BoundingSphereImpl<VT>::expandRadiusBy(const BoundingSphereImpl& sh)
229{
230    if (sh.valid())
231    {
232        if (valid())
233        {
234            value_type r = (sh._center-_center).length()+sh._radius;
235            if (r>_radius) _radius = r;
236            // else do nothing as vertex is within sphere.
237        }
238        else
239        {
240            _center = sh._center;
241            _radius = sh._radius;
242        }
243    }
244}
245
246template<typename VT>
247void BoundingSphereImpl<VT>::expandBy(const BoundingBoxImpl<VT>& bb)
248{
249    if (bb.valid())
250    {
251        if (valid())
252        {
253            BoundingBoxImpl<vec_type> newbb(bb);
254
255            for(unsigned int c=0;c<8;++c)
256            {
257                vec_type v = bb.corner(c)-_center; // get the direction vector from corner
258                v.normalize(); // normalise it.
259                v *= -_radius; // move the vector in the opposite direction distance radius.
260                v += _center; // move to absolute position.
261                newbb.expandBy(v); // add it into the new bounding box.
262            }
263
264            _center = newbb.center();
265            _radius = newbb.radius();
266
267        }
268        else
269        {
270            _center = bb.center();
271            _radius = bb.radius();
272        }
273    }
274}
275
276template<typename VT>
277void BoundingSphereImpl<VT>::expandRadiusBy(const BoundingBoxImpl<VT>& bb)
278{
279    if (bb.valid())
280    {
281        if (valid())
282        {
283            for(unsigned int c=0;c<8;++c)
284            {
285                expandRadiusBy(bb.corner(c));
286            }
287        }
288        else
289        {
290            _center = bb.center();
291            _radius = bb.radius();
292        }
293    }
294}
295
296typedef BoundingSphereImpl<Vec3f> BoundingSpheref;
297typedef BoundingSphereImpl<Vec3d> BoundingSphered;
298
299#ifdef OSG_USE_FLOAT_BOUNDINGSPHERE
300        typedef BoundingSpheref BoundingSphere;
301#else
302        typedef BoundingSphered BoundingSphere;
303#endif
304}
305
306#endif
Note: See TracBrowser for help on using the browser.