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

Revision 13041, 14.3 kB (checked in by robert, 2 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_PLANE
15#define OSG_PLANE 1
16
17#include <osg/Config>
18#include <osg/Export>
19#include <osg/Vec3>
20#include <osg/Vec4>
21#include <osg/Matrix>
22#include <osg/BoundingSphere>
23#include <osg/BoundingBox>
24
25#include <vector>
26
27namespace osg {
28
29/** @brief A plane class. It can be used to represent an infinite plane.
30  *
31  * The infinite plane is described by an implicit plane equation a*x+b*y+c*z+d = 0. Though it is not mandatory that
32  * a^2+b^2+c^2 = 1 is fulfilled in general some methods require it (@see osg::Plane::distance). */
33class OSG_EXPORT Plane
34{
35
36    public:
37
38#ifdef OSG_USE_FLOAT_PLANE
39        /** Type of Plane class.*/
40        typedef float value_type;
41        typedef Vec3f Vec3_type;
42        typedef Vec4f Vec4_type;
43#else
44        /** Type of Plane class.*/
45        typedef double value_type;
46        typedef Vec3d Vec3_type;
47        typedef Vec4d Vec4_type;
48#endif
49
50        /** Number of vector components. */
51        enum { num_components = 3 };
52
53
54        /// Default constructor
55        /** The default constructor initializes all values to zero.
56          * @warning Although the method osg::Plane::valid() will return true after the default constructors call the plane
57          *          is mathematically invalid! Default data do not describe a valid plane. */
58        inline Plane() { _fv[0]=0.0; _fv[1]=0.0; _fv[2]=0.0; _fv[3]=0.0; _lowerBBCorner = 0; _upperBBCorner = 0; }
59        inline Plane(const Plane& pl) { set(pl); }
60        /// Constructor
61        /** The plane is described as a*x+b*y+c*z+d = 0.
62          * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed values are not normalized. */
63        inline Plane(value_type a,value_type b,value_type c,value_type d) { set(a,b,c,d); }
64
65        /// Constructor
66        /** The plane can also be described as vec*[x,y,z,1].
67          * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed values are not normalized. */
68        inline Plane(const Vec4f& vec) { set(vec); }
69        /// Constructor
70        /** The plane can also be described as vec*[x,y,z,1].
71          * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed values are not normalized. */
72        inline Plane(const Vec4d& vec) { set(vec); }
73
74        /// Constructor
75        /** This constructor initializes the internal values directly without any checking or manipulation.
76          * @param norm The normal of the plane.
77          * @param d    The negative distance from the point of origin to the plane.
78          * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed normal was not normalized. */
79        inline Plane(const Vec3_type& norm,value_type d) { set(norm,d); }
80
81        /// Constructor
82        /** This constructor calculates from the three points describing an infinite plane the internal values.
83          * @param v1 Point in the plane.
84          * @param v2 Point in the plane.
85          * @param v3 Point in the plane.
86          * @remark After this constructor call the plane's normal is normalized in case the three points described a mathematically
87          *         valid plane.
88          * @remark The normal is determined by building the cross product of (v2-v1) ^ (v3-v2). */
89        inline Plane(const Vec3_type& v1, const Vec3_type& v2, const Vec3_type& v3) { set(v1,v2,v3); }
90
91        /// Constructor
92        /** This constructor initializes the internal values directly without any checking or manipulation.
93          * @param norm  The normal of the plane.
94          * @param point A point of the plane.
95          * @remark You may call osg::Plane::MakeUnitLength afterwards if the passed normal was not normalized. */
96        inline Plane(const Vec3_type& norm, const Vec3_type& point) { set(norm,point); }
97
98        inline Plane& operator = (const Plane& pl)
99        {
100            if (&pl==this) return *this;
101            set(pl);
102            return *this;
103        }
104
105        inline void set(const Plane& pl) { _fv[0]=pl._fv[0]; _fv[1]=pl._fv[1]; _fv[2]=pl._fv[2]; _fv[3]=pl._fv[3]; calculateUpperLowerBBCorners(); }
106        inline void set(value_type a, value_type b, value_type c, value_type d) { _fv[0]=a; _fv[1]=b; _fv[2]=c; _fv[3]=d; calculateUpperLowerBBCorners(); }
107
108        inline void set(const Vec4f& vec) { set(vec[0],vec[1],vec[2],vec[3]); }
109        inline void set(const Vec4d& vec) { set(vec[0],vec[1],vec[2],vec[3]); }
110
111        inline void set(const Vec3_type& norm, double d) { set(norm[0],norm[1],norm[2],d); }
112
113        inline void set(const Vec3_type& v1, const Vec3_type& v2, const Vec3_type& v3)
114        {
115            Vec3_type norm = (v2-v1)^(v3-v2);
116            value_type length = norm.length();
117            if (length>1e-6) norm/= length;
118            else norm.set(0.0,0.0,0.0);
119            set(norm[0],norm[1],norm[2],-(v1*norm));
120        }
121
122        inline void set(const Vec3_type& norm, const Vec3_type& point)
123        {
124            value_type d = -norm[0]*point[0] - norm[1]*point[1] - norm[2]*point[2];
125            set(norm[0],norm[1],norm[2],d);
126        }
127
128        /** flip/reverse the orientation of the plane.*/
129        inline void flip()
130        {
131            _fv[0] = -_fv[0];
132            _fv[1] = -_fv[1];
133            _fv[2] = -_fv[2];
134            _fv[3] = -_fv[3];
135            calculateUpperLowerBBCorners();
136        }
137
138        /** This method multiplies the coefficients of the plane equation with a constant factor so that the
139          * equation a^2+b^2+c^2 = 1 holds. */
140        inline void makeUnitLength()
141        {
142            value_type inv_length = 1.0 / sqrt(_fv[0]*_fv[0] + _fv[1]*_fv[1]+ _fv[2]*_fv[2]);
143            _fv[0] *= inv_length;
144            _fv[1] *= inv_length;
145            _fv[2] *= inv_length;
146            _fv[3] *= inv_length;
147        }
148
149        /** calculate the upper and lower bounding box corners to be used
150          * in the intersect(BoundingBox&) method for speeding calculations.*/
151        inline void calculateUpperLowerBBCorners()
152        {
153            _upperBBCorner = (_fv[0]>=0.0?1:0) |
154                             (_fv[1]>=0.0?2:0) |
155                             (_fv[2]>=0.0?4:0);
156
157            _lowerBBCorner = (~_upperBBCorner)&7;
158
159        }
160
161        /// Checks if all internal values describing the plane have valid numbers
162        /** @warning This method does not check if the plane is mathematically correctly described!
163          * @remark  The only case where all elements have valid numbers and the plane description is invalid occurs if the plane's normal
164          *          is zero. */
165        inline bool valid() const { return !isNaN(); }
166        inline bool isNaN() const { return osg::isNaN(_fv[0]) || osg::isNaN(_fv[1]) || osg::isNaN(_fv[2]) || osg::isNaN(_fv[3]); }
167
168        inline bool operator == (const Plane& plane) const { return _fv[0]==plane._fv[0] && _fv[1]==plane._fv[1] && _fv[2]==plane._fv[2] && _fv[3]==plane._fv[3]; }
169
170        inline bool operator != (const Plane& plane) const { return _fv[0]!=plane._fv[0] || _fv[1]!=plane._fv[1] || _fv[2]!=plane._fv[2] || _fv[3]!=plane._fv[3]; }
171
172        /** A plane is said to be smaller than another plane if the first non-identical element of the internal array is smaller than the
173          * corresponding element of the other plane. */
174        inline bool operator <  (const Plane& plane) const
175        {
176            if (_fv[0]<plane._fv[0]) return true;
177            else if (_fv[0]>plane._fv[0]) return false;
178            else if (_fv[1]<plane._fv[1]) return true;
179            else if (_fv[1]>plane._fv[1]) return false;
180            else if (_fv[2]<plane._fv[2]) return true;
181            else if (_fv[2]>plane._fv[2]) return false;
182            else return (_fv[3]<plane._fv[3]);
183        }
184
185
186        inline value_type* ptr() { return _fv; }
187        inline const value_type* ptr() const { return _fv; }
188
189        inline Vec4_type asVec4() const { return Vec4_type(_fv[0],_fv[1],_fv[2],_fv[3]); }
190
191        inline value_type& operator [] (unsigned int i) { return _fv[i]; }
192        inline value_type operator [] (unsigned int i) const { return _fv[i]; }
193
194
195        inline Vec3_type getNormal() const { return Vec3_type(_fv[0],_fv[1],_fv[2]); }
196
197        /** Calculate the distance between a point and the plane.
198          * @remark This method only leads to real distance values if the plane's norm is 1.
199          * @sa osg::Plane::makeUnitLength */
200        inline float distance(const osg::Vec3f& v) const
201        {
202            return _fv[0]*v.x()+
203                   _fv[1]*v.y()+
204                   _fv[2]*v.z()+
205                   _fv[3];
206        }
207        /** Calculate the distance between a point and the plane.
208          * @remark This method only leads to real distance values if the plane's norm is 1.
209          * @sa osg::Plane::makeUnitLength */
210        inline double distance(const osg::Vec3d& v) const
211        {
212            return _fv[0]*v.x()+
213                   _fv[1]*v.y()+
214                   _fv[2]*v.z()+
215                   _fv[3];
216        }
217
218        /** calculate the dot product of the plane normal and a point.*/
219        inline float dotProductNormal(const osg::Vec3f& v) const
220        {
221            return _fv[0]*v.x()+
222                   _fv[1]*v.y()+
223                   _fv[2]*v.z();
224        }
225
226        /** calculate the dot product of the plane normal and a point.*/
227        inline double dotProductNormal(const osg::Vec3d& v) const
228        {
229            return _fv[0]*v.x()+
230                   _fv[1]*v.y()+
231                   _fv[2]*v.z();
232        }
233
234        /** intersection test between plane and vertex list
235            return 1 if the bs is completely above plane,
236            return 0 if the bs intersects the plane,
237            return -1 if the bs is completely below the plane.*/
238        inline int intersect(const std::vector<Vec3f>& vertices) const
239        {
240            if (vertices.empty()) return -1;
241
242            int noAbove = 0;
243            int noBelow = 0;
244            int noOn = 0;
245            for(std::vector<Vec3f>::const_iterator itr=vertices.begin();
246                itr != vertices.end();
247                ++itr)
248            {
249                float d = distance(*itr);
250                if (d>0.0f) ++noAbove;
251                else if (d<0.0f) ++noBelow;
252                else ++noOn;
253            }
254
255            if (noAbove>0)
256            {
257                if (noBelow>0) return 0;
258                else return 1;
259            }
260            return -1; // treat points on line as outside...
261        }
262
263        /** intersection test between plane and vertex list
264            return 1 if the bs is completely above plane,
265            return 0 if the bs intersects the plane,
266            return -1 if the bs is completely below the plane.*/
267        inline int intersect(const std::vector<Vec3d>& vertices) const
268        {
269            if (vertices.empty()) return -1;
270
271            int noAbove = 0;
272            int noBelow = 0;
273            int noOn = 0;
274            for(std::vector<Vec3d>::const_iterator itr=vertices.begin();
275                itr != vertices.end();
276                ++itr)
277            {
278                double d = distance(*itr);
279                if (d>0.0) ++noAbove;
280                else if (d<0.0) ++noBelow;
281                else ++noOn;
282            }
283
284            if (noAbove>0)
285            {
286                if (noBelow>0) return 0;
287                else return 1;
288            }
289            return -1; // treat points on line as outside...
290        }
291
292        /** intersection test between plane and bounding sphere.
293            return 1 if the bs is completely above plane,
294            return 0 if the bs intersects the plane,
295            return -1 if the bs is completely below the plane.*/
296        inline int intersect(const BoundingSphere& bs) const
297        {
298            float d = distance(bs.center());
299
300            if (d>bs.radius()) return 1;
301            else if (d<-bs.radius()) return -1;
302            else return 0;
303        }
304
305
306        /** intersection test between plane and bounding sphere.
307            return 1 if the bs is completely above plane,
308            return 0 if the bs intersects the plane,
309            return -1 if the bs is completely below the plane.*/
310        inline int intersect(const BoundingBox& bb) const
311        {
312            // if lowest point above plane than all above.
313            if (distance(bb.corner(_lowerBBCorner))>0.0f) return 1;
314
315            // if highest point is below plane then all below.
316            if (distance(bb.corner(_upperBBCorner))<0.0f) return -1;
317
318            // d_lower<=0.0f && d_upper>=0.0f
319            // therefore must be crossing plane.
320            return 0;
321
322        }
323
324        /** Transform the plane by matrix.  Note, this operation carries out
325          * the calculation of the inverse of the matrix since a plane
326          * must be multiplied by the inverse transposed to transform it. This
327          * make this operation expensive.  If the inverse has been already
328          * calculated elsewhere then use transformProvidingInverse() instead.
329          * See http://www.worldserver.com/turk/computergraphics/NormalTransformations.pdf*/
330        inline void transform(const osg::Matrix& matrix)
331        {
332            osg::Matrix inverse;
333            inverse.invert(matrix);
334            transformProvidingInverse(inverse);
335        }
336
337        /** Transform the plane by providing a pre inverted matrix.
338          * see transform for details. */
339        inline void transformProvidingInverse(const osg::Matrix& matrix)
340        {
341            // note pre multiplications, which effectively transposes matrix.
342            Vec4_type vec(_fv[0],_fv[1],_fv[2],_fv[3]);
343            vec = matrix * vec;
344            set(vec);
345            makeUnitLength();
346        }
347
348    protected:
349
350        /** Vec member variable. */
351        value_type _fv[4];
352
353        // variables cached to optimize calcs against bounding boxes.
354        unsigned int        _upperBBCorner;
355        unsigned int        _lowerBBCorner;
356
357
358};
359
360} // end of namespace
361
362#endif
Note: See TracBrowser for help on using the browser.