Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/include/OgreMath.h @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 23.8 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#ifndef __Math_H__
30#define __Math_H__
31
32#include "OgrePrerequisites.h"
33
34namespace Ogre
35{
36    /** Wrapper class which indicates a given angle value is in Radians.
37    @remarks
38        Radian values are interchangeable with Degree values, and conversions
39        will be done automatically between them.
40    */
41        class Radian
42        {
43                Real mRad;
44
45        public:
46                explicit Radian ( Real r=0 ) : mRad(r) {}
47                Radian ( const Degree& d );
48                Radian& operator = ( const Real& f ) { mRad = f; return *this; }
49                Radian& operator = ( const Radian& r ) { mRad = r.mRad; return *this; }
50                Radian& operator = ( const Degree& d );
51
52                Real valueDegrees() const; // see bottom of this file
53                Real valueRadians() const { return mRad; }
54                Real valueAngleUnits() const;
55
56        const Radian& operator + () const { return *this; }
57                Radian operator + ( const Radian& r ) const { return Radian ( mRad + r.mRad ); }
58                Radian operator + ( const Degree& d ) const;
59                Radian& operator += ( const Radian& r ) { mRad += r.mRad; return *this; }
60                Radian& operator += ( const Degree& d );
61                Radian operator - () const { return Radian(-mRad); }
62                Radian operator - ( const Radian& r ) const { return Radian ( mRad - r.mRad ); }
63                Radian operator - ( const Degree& d ) const;
64                Radian& operator -= ( const Radian& r ) { mRad -= r.mRad; return *this; }
65                Radian& operator -= ( const Degree& d );
66                Radian operator * ( Real f ) const { return Radian ( mRad * f ); }
67        Radian operator * ( const Radian& f ) const { return Radian ( mRad * f.mRad ); }
68                Radian& operator *= ( Real f ) { mRad *= f; return *this; }
69                Radian operator / ( Real f ) const { return Radian ( mRad / f ); }
70                Radian& operator /= ( Real f ) { mRad /= f; return *this; }
71
72                bool operator <  ( const Radian& r ) const { return mRad <  r.mRad; }
73                bool operator <= ( const Radian& r ) const { return mRad <= r.mRad; }
74                bool operator == ( const Radian& r ) const { return mRad == r.mRad; }
75                bool operator != ( const Radian& r ) const { return mRad != r.mRad; }
76                bool operator >= ( const Radian& r ) const { return mRad >= r.mRad; }
77                bool operator >  ( const Radian& r ) const { return mRad >  r.mRad; }
78        };
79
80    /** Wrapper class which indicates a given angle value is in Degrees.
81    @remarks
82        Degree values are interchangeable with Radian values, and conversions
83        will be done automatically between them.
84    */
85        class Degree
86        {
87                Real mDeg; // if you get an error here - make sure to define/typedef 'Real' first
88
89        public:
90                explicit Degree ( Real d=0 ) : mDeg(d) {}
91                Degree ( const Radian& r ) : mDeg(r.valueDegrees()) {}
92                Degree& operator = ( const Real& f ) { mDeg = f; return *this; }
93                Degree& operator = ( const Degree& d ) { mDeg = d.mDeg; return *this; }
94                Degree& operator = ( const Radian& r ) { mDeg = r.valueDegrees(); return *this; }
95
96                Real valueDegrees() const { return mDeg; }
97                Real valueRadians() const; // see bottom of this file
98                Real valueAngleUnits() const;
99
100                const Degree& operator + () const { return *this; }
101                Degree operator + ( const Degree& d ) const { return Degree ( mDeg + d.mDeg ); }
102                Degree operator + ( const Radian& r ) const { return Degree ( mDeg + r.valueDegrees() ); }
103                Degree& operator += ( const Degree& d ) { mDeg += d.mDeg; return *this; }
104                Degree& operator += ( const Radian& r ) { mDeg += r.valueDegrees(); return *this; }
105                Degree operator - () const { return Degree(-mDeg); }
106                Degree operator - ( const Degree& d ) const { return Degree ( mDeg - d.mDeg ); }
107                Degree operator - ( const Radian& r ) const { return Degree ( mDeg - r.valueDegrees() ); }
108                Degree& operator -= ( const Degree& d ) { mDeg -= d.mDeg; return *this; }
109                Degree& operator -= ( const Radian& r ) { mDeg -= r.valueDegrees(); return *this; }
110                Degree operator * ( Real f ) const { return Degree ( mDeg * f ); }
111        Degree operator * ( const Degree& f ) const { return Degree ( mDeg * f.mDeg ); }
112                Degree& operator *= ( Real f ) { mDeg *= f; return *this; }
113                Degree operator / ( Real f ) const { return Degree ( mDeg / f ); }
114                Degree& operator /= ( Real f ) { mDeg /= f; return *this; }
115
116                bool operator <  ( const Degree& d ) const { return mDeg <  d.mDeg; }
117                bool operator <= ( const Degree& d ) const { return mDeg <= d.mDeg; }
118                bool operator == ( const Degree& d ) const { return mDeg == d.mDeg; }
119                bool operator != ( const Degree& d ) const { return mDeg != d.mDeg; }
120                bool operator >= ( const Degree& d ) const { return mDeg >= d.mDeg; }
121                bool operator >  ( const Degree& d ) const { return mDeg >  d.mDeg; }
122        };
123
124    /** Wrapper class which identifies a value as the currently default angle
125        type, as defined by Math::setAngleUnit.
126    @remarks
127        Angle values will be automatically converted between radians and degrees,
128        as appropriate.
129    */
130        class Angle
131        {
132                Real mAngle;
133        public:
134                explicit Angle ( Real angle ) : mAngle(angle) {}
135                operator Radian() const;
136                operator Degree() const;
137        };
138
139        // these functions could not be defined within the class definition of class
140        // Radian because they required class Degree to be defined
141        inline Radian::Radian ( const Degree& d ) : mRad(d.valueRadians()) {
142        }
143        inline Radian& Radian::operator = ( const Degree& d ) {
144                mRad = d.valueRadians(); return *this;
145        }
146        inline Radian Radian::operator + ( const Degree& d ) const {
147                return Radian ( mRad + d.valueRadians() );
148        }
149        inline Radian& Radian::operator += ( const Degree& d ) {
150                mRad += d.valueRadians();
151                return *this;
152        }
153        inline Radian Radian::operator - ( const Degree& d ) const {
154                return Radian ( mRad - d.valueRadians() );
155        }
156        inline Radian& Radian::operator -= ( const Degree& d ) {
157                mRad -= d.valueRadians();
158                return *this;
159        }
160
161    /** Class to provide access to common mathematical functions.
162        @remarks
163            Most of the maths functions are aliased versions of the C runtime
164            library functions. They are aliased here to provide future
165            optimisation opportunities, either from faster RTLs or custom
166            math approximations.
167        @note
168            <br>This is based on MgcMath.h from
169            <a href="http://www.geometrictools.com/">Wild Magic</a>.
170    */
171    class _OgreExport Math
172    {
173   public:
174       /** The angular units used by the API. This functionality is now deprecated in favor
175               of discreet angular unit types ( see Degree and Radian above ). The only place
176                   this functionality is actually still used is when parsing files. Search for
177                   usage of the Angle class for those instances
178       */
179       enum AngleUnit
180       {
181           AU_DEGREE,
182           AU_RADIAN
183       };
184
185    protected:
186       // angle units used by the api
187       static AngleUnit msAngleUnit;
188
189        /// Size of the trig tables as determined by constructor.
190        static int mTrigTableSize;
191
192        /// Radian -> index factor value ( mTrigTableSize / 2 * PI )
193        static Real mTrigTableFactor;
194        static Real* mSinTable;
195        static Real* mTanTable;
196
197        /** Private function to build trig tables.
198        */
199        void buildTrigTables();
200
201                static Real SinTable (Real fValue);
202                static Real TanTable (Real fValue);
203    public:
204        /** Default constructor.
205            @param
206                trigTableSize Optional parameter to set the size of the
207                tables used to implement Sin, Cos, Tan
208        */
209        Math(unsigned int trigTableSize = 4096);
210
211        /** Default destructor.
212        */
213        ~Math();
214
215                static inline int IAbs (int iValue) { return ( iValue >= 0 ? iValue : -iValue ); }
216                static inline int ICeil (float fValue) { return int(ceil(fValue)); }
217                static inline int IFloor (float fValue) { return int(floor(fValue)); }
218        static int ISign (int iValue);
219
220                static inline Real Abs (Real fValue) { return Real(fabs(fValue)); }
221                static inline Degree Abs (const Degree& dValue) { return Degree(fabs(dValue.valueDegrees())); }
222                static inline Radian Abs (const Radian& rValue) { return Radian(fabs(rValue.valueRadians())); }
223                static Radian ACos (Real fValue);
224                static Radian ASin (Real fValue);
225                static inline Radian ATan (Real fValue) { return Radian(atan(fValue)); }
226                static inline Radian ATan2 (Real fY, Real fX) { return Radian(atan2(fY,fX)); }
227                static inline Real Ceil (Real fValue) { return Real(ceil(fValue)); }
228
229        /** Cosine function.
230            @param
231                fValue Angle in radians
232            @param
233                useTables If true, uses lookup tables rather than
234                calculation - faster but less accurate.
235        */
236        static inline Real Cos (const Radian& fValue, bool useTables = false) {
237                        return (!useTables) ? Real(cos(fValue.valueRadians())) : SinTable(fValue.valueRadians() + HALF_PI);
238                }
239        /** Cosine function.
240            @param
241                fValue Angle in radians
242            @param
243                useTables If true, uses lookup tables rather than
244                calculation - faster but less accurate.
245        */
246        static inline Real Cos (Real fValue, bool useTables = false) {
247                        return (!useTables) ? Real(cos(fValue)) : SinTable(fValue + HALF_PI);
248                }
249
250                static inline Real Exp (Real fValue) { return Real(exp(fValue)); }
251
252                static inline Real Floor (Real fValue) { return Real(floor(fValue)); }
253
254                static inline Real Log (Real fValue) { return Real(log(fValue)); }
255
256                static inline Real Pow (Real fBase, Real fExponent) { return Real(pow(fBase,fExponent)); }
257
258        static Real Sign (Real fValue);
259                static inline Radian Sign ( const Radian& rValue )
260                {
261                        return Radian(Sign(rValue.valueRadians()));
262                }
263                static inline Degree Sign ( const Degree& dValue )
264                {
265                        return Degree(Sign(dValue.valueDegrees()));
266                }
267
268        /** Sine function.
269            @param
270                fValue Angle in radians
271            @param
272                useTables If true, uses lookup tables rather than
273                calculation - faster but less accurate.
274        */
275        static inline Real Sin (const Radian& fValue, bool useTables = false) {
276                        return (!useTables) ? Real(sin(fValue.valueRadians())) : SinTable(fValue.valueRadians());
277                }
278        /** Sine function.
279            @param
280                fValue Angle in radians
281            @param
282                useTables If true, uses lookup tables rather than
283                calculation - faster but less accurate.
284        */
285        static inline Real Sin (Real fValue, bool useTables = false) {
286                        return (!useTables) ? Real(sin(fValue)) : SinTable(fValue);
287                }
288
289                static inline Real Sqr (Real fValue) { return fValue*fValue; }
290
291                static inline Real Sqrt (Real fValue) { return Real(sqrt(fValue)); }
292
293        static inline Radian Sqrt (const Radian& fValue) { return Radian(sqrt(fValue.valueRadians())); }
294
295        static inline Degree Sqrt (const Degree& fValue) { return Degree(sqrt(fValue.valueDegrees())); }
296
297        /** Inverse square root i.e. 1 / Sqrt(x), good for vector
298            normalisation.
299        */
300                static Real InvSqrt(Real fValue);
301
302        static Real UnitRandom ();  // in [0,1]
303
304        static Real RangeRandom (Real fLow, Real fHigh);  // in [fLow,fHigh]
305
306        static Real SymmetricRandom ();  // in [-1,1]
307
308        /** Tangent function.
309            @param
310                fValue Angle in radians
311            @param
312                useTables If true, uses lookup tables rather than
313                calculation - faster but less accurate.
314        */
315                static inline Real Tan (const Radian& fValue, bool useTables = false) {
316                        return (!useTables) ? Real(tan(fValue.valueRadians())) : TanTable(fValue.valueRadians());
317                }
318        /** Tangent function.
319            @param
320                fValue Angle in radians
321            @param
322                useTables If true, uses lookup tables rather than
323                calculation - faster but less accurate.
324        */
325                static inline Real Tan (Real fValue, bool useTables = false) {
326                        return (!useTables) ? Real(tan(fValue)) : TanTable(fValue);
327                }
328
329                static inline Real DegreesToRadians(Real degrees) { return degrees * fDeg2Rad; }
330        static inline Real RadiansToDegrees(Real radians) { return radians * fRad2Deg; }
331
332       /** These functions used to set the assumed angle units (radians or degrees)
333            expected when using the Angle type.
334       @par
335            You can set this directly after creating a new Root, and also before/after resource creation,
336            depending on whether you want the change to affect resource files.
337       */
338       static void setAngleUnit(AngleUnit unit);
339       /** Get the unit being used for angles. */
340       static AngleUnit getAngleUnit(void);
341
342       /** Convert from the current AngleUnit to radians. */
343       static Real AngleUnitsToRadians(Real units);
344       /** Convert from radians to the current AngleUnit . */
345       static Real RadiansToAngleUnits(Real radians);
346       /** Convert from the current AngleUnit to degrees. */
347       static Real AngleUnitsToDegrees(Real units);
348       /** Convert from degrees to the current AngleUnit. */
349       static Real DegreesToAngleUnits(Real degrees);
350
351       /** Checks whether a given point is inside a triangle, in a
352            2-dimensional (Cartesian) space.
353            @remarks
354                The vertices of the triangle must be given in either
355                trigonometrical (anticlockwise) or inverse trigonometrical
356                (clockwise) order.
357            @param
358                p The point.
359            @param
360                a The triangle's first vertex.
361            @param
362                b The triangle's second vertex.
363            @param
364                c The triangle's third vertex.
365            @returns
366                If the point resides in the triangle, <b>true</b> is
367                returned.
368            @par
369                If the point is outside the triangle, <b>false</b> is
370                returned.
371        */
372        static bool pointInTri2D(const Vector2& p, const Vector2& a, 
373                        const Vector2& b, const Vector2& c);
374
375       /** Checks whether a given 3D point is inside a triangle.
376       @remarks
377            The vertices of the triangle must be given in either
378            trigonometrical (anticlockwise) or inverse trigonometrical
379            (clockwise) order, and the point must be guaranteed to be in the
380                        same plane as the triangle
381        @param
382            p The point.
383        @param
384            a The triangle's first vertex.
385        @param
386            b The triangle's second vertex.
387        @param
388            c The triangle's third vertex.
389                @param
390                        normal The triangle plane's normal (passed in rather than calculated
391                                on demand since the callermay already have it)
392        @returns
393            If the point resides in the triangle, <b>true</b> is
394            returned.
395        @par
396            If the point is outside the triangle, <b>false</b> is
397            returned.
398        */
399        static bool pointInTri3D(const Vector3& p, const Vector3& a, 
400                        const Vector3& b, const Vector3& c, const Vector3& normal);
401        /** Ray / plane intersection, returns boolean result and distance. */
402        static std::pair<bool, Real> intersects(const Ray& ray, const Plane& plane);
403
404        /** Ray / sphere intersection, returns boolean result and distance. */
405        static std::pair<bool, Real> intersects(const Ray& ray, const Sphere& sphere, 
406            bool discardInside = true);
407       
408        /** Ray / box intersection, returns boolean result and distance. */
409        static std::pair<bool, Real> intersects(const Ray& ray, const AxisAlignedBox& box);
410
411        /** Ray / box intersection, returns boolean result and two intersection distance.
412        @param
413            ray The ray.
414        @param
415            box The box.
416        @param
417            d1 A real pointer to retrieve the near intersection distance
418                from the ray origin, maybe <b>null</b> which means don't care
419                about the near intersection distance.
420        @param
421            d2 A real pointer to retrieve the far intersection distance
422                from the ray origin, maybe <b>null</b> which means don't care
423                about the far intersection distance.
424        @returns
425            If the ray is intersects the box, <b>true</b> is returned, and
426            the near intersection distance is return by <i>d1</i>, the
427            far intersection distance is return by <i>d2</i>. Guarantee
428            <b>0</b> <= <i>d1</i> <= <i>d2</i>.
429        @par
430            If the ray isn't intersects the box, <b>false</b> is returned, and
431            <i>d1</i> and <i>d2</i> is unmodified.
432        */
433        static bool intersects(const Ray& ray, const AxisAlignedBox& box,
434            Real* d1, Real* d2);
435
436        /** Ray / triangle intersection, returns boolean result and distance.
437        @param
438            ray The ray.
439        @param
440            a The triangle's first vertex.
441        @param
442            b The triangle's second vertex.
443        @param
444            c The triangle's third vertex.
445                @param
446                        normal The triangle plane's normal (passed in rather than calculated
447                                on demand since the callermay already have it), doesn't need
448                normalised since we don't care.
449        @param
450            positiveSide Intersect with "positive side" of the triangle
451        @param
452            negativeSide Intersect with "negative side" of the triangle
453        @returns
454            If the ray is intersects the triangle, a pair of <b>true</b> and the
455            distance between intersection point and ray origin returned.
456        @par
457            If the ray isn't intersects the triangle, a pair of <b>false</b> and
458            <b>0</b> returned.
459        */
460        static std::pair<bool, Real> intersects(const Ray& ray, const Vector3& a,
461            const Vector3& b, const Vector3& c, const Vector3& normal,
462            bool positiveSide = true, bool negativeSide = true);
463
464        /** Ray / triangle intersection, returns boolean result and distance.
465        @param
466            ray The ray.
467        @param
468            a The triangle's first vertex.
469        @param
470            b The triangle's second vertex.
471        @param
472            c The triangle's third vertex.
473        @param
474            positiveSide Intersect with "positive side" of the triangle
475        @param
476            negativeSide Intersect with "negative side" of the triangle
477        @returns
478            If the ray is intersects the triangle, a pair of <b>true</b> and the
479            distance between intersection point and ray origin returned.
480        @par
481            If the ray isn't intersects the triangle, a pair of <b>false</b> and
482            <b>0</b> returned.
483        */
484        static std::pair<bool, Real> intersects(const Ray& ray, const Vector3& a,
485            const Vector3& b, const Vector3& c,
486            bool positiveSide = true, bool negativeSide = true);
487
488        /** Sphere / box intersection test. */
489        static bool intersects(const Sphere& sphere, const AxisAlignedBox& box);
490
491        /** Plane / box intersection test. */
492        static bool intersects(const Plane& plane, const AxisAlignedBox& box);
493
494        /** Ray / convex plane list intersection test.
495        @param ray The ray to test with
496        @param plaeList List of planes which form a convex volume
497        @param normalIsOutside Does the normal point outside the volume
498        */
499        static std::pair<bool, Real> intersects(
500            const Ray& ray, const std::vector<Plane>& planeList, 
501            bool normalIsOutside);
502        /** Ray / convex plane list intersection test.
503        @param ray The ray to test with
504        @param plaeList List of planes which form a convex volume
505        @param normalIsOutside Does the normal point outside the volume
506        */
507        static std::pair<bool, Real> intersects(
508            const Ray& ray, const std::list<Plane>& planeList, 
509            bool normalIsOutside);
510
511        /** Sphere / plane intersection test.
512        @remarks NB just do a plane.getDistance(sphere.getCenter()) for more detail!
513        */
514        static bool intersects(const Sphere& sphere, const Plane& plane);
515
516        /** Compare 2 reals, using tolerance for inaccuracies.
517        */
518        static bool RealEqual(Real a, Real b,
519            Real tolerance = std::numeric_limits<Real>::epsilon());
520
521        /** Calculates the tangent space vector for a given set of positions / texture coords. */
522        static Vector3 calculateTangentSpaceVector(
523            const Vector3& position1, const Vector3& position2, const Vector3& position3,
524            Real u1, Real v1, Real u2, Real v2, Real u3, Real v3);
525
526        /** Build a reflection matrix for the passed in plane. */
527        static Matrix4 buildReflectionMatrix(const Plane& p);
528        /** Calculate a face normal, including the w component which is the offset from the origin. */
529        static Vector4 calculateFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
530        /** Calculate a face normal, no w-information. */
531        static Vector3 calculateBasicFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
532        /** Calculate a face normal without normalize, including the w component which is the offset from the origin. */
533        static Vector4 calculateFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3);
534        /** Calculate a face normal without normalize, no w-information. */
535        static Vector3 calculateBasicFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3);
536
537                /** Generates a value based on the gaussian (normal) distribution function
538                        with the given offset and scale parameters.
539                */
540                static Real gaussianDistribution(Real x, Real offset = 0.0f, Real scale = 1.0f);
541
542        static const Real POS_INFINITY;
543        static const Real NEG_INFINITY;
544        static const Real PI;
545        static const Real TWO_PI;
546        static const Real HALF_PI;
547                static const Real fDeg2Rad;
548                static const Real fRad2Deg;
549
550    };
551
552        // these functions must be defined down here, because they rely on the
553        // angle unit conversion functions in class Math:
554
555        inline Real Radian::valueDegrees() const
556        {
557                return Math::RadiansToDegrees ( mRad );
558        }
559
560        inline Real Radian::valueAngleUnits() const
561        {
562                return Math::RadiansToAngleUnits ( mRad );
563        }
564
565        inline Real Degree::valueRadians() const
566        {
567                return Math::DegreesToRadians ( mDeg );
568        }
569
570        inline Real Degree::valueAngleUnits() const
571        {
572                return Math::DegreesToAngleUnits ( mDeg );
573        }
574
575        inline Angle::operator Radian() const
576        {
577                return Radian(Math::AngleUnitsToRadians(mAngle));
578        }
579
580        inline Angle::operator Degree() const
581        {
582                return Degree(Math::AngleUnitsToDegrees(mAngle));
583        }
584
585        inline Radian operator * ( Real a, const Radian& b )
586        {
587                return Radian ( a * b.valueRadians() );
588        }
589
590        inline Radian operator / ( Real a, const Radian& b )
591        {
592                return Radian ( a / b.valueRadians() );
593        }
594
595        inline Degree operator * ( Real a, const Degree& b )
596        {
597                return Degree ( a * b.valueDegrees() );
598        }
599
600        inline Degree operator / ( Real a, const Degree& b )
601        {
602                return Degree ( a / b.valueDegrees() );
603        }
604
605}
606#endif
Note: See TracBrowser for help on using the repository browser.