Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/forks/sandbox_light/src/external/ogremath/OgreMath.h @ 8474

Last change on this file since 8474 was 7908, checked in by rgrieder, 14 years ago

Stripped down trunk to form a new light sandbox.

  • Property svn:eol-style set to native
File size: 19.1 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
34#include <cassert>
35#include <cmath>
36#include <vector>
37#include <utility>
38#include <list>
39#include <limits>
40
41namespace Ogre
42{
43    /** Wrapper class which indicates a given angle value is in Radians.
44    @remarks
45        Radian values are interchangeable with Degree values, and conversions
46        will be done automatically between them.
47    */
48        class Radian
49        {
50                Real mRad;
51
52        public:
53                explicit Radian ( Real r=0 ) : mRad(r) {}
54                Radian ( const Degree& d );
55                Radian& operator = ( const Real& f ) { mRad = f; return *this; }
56                Radian& operator = ( const Radian& r ) { mRad = r.mRad; return *this; }
57                Radian& operator = ( const Degree& d );
58
59                Real valueDegrees() const; // see bottom of this file
60                Real valueRadians() const { return mRad; }
61                Real valueAngleUnits() const;
62
63        const Radian& operator + () const { return *this; }
64                Radian operator + ( const Radian& r ) const { return Radian ( mRad + r.mRad ); }
65                Radian operator + ( const Degree& d ) const;
66                Radian& operator += ( const Radian& r ) { mRad += r.mRad; return *this; }
67                Radian& operator += ( const Degree& d );
68                Radian operator - () const { return Radian(-mRad); }
69                Radian operator - ( const Radian& r ) const { return Radian ( mRad - r.mRad ); }
70                Radian operator - ( const Degree& d ) const;
71                Radian& operator -= ( const Radian& r ) { mRad -= r.mRad; return *this; }
72                Radian& operator -= ( const Degree& d );
73                Radian operator * ( Real f ) const { return Radian ( mRad * f ); }
74        Radian operator * ( const Radian& f ) const { return Radian ( mRad * f.mRad ); }
75                Radian& operator *= ( Real f ) { mRad *= f; return *this; }
76                Radian operator / ( Real f ) const { return Radian ( mRad / f ); }
77                Radian& operator /= ( Real f ) { mRad /= f; return *this; }
78
79                bool operator <  ( const Radian& r ) const { return mRad <  r.mRad; }
80                bool operator <= ( const Radian& r ) const { return mRad <= r.mRad; }
81                bool operator == ( const Radian& r ) const { return mRad == r.mRad; }
82                bool operator != ( const Radian& r ) const { return mRad != r.mRad; }
83                bool operator >= ( const Radian& r ) const { return mRad >= r.mRad; }
84                bool operator >  ( const Radian& r ) const { return mRad >  r.mRad; }
85        };
86
87    /** Wrapper class which indicates a given angle value is in Degrees.
88    @remarks
89        Degree values are interchangeable with Radian values, and conversions
90        will be done automatically between them.
91    */
92        class Degree
93        {
94                Real mDeg; // if you get an error here - make sure to define/typedef 'Real' first
95
96        public:
97                explicit Degree ( Real d=0 ) : mDeg(d) {}
98                Degree ( const Radian& r ) : mDeg(r.valueDegrees()) {}
99                Degree& operator = ( const Real& f ) { mDeg = f; return *this; }
100                Degree& operator = ( const Degree& d ) { mDeg = d.mDeg; return *this; }
101                Degree& operator = ( const Radian& r ) { mDeg = r.valueDegrees(); return *this; }
102
103                Real valueDegrees() const { return mDeg; }
104                Real valueRadians() const; // see bottom of this file
105                Real valueAngleUnits() const;
106
107                const Degree& operator + () const { return *this; }
108                Degree operator + ( const Degree& d ) const { return Degree ( mDeg + d.mDeg ); }
109                Degree operator + ( const Radian& r ) const { return Degree ( mDeg + r.valueDegrees() ); }
110                Degree& operator += ( const Degree& d ) { mDeg += d.mDeg; return *this; }
111                Degree& operator += ( const Radian& r ) { mDeg += r.valueDegrees(); return *this; }
112                Degree operator - () const { return Degree(-mDeg); }
113                Degree operator - ( const Degree& d ) const { return Degree ( mDeg - d.mDeg ); }
114                Degree operator - ( const Radian& r ) const { return Degree ( mDeg - r.valueDegrees() ); }
115                Degree& operator -= ( const Degree& d ) { mDeg -= d.mDeg; return *this; }
116                Degree& operator -= ( const Radian& r ) { mDeg -= r.valueDegrees(); return *this; }
117                Degree operator * ( Real f ) const { return Degree ( mDeg * f ); }
118        Degree operator * ( const Degree& f ) const { return Degree ( mDeg * f.mDeg ); }
119                Degree& operator *= ( Real f ) { mDeg *= f; return *this; }
120                Degree operator / ( Real f ) const { return Degree ( mDeg / f ); }
121                Degree& operator /= ( Real f ) { mDeg /= f; return *this; }
122
123                bool operator <  ( const Degree& d ) const { return mDeg <  d.mDeg; }
124                bool operator <= ( const Degree& d ) const { return mDeg <= d.mDeg; }
125                bool operator == ( const Degree& d ) const { return mDeg == d.mDeg; }
126                bool operator != ( const Degree& d ) const { return mDeg != d.mDeg; }
127                bool operator >= ( const Degree& d ) const { return mDeg >= d.mDeg; }
128                bool operator >  ( const Degree& d ) const { return mDeg >  d.mDeg; }
129        };
130
131    /** Wrapper class which identifies a value as the currently default angle
132        type, as defined by Math::setAngleUnit.
133    @remarks
134        Angle values will be automatically converted between radians and degrees,
135        as appropriate.
136    */
137        class Angle
138        {
139                Real mAngle;
140        public:
141                explicit Angle ( Real angle ) : mAngle(angle) {}
142                operator Radian() const;
143                operator Degree() const;
144        };
145
146        // these functions could not be defined within the class definition of class
147        // Radian because they required class Degree to be defined
148        inline Radian::Radian ( const Degree& d ) : mRad(d.valueRadians()) {
149        }
150        inline Radian& Radian::operator = ( const Degree& d ) {
151                mRad = d.valueRadians(); 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        inline Radian Radian::operator - ( const Degree& d ) const {
161                return Radian ( mRad - d.valueRadians() );
162        }
163        inline Radian& Radian::operator -= ( const Degree& d ) {
164                mRad -= d.valueRadians();
165                return *this;
166        }
167
168    /** Class to provide access to common mathematical functions.
169        @remarks
170            Most of the maths functions are aliased versions of the C runtime
171            library functions. They are aliased here to provide future
172            optimisation opportunities, either from faster RTLs or custom
173            math approximations.
174        @note
175            <br>This is based on MgcMath.h from
176            <a href="http://www.geometrictools.com/">Wild Magic</a>.
177    */
178    class _OgreExport Math
179    {
180   public:
181       /** The angular units used by the API. This functionality is now deprecated in favor
182               of discreet angular unit types ( see Degree and Radian above ). The only place
183                   this functionality is actually still used is when parsing files. Search for
184                   usage of the Angle class for those instances
185       */
186       enum AngleUnit
187       {
188           AU_DEGREE,
189           AU_RADIAN
190       };
191
192    protected:
193       // angle units used by the api
194       static AngleUnit msAngleUnit;
195
196        /// Size of the trig tables as determined by constructor.
197        static int mTrigTableSize;
198
199        /// Radian -> index factor value ( mTrigTableSize / 2 * PI )
200        static Real mTrigTableFactor;
201        static Real* mSinTable;
202        static Real* mTanTable;
203
204        /** Private function to build trig tables.
205        */
206        void buildTrigTables();
207
208                static Real SinTable (Real fValue);
209                static Real TanTable (Real fValue);
210    public:
211        /** Default constructor.
212            @param
213                trigTableSize Optional parameter to set the size of the
214                tables used to implement Sin, Cos, Tan
215        */
216        Math(unsigned int trigTableSize = 4096);
217
218        /** Default destructor.
219        */
220        ~Math();
221
222                static inline int IAbs (int iValue) { return ( iValue >= 0 ? iValue : -iValue ); }
223                static inline int ICeil (float fValue) { return int(ceil(fValue)); }
224                static inline int IFloor (float fValue) { return int(floor(fValue)); }
225        static int ISign (int iValue);
226
227                static inline Real Abs (Real fValue) { return Real(fabs(fValue)); }
228                static inline Degree Abs (const Degree& dValue) { return Degree(fabs(dValue.valueDegrees())); }
229                static inline Radian Abs (const Radian& rValue) { return Radian(fabs(rValue.valueRadians())); }
230                static Radian ACos (Real fValue);
231                static Radian ASin (Real fValue);
232                static inline Radian ATan (Real fValue) { return Radian(atan(fValue)); }
233                static inline Radian ATan2 (Real fY, Real fX) { return Radian(atan2(fY,fX)); }
234                static inline Real Ceil (Real fValue) { return Real(ceil(fValue)); }
235
236        /** Cosine function.
237            @param
238                fValue Angle in radians
239            @param
240                useTables If true, uses lookup tables rather than
241                calculation - faster but less accurate.
242        */
243        static inline Real Cos (const Radian& fValue, bool useTables = false) {
244                        return (!useTables) ? Real(cos(fValue.valueRadians())) : SinTable(fValue.valueRadians() + HALF_PI);
245                }
246        /** Cosine function.
247            @param
248                fValue Angle in radians
249            @param
250                useTables If true, uses lookup tables rather than
251                calculation - faster but less accurate.
252        */
253        static inline Real Cos (Real fValue, bool useTables = false) {
254                        return (!useTables) ? Real(cos(fValue)) : SinTable(fValue + HALF_PI);
255                }
256
257                static inline Real Exp (Real fValue) { return Real(exp(fValue)); }
258
259                static inline Real Floor (Real fValue) { return Real(floor(fValue)); }
260
261                static inline Real Log (Real fValue) { return Real(log(fValue)); }
262
263                static inline Real Pow (Real fBase, Real fExponent) { return Real(pow(fBase,fExponent)); }
264
265        static Real Sign (Real fValue);
266                static inline Radian Sign ( const Radian& rValue )
267                {
268                        return Radian(Sign(rValue.valueRadians()));
269                }
270                static inline Degree Sign ( const Degree& dValue )
271                {
272                        return Degree(Sign(dValue.valueDegrees()));
273                }
274
275        /** Sine function.
276            @param
277                fValue Angle in radians
278            @param
279                useTables If true, uses lookup tables rather than
280                calculation - faster but less accurate.
281        */
282        static inline Real Sin (const Radian& fValue, bool useTables = false) {
283                        return (!useTables) ? Real(sin(fValue.valueRadians())) : SinTable(fValue.valueRadians());
284                }
285        /** Sine function.
286            @param
287                fValue Angle in radians
288            @param
289                useTables If true, uses lookup tables rather than
290                calculation - faster but less accurate.
291        */
292        static inline Real Sin (Real fValue, bool useTables = false) {
293                        return (!useTables) ? Real(sin(fValue)) : SinTable(fValue);
294                }
295
296                static inline Real Sqr (Real fValue) { return fValue*fValue; }
297
298                static inline Real Sqrt (Real fValue) { return Real(sqrt(fValue)); }
299
300        static inline Radian Sqrt (const Radian& fValue) { return Radian(sqrt(fValue.valueRadians())); }
301
302        static inline Degree Sqrt (const Degree& fValue) { return Degree(sqrt(fValue.valueDegrees())); }
303
304        /** Inverse square root i.e. 1 / Sqrt(x), good for vector
305            normalisation.
306        */
307                static Real InvSqrt(Real fValue);
308
309        static Real UnitRandom ();  // in [0,1]
310
311        static Real RangeRandom (Real fLow, Real fHigh);  // in [fLow,fHigh]
312
313        static Real SymmetricRandom ();  // in [-1,1]
314
315        /** Tangent function.
316            @param
317                fValue Angle in radians
318            @param
319                useTables If true, uses lookup tables rather than
320                calculation - faster but less accurate.
321        */
322                static inline Real Tan (const Radian& fValue, bool useTables = false) {
323                        return (!useTables) ? Real(tan(fValue.valueRadians())) : TanTable(fValue.valueRadians());
324                }
325        /** Tangent function.
326            @param
327                fValue Angle in radians
328            @param
329                useTables If true, uses lookup tables rather than
330                calculation - faster but less accurate.
331        */
332                static inline Real Tan (Real fValue, bool useTables = false) {
333                        return (!useTables) ? Real(tan(fValue)) : TanTable(fValue);
334                }
335
336                static inline Real DegreesToRadians(Real degrees) { return degrees * fDeg2Rad; }
337        static inline Real RadiansToDegrees(Real radians) { return radians * fRad2Deg; }
338
339       /** These functions used to set the assumed angle units (radians or degrees)
340            expected when using the Angle type.
341       @par
342            You can set this directly after creating a new Root, and also before/after resource creation,
343            depending on whether you want the change to affect resource files.
344       */
345       static void setAngleUnit(AngleUnit unit);
346       /** Get the unit being used for angles. */
347       static AngleUnit getAngleUnit(void);
348
349       /** Convert from the current AngleUnit to radians. */
350       static Real AngleUnitsToRadians(Real units);
351       /** Convert from radians to the current AngleUnit . */
352       static Real RadiansToAngleUnits(Real radians);
353       /** Convert from the current AngleUnit to degrees. */
354       static Real AngleUnitsToDegrees(Real units);
355       /** Convert from degrees to the current AngleUnit. */
356       static Real DegreesToAngleUnits(Real degrees);
357
358       /** Checks whether a given point is inside a triangle, in a
359            2-dimensional (Cartesian) space.
360            @remarks
361                The vertices of the triangle must be given in either
362                trigonometrical (anticlockwise) or inverse trigonometrical
363                (clockwise) order.
364            @param
365                p The point.
366            @param
367                a The triangle's first vertex.
368            @param
369                b The triangle's second vertex.
370            @param
371                c The triangle's third vertex.
372            @returns
373                If the point resides in the triangle, <b>true</b> is
374                returned.
375            @par
376                If the point is outside the triangle, <b>false</b> is
377                returned.
378        */
379        static bool pointInTri2D(const Vector2& p, const Vector2& a, 
380                        const Vector2& b, const Vector2& c);
381
382       /** Checks whether a given 3D point is inside a triangle.
383       @remarks
384            The vertices of the triangle must be given in either
385            trigonometrical (anticlockwise) or inverse trigonometrical
386            (clockwise) order, and the point must be guaranteed to be in the
387                        same plane as the triangle
388        @param
389            p The point.
390        @param
391            a The triangle's first vertex.
392        @param
393            b The triangle's second vertex.
394        @param
395            c The triangle's third vertex.
396                @param
397                        normal The triangle plane's normal (passed in rather than calculated
398                                on demand since the caller may already have it)
399        @returns
400            If the point resides in the triangle, <b>true</b> is
401            returned.
402        @par
403            If the point is outside the triangle, <b>false</b> is
404            returned.
405        */
406        static bool pointInTri3D(const Vector3& p, const Vector3& a, 
407                        const Vector3& b, const Vector3& c, const Vector3& normal);
408
409        /** Compare 2 reals, using tolerance for inaccuracies.
410        */
411        static bool RealEqual(Real a, Real b,
412            Real tolerance = std::numeric_limits<Real>::epsilon());
413
414        /** Calculates the tangent space vector for a given set of positions / texture coords. */
415        static Vector3 calculateTangentSpaceVector(
416            const Vector3& position1, const Vector3& position2, const Vector3& position3,
417            Real u1, Real v1, Real u2, Real v2, Real u3, Real v3);
418
419        /** Calculate a face normal, including the w component which is the offset from the origin. */
420        static Vector4 calculateFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
421        /** Calculate a face normal, no w-information. */
422        static Vector3 calculateBasicFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
423        /** Calculate a face normal without normalize, including the w component which is the offset from the origin. */
424        static Vector4 calculateFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3);
425        /** Calculate a face normal without normalize, no w-information. */
426        static Vector3 calculateBasicFaceNormalWithoutNormalize(const Vector3& v1, const Vector3& v2, const Vector3& v3);
427
428                /** Generates a value based on the Gaussian (normal) distribution function
429                        with the given offset and scale parameters.
430                */
431                static Real gaussianDistribution(Real x, Real offset = 0.0f, Real scale = 1.0f);
432
433                /** Clamp a value within an inclusive range. */
434                template <typename T>
435                static T Clamp(T val, T minval, T maxval)
436                {
437                        assert (minval < maxval && "Invalid clamp range");
438                        return std::max(std::min(val, maxval), minval);
439                }
440
441                static Matrix4 makeViewMatrix(const Vector3& position, const Quaternion& orientation, 
442                        const Matrix4* reflectMatrix = 0);
443
444
445
446        static const Real POS_INFINITY;
447        static const Real NEG_INFINITY;
448        static const Real PI;
449        static const Real TWO_PI;
450        static const Real HALF_PI;
451                static const Real fDeg2Rad;
452                static const Real fRad2Deg;
453
454    };
455
456        // these functions must be defined down here, because they rely on the
457        // angle unit conversion functions in class Math:
458
459        inline Real Radian::valueDegrees() const
460        {
461                return Math::RadiansToDegrees ( mRad );
462        }
463
464        inline Real Radian::valueAngleUnits() const
465        {
466                return Math::RadiansToAngleUnits ( mRad );
467        }
468
469        inline Real Degree::valueRadians() const
470        {
471                return Math::DegreesToRadians ( mDeg );
472        }
473
474        inline Real Degree::valueAngleUnits() const
475        {
476                return Math::DegreesToAngleUnits ( mDeg );
477        }
478
479        inline Angle::operator Radian() const
480        {
481                return Radian(Math::AngleUnitsToRadians(mAngle));
482        }
483
484        inline Angle::operator Degree() const
485        {
486                return Degree(Math::AngleUnitsToDegrees(mAngle));
487        }
488
489        inline Radian operator * ( Real a, const Radian& b )
490        {
491                return Radian ( a * b.valueRadians() );
492        }
493
494        inline Radian operator / ( Real a, const Radian& b )
495        {
496                return Radian ( a / b.valueRadians() );
497        }
498
499        inline Degree operator * ( Real a, const Degree& b )
500        {
501                return Degree ( a * b.valueDegrees() );
502        }
503
504        inline Degree operator / ( Real a, const Degree& b )
505        {
506                return Degree ( a / b.valueDegrees() );
507        }
508
509}
510#endif
Note: See TracBrowser for help on using the repository browser.