source: GTP/trunk/App/Demos/Geom/OgreStuff/include/OgreMath.h @ 1812

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