Main Page Modules Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# deMath.hpp

Go to the documentation of this file.

    00001 ///////////////////////////////////////////////////////////////////////////////
    00002 /// @file deMath.hpp
    00003 ///
    00004 /// @brief Math lib header
    00005 ///
    00006 /// @author Assassin
    00007 ///
    00008 /// This file is the intellectual property of Novus Delta, LLC.. Usage of the
    00009 /// contents of this file is subject to the Destiny3D Member License which
    00010 /// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
    00011 ///
    00012 /// This file is distributed "AS IS" without warranty of any kind.  Novus
    00013 /// Delta, LLC. does not guarantee the fitness of the contents of this file
    00014 /// for any particular purpose.
    00015 ///
    00016 /// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
    00017 ///
    00018 /// <hr>
    00019 ///                                 Change History
    00020 /// <hr>
    00021 ///
    00022 /// @date Jan 2002
    00023 /// @author Assassin
    00024 /// @remarks Creation
    00025 ///
    00026 /// @date Jul 2002
    00027 /// @author Hootie
    00028 /// @remarks Convert to static lib
    00029 ///
    00030 ///////////////////////////////////////////////////////////////////////////////
    00031
    00032 #ifndef DEMATH_HPP
    00033 #define DEMATH_HPP
    00034
    00035 #if defined(USING_DESTINY3D) || defined(USING_DESTINY3D_DLL)
    00036 #ifdef _DEBUG
    00037 // no static link option
    00038 #pragma comment(lib, "deMathd")
    00039 #else
    00040 #pragma comment(lib, "deMath")
    00041 #endif //_DEBUG
    00042 #endif //USING_DESTINY3D
    00043
    00044
    00045 #include "deGlobalTypes.hpp"
    00046 #include "deStack.hpp"
    00047 #include <cmath>
    00048
    00049
    00050
    00051 struct deFractionInfo
    00052 {
    00053 protected:
    00054     int m_Num, m_Den;
    00055     friend class deFraction;
    00056 };
    00057 class deFraction : public deFractionInfo
    00058 {
    00059 public:
    00060     inline deFraction()
    00061         { m_Num = 0; m_Den = 1; }
    00062     inline deFraction(int Num)
    00063         { m_Num = Num; m_Den = 1; }
    00064     inline deFraction(int Num, int Den)
    00065         { m_Num = Num; m_Den = Den; }
    00066     inline deFraction(const deFraction & ref)
    00067         { m_Num = ref.m_Num; m_Den = ref.m_Den; }
    00068     inline deFraction(const deFractionInfo & ref)
    00069         { m_Num = ref.m_Num; m_Den = ref.m_Den; }
    00070     inline ~deFraction() {}
    00071
    00072     inline operator double() const { return ((double)m_Num)/m_Den; }
    00073     inline operator float() const { return ((float)m_Num)/m_Den; }
    00074     inline int Num() const { return m_Num; }
    00075     inline int Den() const { return m_Den; }
    00076
    00077     inline deFraction operator+(const deFraction & rhs) const
    00078         { deFraction ret(*this); ret += rhs; return ret; }
    00079     inline deFraction operator-(const deFraction & rhs) const
    00080         { deFraction ret(*this); ret -= rhs; return ret; }
    00081     inline deFraction operator*(const deFraction & rhs) const
    00082         { deFraction ret(*this); ret *= rhs; return ret; }
    00083     inline deFraction operator/(const deFraction & rhs) const
    00084         { deFraction ret(*this); ret /= rhs; return ret; }
    00085
    00086     deFraction operator+(int rhs) const;
    00087     deFraction operator-(int rhs) const;
    00088     deFraction operator*(int rhs) const;
    00089     deFraction operator/(int rhs) const;
    00090
    00091     deFraction& operator+=(const deFraction & rhs);
    00092     deFraction& operator-=(const deFraction & rhs);
    00093     inline deFraction& operator*=(const deFraction & rhs)
    00094         { m_Num *= rhs.m_Num; m_Den *= rhs.m_Den; return *this; }
    00095     inline deFraction& operator/=(const deFraction & rhs)
    00096         { m_Num *= rhs.m_Den; m_Den *= rhs.m_Num; return *this; }
    00097
    00098     inline const deFraction& operator=(const deFraction & rhs)
    00099         { m_Num = rhs.m_Num; m_Den = rhs.m_Den; return *this; }
    00100     inline const deFraction& operator=(int rhs)
    00101         { m_Num = rhs; m_Den = 1; return *this; }
    00102     bool operator==(const deFraction & rhs);
    00103     bool operator==(int rhs);
    00104 };
    00105
    00106 /// storage class for a Destiny3D transform
    00107 struct deTransformInfo
    00108 {
    00109 public:
    00110     deVec3d Translation;    ///< translation, in coordinate space of parent system
    00111     deVec3d R,U,I;          ///< basis vectors, hopefully orthogonal for a rigid-body transform
    00112     deBoolean m_Identity;   ///< quick bypass value used if the basis vectors form a 3x3 identity matrix. Do not alter manually, use deTransform::TestIdentity
    00113 };
    00114 /// rigid-body transformation. supports a translation and rotation, with possible scaling.
    00115 class deTransform : public deTransformInfo
    00116 {
    00117 public:
    00118     inline ~deTransform() {}
    00119     /// default constructor initializes to identity matrix.
    00120     inline deTransform(void)
    00121         { m_Identity = deTRUE; R = U = I = Translation = deZeroVec; R.X = U.Y = I.Z = 1.0; }
    00122     /// copy constructor.
    00123     inline deTransform(const deTransformInfo & ref)
    00124         { m_Identity = ref.m_Identity; R = ref.R; U = ref.U; I = ref.I; Translation = ref.Translation; }
    00125     /// translation constructor, sets rotation to identity.
    00126     deTransform(const deVec3d & Trans)
    00127         { m_Identity = deTRUE; R = U = I = deZeroVec; R.X = U.Y = I.Z = 1.0; Translation = Trans; }
    00128     /// rotation constructor, sets translation to identity.
    00129     deTransform(const deVec3d & Right, const deVec3d & Up, const deVec3d & In);
    00130     /// all data constructor.
    00131     deTransform(const deVec3d & Right, const deVec3d & Up, const deVec3d & In, const deVec3d & Trans);
    00132
    00133     /// reset the transform to 0 translation and identity rotation
    00134     void inline Reset()
    00135         { m_Identity = deTRUE; R = U = I = Translation = deZeroVec; R.X = U.Y = I.Z = 1.0; }
    00136     /// convert from a 4x4 matrix, such as an opengl or direct3d one. the last column will be ignored.
    00137     void FromFloat44(const float Mat[4][4], deBoolean d3d);
    00138     /// convert from a 4x4 matrix, such as deMatrix44.
    00139     void FromDouble44(const double Mat[4][4], deBoolean d3d);
    00140     /// convert to a 4x4 matrix, such as an opengl or direct3d one. the last column will be created with (0,0,0,1).
    00141     void ToFloat44(float Mat[4][4], deBoolean d3d) const;
    00142     /// forces any values that are close to 0 to become exactly 0
    00143     void SqueezeVectors();
    00144     /// set the "right" (aka X or i) basis vector
    00145     void SetRight(const deVec3d & Right);
    00146     /// set the "up" (aka Y or j) basis vector
    00147     void SetUp(const deVec3d & Up);
    00148     /// set the "in" (aka Z or k) basis vector
    00149     void SetIn(const deVec3d & In);
    00150     /// set the translation of the transform. translation is in the space of the parent's coordinate system.
    00151     void inline SetTranslation(const deVec3d & Trans) { Translation = Trans; }
    00152     /// set all the basis vectors at once
    00153     void SetRightUpIn(const deVec3d & Right, const deVec3d & Up, const deVec3d & In);
    00154     /// Reset the transform and then build a rotation around the X axis. Any existing rotation or translation is lost.
    00155     void SetXRot(deDouble r);
    00156     /// Reset the transform and then build a rotation around the Y axis. Any existing rotation or translation is lost.
    00157     void SetYRot(deDouble r);
    00158     /// Reset the transform and then build a rotation around the Z axis. Any existing rotation or translation is lost.
    00159     void SetZRot(deDouble r);
    00160     /// Applies a rotation around the X axis to the existing data in the transform.
    00161     void RotateX(deDouble Rads);
    00162     /// Applies a rotation around the Y axis to the existing data in the transform.
    00163     void RotateY(deDouble Rads);
    00164     /// Applies a rotation around the Z axis to the existing data in the transform.
    00165     void RotateZ(deDouble Rads);
    00166     /// Builds a Euler angles rotation, losing any previously stored rotation or translation.
    00167     void FreeRot(const deVec3d &Rads);
    00168     /// Builds a Euler angles rotation, losing any previously stored rotation or translation.
    00169     void FreeRot(deDouble x, deDouble y, deDouble z);
    00170     /// Builds a Euler angles rotation, losing any previously stored rotation, but not translation.
    00171     void FreeRotInPlace(const deVec3d &Rads);
    00172     /// Builds a Euler angles rotation, losing any previously stored rotation, but not translation.
    00173     void FreeRotInPlace(deDouble x, deDouble y, deDouble z);
    00174     /// Scale the basis vectors by a uniform value.
    00175     void ApplyScaling(deDouble UniformScaling);
    00176     /// Scale the basis vectors by a distinct axis values.
    00177     void ApplyScaling(const deVec3d & Multiples);
    00178     /// Scale the basis vectors by a distinct axis values.
    00179     void ApplyScaling(deDouble x, deDouble y, deDouble z);
    00180     /// Obtain the lengths of the basis vectors (axes) of the transform
    00181     void GetBasisScales(deDouble& x, deDouble& y, deDouble &z);
    00182     inline void GetBasisScales(deVec3d& v) { GetBasisScales(v.x, v.y, v.z); }
    00183
    00184     /// Tests whether the basis vectors form an identity matrix, setting the internal m_Identity member appropriately.
    00185     deBoolean TestIdentity(deDouble Epsilon = 0.00001);
    00186     /// Tests whether the basis vectors form an orthogonal basis (all perpendicular to one another).
    00187     deBoolean IsOrthogonal() const;
    00188     /// Tests the basis vectors for an orthonormality (all perpendicular to one another and magnitude=1.0).
    00189     deBoolean IsOrthoNormal() const;
    00190     /// Creates an orthonormal basis from the existing basis vectors.
    00191     deBoolean OrthoNormalize();
    00192
    00193     /// retrieve the "right" basis vector
    00194     void GetRight(deVec3d & r) const;
    00195     /// retrieve the "up" basis vector
    00196     void GetUp(deVec3d & u) const;
    00197     /// retrieve the "in" basis vector
    00198     void GetIn(deVec3d & i) const;
    00199     /// retrieve the "right" basis vector
    00200     deVec3d GetRight() const;
    00201     /// retrieve the "up" basis vector
    00202     deVec3d GetUp() const;
    00203     /// retrieve the "in" basis vector
    00204     deVec3d GetIn() const;
    00205     /// retrieve all the basis vectors at once
    00206     void GetRightUpIn(deVec3d & Right, deVec3d & Up, deVec3d & In) const;
    00207     /// Get a transposition of the rotation matrix, combined with a processed translation.
    00208     /// On an orthonormal transform, this is the same operation as computing the inverse, but much quicker to compute.
    00209     void GetTranspose(deTransformInfo & target);
    00210     /// alternate form of GetTranspose
    00211     deTransformInfo GetTranspose();
    00212     /// retrieve the translation for this transform
    00213     deVec3d inline GetTranslation() const
    00214         { return Translation; }
    00215
    00216     /// Perform a transformation of a 3d vector using this transform.
    00217     void Transform(deVec3d InVec, deVec3d & OutVec) const;
    00218     /// Perform a transformation of an array of 3d vectors using this transform.
    00219     void TransformArray(const deVec3d InVec[], deVec3d OutVec[], int num) const;
    00220     void Transform(deVertex InVec, deVertex & OutVec) const;
    00221     void TransformArray(const deVertex InVec[], deVertex OutVec[], int num) const;
    00222     /// transform a 3d vector by the transposition of this transform, which is the same as the inverse for orthonormal transforms.
    00223     void TransposeTransform(deVec3d InVec, deVec3d & OutVec) const;
    00224     /// concatenate this transform with another transform, storing the result in "ret".
    00225     /// ret = this * rhs
    00226     void Multiply(const deTransformInfo & rhs, deTransformInfo & ret);
    00227     /// return = this * rhs
    00228     deTransform Multiply(const deTransformInfo & rhs);
    00229 };
    00230
    00231 struct deVec4d
    00232 {
    00233     deDouble x,y,z,w;
    00234 };
    00235 class deMatrix44
    00236 {
    00237     // uses direct3d matrix layout
    00238 public:
    00239     union {
    00240         struct {
    00241             deDouble        _00, _01, _02, _03;
    00242             deDouble        _10, _11, _12, _13;
    00243             deDouble        _20, _21, _22, _23;
    00244             deDouble        _30, _31, _32, _33;
    00245         };
    00246         deDouble m[4][4];
    00247     };
    00248     inline ~deMatrix44() {}
    00249     inline deMatrix44() {}
    00250     inline deMatrix44(const deTransformInfo & ref)
    00251     {
    00252         _00 = ref.R.x; _01 = ref.R.y; _02 = ref.R.z; _03 = 0;
    00253         _10 = ref.U.x; _11 = ref.U.y; _12 = ref.U.z; _13 = 0;
    00254         _20 = ref.I.x; _21 = ref.I.y; _22 = ref.I.z; _23 = 0;
    00255         _30 = ref.Translation.x; _31 = ref.Translation.y; _32 = ref.Translation.z;
    00256         _33 = 1;
    00257     }
    00258     deMatrix44(const deVec3d & Right, const deVec3d & Up, const deVec3d & In, const deVec3d & Trans = deZeroVec)
    00259     {
    00260         _00 = Right.x; _01 = Right.y; _02 = Right.z; _03 = 0;
    00261         _10 = Up.x;    _11 = Up.y;    _12 = Up.z;    _13 = 0;
    00262         _20 = In.x;    _21 = In.y;    _22 = In.z;    _23 = 0;
    00263         _30 = Trans.x; _31 = Trans.y; _32 = Trans.z; _33 = 1;
    00264     }
    00265     deMatrix44(const deFloat f[4][4], deBoolean d3d);
    00266     deMatrix44(const deDouble d[4][4], deBoolean d3d);
    00267     void operator=(const deDouble d[4][4]);
    00268
    00269     void Identity()
    00270     {
    00271         _00 = 1; _01 = 0; _02 = 0; _03 = 0;
    00272         _10 = 0; _11 = 1; _12 = 0; _13 = 0;
    00273         _20 = 0; _21 = 0; _22 = 1; _23 = 0;
    00274         _30 = 0; _31 = 0; _32 = 0; _33 = 1;
    00275     }
    00276     void Translation(const deVec3d & T)
    00277     {
    00278         _00 = 1;   _01 = 0;   _02 = 0;   _03 = 0;
    00279         _10 = 0;   _11 = 1;   _12 = 0;   _13 = 0;
    00280         _20 = 0;   _21 = 0;   _22 = 1;   _23 = 0;
    00281         _30 = T.x; _31 = T.y; _32 = T.z; _33 = 1;
    00282     }
    00283     void Scaling(deDouble x, deDouble y, deDouble z)
    00284     {
    00285         _00 = x; _01 = 0; _02 = 0; _03 = 0;
    00286         _10 = 0; _11 = y; _12 = 0; _13 = 0;
    00287         _20 = 0; _21 = 0; _22 = z; _23 = 0;
    00288         _30 = 0; _31 = 0; _32 = 0; _33 = 1;
    00289     }
    00290     void Multiply(const deMatrix44 & right, deMatrix44 & out) const;
    00291     void Transform(const deVec3d & in, deVec3d & out) const;
    00292     void Transform(const deVec3d & in, deVec4d & out) const;
    00293     void Transform(const deVertex & in, deVec4d & out) const;
    00294 };
    00295
    00296
    00297 /// a class for maintaining a hierarchy of transformations.
    00298 /// concatenations are performed with first-in on the left.
    00299 class deTransformStack
    00300 {
    00301 private:
    00302     deTStack <deTransform> m_Stack;
    00303
    00304 public:
    00305     inline deTransformStack() : m_Stack(deTStack<deTransform>::LIFO_STACK) {}
    00306     inline ~deTransformStack() {}
    00307
    00308     /// compute the concatenation of a transform with the previous top of the stack, and store the concatenation as the new top.
    00309     deBoolean Push(const deTransformInfo & transform, deTransformInfo * concat = NULL);
    00310     /// remove the last-inserted transform from the stack
    00311     deBoolean Pop(deTransformInfo & transform);
    00312     /// remove the last-inserted transform from the stack
    00313     deBoolean Pop();
    00314     /// view the concatenation of all the currently-stored transforms
    00315     deBoolean Peek(deTransformInfo & transform);
    00316
    00317     /// remove all the transforms from this structure
    00318     inline deBoolean Clear() { m_Stack.Clear();}
    00319 };
    00320
    00321
    00322 /// a quaternion calculation class
    00323 class deQuaternion {
    00324 public:
    00325     union
    00326     {   struct
    00327         {
    00328             deDouble x, y, z;
    00329         };
    00330         deVec3d vector;
    00331     };
    00332     deDouble w;
    00333
    00334     // A quaternion's length must be closer than this tolerance to 1.0 to be
    00335     // considered a unit quaternion
    00336     static const deDouble UNIT_TOLERANCE;
    00337
    00338     // Epsilon used in spherical linear interpolation
    00339     static const deDouble SLERP_EPSILON;
    00340
    00341     // Operators
    00342     void operator +=(const deQuaternion&);
    00343     void operator -=(const deQuaternion&);
    00344     void operator *=(const deQuaternion&);
    00345     deQuaternion operator +(const deQuaternion&) const;
    00346     deQuaternion operator -(const deQuaternion&) const;
    00347     deQuaternion operator *(const deQuaternion&) const;
    00348     bool operator ==(const deQuaternion&) const;
    00349     bool operator !=(const deQuaternion&) const;
    00350
    00351     // Conversion operators
    00352     operator deVec3d&(){ return vector; }
    00353     operator const deVec3d&() const { return vector; }
    00354
    00355     // Analytical functions
    00356     deBoolean IsValid() const;
    00357     deBoolean IsUnit() const;
    00358
    00359     // Math operations
    00360     // These are slightly faster than the +, -, * operators since they don't use the stack to
    00361     // return the result.
    00362     // NOTE: These functions are still slower than the +=, -= or *= operators.
    00363     void Multiply(const deQuaternion &q, deQuaternion &result) const;
    00364     void Add(const deQuaternion &q, deQuaternion &result) const;
    00365     void Subtract(const deQuaternion &q, deQuaternion &result) const;
    00366
    00367     void Set(deDouble xAxis, deDouble yAxis, deDouble zAxis, deDouble wAxis)
    00368         { x = xAxis;    y = yAxis;  z = zAxis;  w = wAxis; }
    00369
    00370     // Length of quaternion (also known as 'magnitude')
    00371     deDouble Length() const;
    00372
    00373     // Normalize quaternion
    00374     void Normalize();
    00375
    00376     // Interpolate between two quaternions
    00377     // If balance is 0, the result is 'this', if balance is 1.0 the result is 'q'
    00378     // NOTE: The balance must >= 0 and <= 1
    00379     void Interpolate(const deQuaternion &q, deDouble balance, deQuaternion &result);
    00380
    00381     void RotateX(deDouble radians){ x += radians; }
    00382     void RotateY(deDouble radians){ y += radians; }
    00383     void RotateZ(deDouble radians){ z += radians; }
    00384
    00385     // Conversion
    00386     deBoolean FromMatrix(const deTransformInfo &matrix);
    00387
    00388     // NOTE: The translation of the matrix remains unchanged.
    00389     void ToMatrix(deTransformInfo &matrix) const;
    00390
    00391     deQuaternion(){}
    00392     deQuaternion(deDouble xAxis, deDouble yAxis, deDouble zAxis, deDouble wAxis){ x = xAxis;    y = yAxis;  z = zAxis;  w = wAxis; }
    00393     deQuaternion(deVec3d &axisdeVector, deDouble www){ vector = axisdeVector; w = www;}
    00394
    00395 };
    00396
    00397
    00398
    00399 template <typename T>
    00400 static inline T SQUARE(T x) {return (x)*(x);}
    00401 /// squared length of a deVec3d
    00402 static inline deDouble Vec3d_LengthSq(const deVec3d& v)
    00403     {return SQUARE(v.X) + SQUARE(v.Y) + SQUARE(v.Z);}
    00404 /// length of a deVec3d
    00405 static inline deDouble Vec3d_Length(const deVec3d& v)
    00406     {return sqrt(Vec3d_LengthSq(v));}
    00407 /// multiply each component of a deVec3d by the corresponding component of another
    00408 static inline void Vec3d_ScaleByVec(deVec3d & v1, const deVec3d & v2)
    00409     { v1.X *= v2.X; v1.Y *= v2.Y; v1.Z *= v2.Z; }
    00410 /// compare equality of 2 floating-point values, within some Epsilon value
    00411 static inline deBoolean Compare_Epsilon(const deDouble d1, const deDouble d2, deDouble epsilon = 0.00001)
    00412     { return (fabs(d1 - d2) <= epsilon); }
    00413 /// compare equality of two deVec3d, within some Epsilon value
    00414 static inline deBoolean Vec3d_Compare(const deVec3d & v1, const deVec3d &v2, deDouble epsilon = 0.00001)
    00415     { return ((fabs(v1.x - v2.x) <= epsilon) && (fabs(v1.y - v2.y) <= epsilon) && (fabs(v1.z - v2.z) <= epsilon)); }
    00416 /// compare exact opposite equality of two deVec3d, within some Epsilon value
    00417 static inline deBoolean Vec3d_CompareOpposite(const deVec3d & v1, const deVec3d &v2, deDouble epsilon = 0.00001)
    00418     { return ((fabs(v1.x + v2.x) <= epsilon) && (fabs(v1.y + v2.y) <= epsilon) && (fabs(v1.z + v2.z) <= epsilon)); }
    00419 /// compute the dot-product of two deVec3d (deDouble components)
    00420 static inline deDouble Vec3d_Dot(const deVec3d& v1, const deVec3d& v2)
    00421     { return (v1).X*(v2).X+(v1).Y*(v2).Y+(v1).Z*(v2).Z; }
    00422 /// compute the dot-product of two deVertex (deFloat components)
    00423 static inline deFloat Vec3d_Dot(const deVertex& v1, const deVertex& v2)
    00424     { return (v1).X*(v2).X+(v1).Y*(v2).Y+(v1).Z*(v2).Z; }
    00425 /// compute the square of the distance between two deVec3d
    00426 static inline deDouble Vec3d_DistSq(const deVec3d & v1, const deVec3d & v2)
    00427     {
    00428         deDouble Temp1, Temp2;
    00429         Temp1=(v1).x-(v2).x; Temp2 = SQUARE(Temp1);
    00430         Temp1=(v1).y-(v2).y; Temp2 += SQUARE(Temp1);
    00431         Temp1=(v1).z-(v2).z; Temp2 += SQUARE(Temp1);
    00432         return Temp2;
    00433     }
    00434 /// compute the distance between two deVec3d
    00435 static inline deDouble Vec3d_Dist(const deVec3d & v1, const deVec3d & v2)
    00436     { return (deDouble)sqrt(Vec3d_DistSq(v1,v2));}
    00437 /// compute the square of the distance between two deVertex
    00438 static inline deFloat Vec3d_DistSq(const deVertex & v1, const deVertex & v2)
    00439     {
    00440         deFloat Temp1, Temp2;
    00441         Temp1=(v1).x-(v2).x; Temp2 = SQUARE(Temp1);
    00442         Temp1=(v1).y-(v2).y; Temp2 += SQUARE(Temp1);
    00443         Temp1=(v1).z-(v2).z; Temp2 += SQUARE(Temp1);
    00444         return Temp2;
    00445     }
    00446 /// compute the distance between two deVertex
    00447 static inline deFloat Vec3d_Dist(const deVertex & v1, const deVertex & v2)
    00448     { return (deFloat)sqrtf(Vec3d_DistSq(v1, v2));}
    00449 /// compute the inverse of a deVec3d (overloaded operator-)
    00450 static inline deVec3d operator-(const deVec3d &v)
    00451     {deVec3d ret={-v.x,-v.y,-v.z};return ret;}
    00452 /// compute the component difference between two deVec3d (overloaded operator-)
    00453 static inline deVec3d operator-(const deVec3d &v1, const deVec3d &v2)
    00454     {deVec3d ret={v1.x-v2.x,v1.y-v2.y,v1.z-v2.z};return ret;}
    00455 /// compute the component sum of two deVec3d (overloaded operator+)
    00456 static inline deVec3d operator+(const deVec3d &v1, const deVec3d &v2)
    00457     {deVec3d ret={v1.x+v2.x,v1.y+v2.y,v1.z+v2.z};return ret;}
    00458 /// compute the scalar product of a deVec3d and a floating-point value (overloaded operator*)
    00459 static inline deVec3d operator*(const deVec3d &v1, deDouble d)
    00460     {deVec3d ret={v1.x*d,v1.y*d,v1.z*d};return ret;}
    00461 /// subtract a deVec3d from another one (overloaded operator-=)
    00462 static inline void operator-=(deVec3d &v1, const deVec3d &v2)
    00463     {v1.x -= v2.x; v1.y -= v2.y; v1.z -= v2.z; }
    00464 /// add a deVec3d to another one (overloaded operator+=)
    00465 static inline void operator+=(deVec3d &v1, const deVec3d &v2)
    00466     {v1.x += v2.x; v1.y += v2.y; v1.z += v2.z; }
    00467 /// multiply a deVec3d by a scalar value (overloaded operator*=)
    00468 static inline void operator*=(deVec3d &v1, deDouble d)
    00469     {v1.x *= d; v1.y *= d; v1.z *= d; }
    00470 /// divide a deVec3d by a scalar value (overloaded operator/=)
    00471 static inline void operator/=(deVec3d &v1, deDouble d)
    00472     {deDouble d2 = 1/d; v1.x *= d2; v1.y *= d2; v1.z *= d2; }
    00473 #ifdef _DEBUG
    00474 // this should work even on packing of 8 due to a double's size
    00475 static inline deDouble & Vec3d_GetElement(const deVec3d& v, long i)
    00476     {if (i < 0 || i >= 3) DEBUGRETURN(*((deDouble*)&v),"Vec3d_GetElement: Invalid index"); return *( ((deDouble*)&v) + i ); }
    00477 #else
    00478 /// obtain a reference to an indexed value inside a 3d vector (valid index values: {0,1,2}, map to {x,y,z})
    00479 static inline deDouble & Vec3d_GetElement(const deVec3d& v, long i)
    00480     {return *(((deDouble*)&v) + i); }
    00481 #endif
    00482
    00483 /// compute the inverse of a deVertex (overloaded operator-)
    00484 static inline deVertex operator-(const deVertex &v)
    00485     {deVertex ret={-v.x,-v.y,-v.z};return ret;}
    00486 /// compute the component difference between two deVertex (overloaded operator-)
    00487 static inline deVertex operator-(const deVertex &v1, const deVertex &v2)
    00488     {deVertex ret={v1.x-v2.x,v1.y-v2.y,v1.z-v2.z};return ret;}
    00489 /// compute the component sum of two deVertex (overloaded operator+)
    00490 static inline deVertex operator+(const deVertex &v1, const deVertex &v2)
    00491     {deVertex ret={v1.x+v2.x,v1.y+v2.y,v1.z+v2.z};return ret;}
    00492 /// compute the scalar product of a deVertex and a floating-point value (overloaded operator*)
    00493 static inline deVertex operator*(const deVertex &v1, deFloat f)
    00494     {deVertex ret={v1.x*f,v1.y*f,v1.z*f};return ret;}
    00495 /// subtract a deVertex from another one (overloaded operator-=)
    00496 static inline void operator-=(deVertex &v1, const deVertex &v2)
    00497     {v1.x -= v2.x; v1.y -= v2.y; v1.z -= v2.z; }
    00498 /// add a deVertex to another one (overloaded operator+=)
    00499 static inline void operator+=(deVertex &v1, const deVertex &v2)
    00500     {v1.x += v2.x; v1.y += v2.y; v1.z += v2.z; }
    00501 /// multiply a deVertex by a scalar value (overloaded operator*=)
    00502 static inline void operator*=(deVertex &v1, deFloat d)
    00503     {v1.x *= d; v1.y *= d; v1.z *= d; }
    00504 /// divide a deVertex by a scalar value (overloaded operator/=)
    00505 static inline void operator/=(deVertex &v1, deFloat d)
    00506     {deFloat d2 = 1/d; v1.x *= d2; v1.y *= d2; v1.z *= d2; }
    00507
    00508 static inline deTexCoord operator-(const deTexCoord &v1, const deTexCoord &v2)
    00509     {deTexCoord ret={v1.u-v2.u,v1.v-v2.v};return ret;}
    00510 static inline deTexCoord operator+(const deTexCoord &v1, const deTexCoord &v2)
    00511     {deTexCoord ret={v1.u+v2.u,v1.v+v2.v};return ret;}
    00512 static inline deTexCoord operator*(const deTexCoord &v1, deFloat f)
    00513     {deTexCoord ret={v1.u*f,v1.v*f};return ret;}
    00514 static inline void operator-=(deTexCoord &v1, const deTexCoord &v2)
    00515     {v1.u -= v2.u; v1.v -= v2.v; }
    00516 static inline void operator+=(deTexCoord &v1, const deTexCoord &v2)
    00517     {v1.u += v2.u; v1.v += v2.v; }
    00518 static inline void operator*=(deTexCoord &v1, deFloat d)
    00519     {v1.u *= d; v1.v *= d; }
    00520 static inline void operator/=(deTexCoord &v1, deFloat d)
    00521     {deFloat d2 = 1/d; v1.u *= d2; v1.v *= d2; }
    00522
    00523 /// multiply each component of a deColor by the corresponding component of another
    00524 static inline void operator*=(deColor& lhs, const deColor& rhs)
    00525     {lhs.a *= rhs.a; lhs.r *= rhs.r; lhs.g *= rhs.g; lhs.b *= rhs.b;}
    00526
    00527 /// "squeeze" the components of a deVec3d: if they are within Epsilon units of zero, set them to zero.
    00528 /// Useful for getting "perfect" orthographic orientations after moving around a bit
    00529 void Vec3d_Squeeze(deVec3d &v, deDouble Epsilon = 0.00001);
    00530 /// compute the cross product of two deVec3d
    00531 void Vec3d_Cross(const deVec3d &V1, const deVec3d &V2, deVec3d &Result);
    00532 /// compute the cross product of two deVertex
    00533 void Vec3d_Cross(const deVertex &V1, const deVertex &V2, deVertex &Result);
    00534 static inline deVec3d Vec3d_Cross(const deVec3d &V1, const deVec3d &V2)
    00535     {deVec3d ret; Vec3d_Cross(V1,V2,ret); return ret;}
    00536 /// normalize a deVec3d
    00537 /// @return the length of the original vector
    00538 deDouble Vec3d_Normalize(deVec3d &V);
    00539 /// normalize a deVertex
    00540 /// @return the length of the original vector
    00541 deFloat Vertex_Normalize(deVertex &V);
    00542 /// compute the 32-bit deARGB value for a normalized deVec3d (for dot3 bumpmapping)
    00543 deARGB Vec3d_ConvertToDot3(const deVec3d &V1, deFloat Height);
    00544 deARGB Vec3d_ConvertToDot3Clamp(const deVec3d &V1, deFloat Height);
    00545
    00546 /// Some useful geometry methods
    00547 namespace deGeometry
    00548 {
    00549     // standard true/false test functions
    00550     /// tests whether the inner AABB is actually inside the outer AABB
    00551     deBoolean BoxInBox(const deVec3d & OuterMin, const deVec3d & OuterMax, const deVec3d & InnerMin, const deVec3d & InnerMax);
    00552     /// tests whether the inner box is actually inside the outer box
    00553     deBoolean BoxInBox(const deAABB & OuterBox, const deAABB & InnerBox);
    00554     /// tests whether two AABBs intersect
    00555     deBoolean BoxBoxIntersect(const deVec3d & Min1, const deVec3d & Max1, const deVec3d & Min2, const deVec3d & Max2);
    00556     /// tests whether two AABBs intersect
    00557     deBoolean BoxBoxIntersect(const deAABB & Box1, const deAABB & Box2);
    00558     /// tests whether a point lies within an AABB
    00559     deBoolean PointInBox(const deVec3d & pt, const deVec3d &Min, const deVec3d &Max);
    00560     /// tests whether a point lies within an AABB
    00561     deBoolean PointInBox(const deVec3d & pt, const deAABB & Box);
    00562     /// returns the distance from a plane to a point, along the plane normal
    00563     static inline deDouble PlaneDist(const deVec3d & pt, const deVec3d & norm, const deDouble & dist)
    00564     {
    00565         return Vec3d_Dot(pt, norm) - dist;
    00566     }
    00567     /// tests whether a point lies on the front of a plane (positive half-space)
    00568     static inline deBoolean PointOnPlaneFront(const deVec3d & pt, const deVec3d & norm, const deDouble & dist)
    00569     { return (Vec3d_Dot(pt,norm) >= dist) ? deTRUE : deFALSE; }
    00570     /// tests whether a point lies on the back of a plane (negative half-space)
    00571     static inline deBoolean PointOnPlaneBack(const deVec3d & pt, const deVec3d & norm, const deDouble & dist)
    00572     { return (Vec3d_Dot(pt,norm) <= dist) ? deTRUE : deFALSE; }
    00573     /// tests whether a point lies within an AABB
    00574     static inline deBoolean PointInAABB(const deVec3d &Point, const deVec3d &Min, const deVec3d &Max)
    00575     {
    00576         if (Point.x < Min.x || Point.y < Min.y || Point.z < Min.z) return deFALSE;
    00577         if (Point.x > Max.x || Point.y > Max.y || Point.z > Max.z) return deFALSE;
    00578         return deTRUE;
    00579     }
    00580     /// calculates the geometric center of an AABB
    00581     static inline void AABBCenter(const deAABB & bbox, deVec3d & vec)
    00582     {
    00583         vec = bbox.Min; vec += bbox.Max; vec *= 0.5;
    00584     }
    00585     /*
    00586     needs fixing, radius is conservative
    00587     /// calculates circumscribed radius of an AABB, from the origin
    00588     static inline deDouble AABBRadius(const deAABB & BBox)
    00589     {
    00590         deDouble len1, len2;
    00591         len1 = Vec3d_LengthSq(BBox.Min);
    00592         len2 = Vec3d_LengthSq(BBox.Max);
    00593         if (len1 < 1 && len2 < 1)
    00594             len1 = sqrt(min(len1, len2));
    00595         else
    00596             len1 = sqrt(max(len1, len2));
    00597         return len1;
    00598     }
    00599     */
    00600     /// calculates diagonal size of an AABB, from min to max points
    00601     static inline deDouble AABBDiagonal(const deAABB & BBox)
    00602     {
    00603         deVec3d len;
    00604         len = BBox.Max;
    00605         len -= BBox.Min;
    00606         return Vec3d_Length(len);
    00607     }
    00608     /// tests whether a point lies within an AABB
    00609     static inline deBoolean PointInAABB(const deVec3d &Point, const deAABB & Box)
    00610     { return PointInAABB(Point, Box.Min, Box.Max); }
    00611     /// expand a given AABB by adding a point. Result: BBox is enlarged to hold input BBox space and pt
    00612     static inline void AABBAddPoint(deAABB & BBox, const deVec3d & pt)
    00613     {
    00614         BBox.Min.x = min(BBox.Min.x, pt.x);
    00615         BBox.Min.y = min(BBox.Min.y, pt.y);
    00616         BBox.Min.z = min(BBox.Min.z, pt.z);
    00617         BBox.Max.x = max(BBox.Max.x, pt.x);
    00618         BBox.Max.y = max(BBox.Max.y, pt.y);
    00619         BBox.Max.z = max(BBox.Max.z, pt.z);
    00620     }
    00621     /// compute the union of two AABBs, and store the resulting AABB in the first argument (In_Out)
    00622     static inline void AABBUnion(deAABB & In_Out, const deAABB & Input)
    00623     {
    00624         In_Out.Min.x = min(In_Out.Min.x, Input.Min.x);
    00625         In_Out.Min.y = min(In_Out.Min.y, Input.Min.y);
    00626         In_Out.Min.z = min(In_Out.Min.z, Input.Min.z);
    00627         In_Out.Max.x = max(In_Out.Max.x, Input.Max.x);
    00628         In_Out.Max.y = max(In_Out.Max.y, Input.Max.y);
    00629         In_Out.Max.z = max(In_Out.Max.z, Input.Max.z);
    00630     }
    00631     /// test whether two AABBs intersect, using a half-open interval
    00632     static inline deBoolean AABBIntersect(const deVec3d &Min1, const deVec3d &Max1, const deVec3d &Min2, const deVec3d &Max2)
    00633     {
    00634         // if one box's max is less than the other's min, they don't intersect
    00635         if (Max1.x < Min2.x || Max1.y < Min2.y || Max1.z < Min2.z) return deFALSE;
    00636         // and vice-versa
    00637         if (Max2.x < Min1.x || Max2.y < Min1.y || Max2.z < Min1.z) return deFALSE;
    00638         // otherwise, they do (I think)
    00639         return deTRUE;
    00640     }
    00641     /// test whether two AABBs intersect, using a half-open interval
    00642     static inline deBoolean AABBIntersect(const deAABB & Box1, const deAABB & Box2)
    00643     { return AABBIntersect(Box1.Min, Box1.Max, Box2.Min, Box2.Max); }
    00644     /// tests whether the inner AABB is actually inside the outer AABB
    00645     static inline deBoolean AABBInAABB(const deVec3d &InMin, const deVec3d &InMax, const deVec3d &OutMin, const deVec3d &OutMax)
    00646     {
    00647         // if the inner box's min is less than the outer box's min, it's not inside
    00648         if (InMin.x < OutMin.x || InMin.y < OutMin.y || InMin.z < OutMin.z) return deFALSE;
    00649         // and opposite relation with max
    00650         if (InMax.x > OutMax.x || InMax.y > OutMax.y || InMax.z > OutMax.z) return deFALSE;
    00651         // otherwise, they do (I think)
    00652         return deTRUE;
    00653     }
    00654     /// tests whether the inner AABB is actually inside the outer AABB
    00655     static inline deBoolean AABBInAABB(const deAABB & InBox, const deAABB & OutBox)
    00656     { return AABBInAABB(InBox.Min, InBox.Max, OutBox.Min, OutBox.Max); }
    00657     /// classify where an AABB lies relative to a plane.
    00658     /// -1 => all negative, 0 => intersects, 1 => all positive
    00659     int AABBPlaneClassify(const deAABB & BBox, const deVec3d & Norm, const deDouble & Dist);
    00660
    00661     // these take a non-const reference to fill in values
    00662     /// intersect a plane and a line segment
    00663     deBoolean PlaneLineIntersect(const deVec3d & Norm, const deDouble & Dist, const deVec3d & Pt1, const deVec3d & Pt2, deVec3d & Res, deDouble & Percent);
    00664     /// intersect a plane and a ray
    00665     deBoolean PlaneRayIntersect(const deVec3d & Norm, const deDouble & Dist, const deVec3d & Start, const deVec3d & Dir, deDouble & Multiple);
    00666     /// intersect a sphere and a ray
    00667     deBoolean SphereRayIntersect(const deVec3d & Center, const deDouble & Radius, const deVec3d & Start, const deVec3d & Dir, deDouble & Multiple);
    00668     /// intersect a sphere and a line segment
    00669     deBoolean SphereLineIntersect(const deVec3d & Center, const deDouble & Radius, const deVec3d & Start, const deVec3d & End, deVec3d & Res, deDouble & Percent);
    00670     /// perform a linear-sweep AABB collision test
    00671     deBoolean AABBCollision(const deAABB & MovingBox, const deVec3d & MoveStart, const deVec3d & MoveEnd,
    00672         const deAABB & StaticBox, const deVec3d & StaticPos, deVec3d & MovingColPt, deVec3d & ColNormal, deDouble & Percent);
    00673     /// create an AABB that contains a set of points
    00674     deBoolean ConstructAABB(const deVec3d * VecArray, long NumVecs, deVec3d & Min, deVec3d & Max);
    00675     /// create an OBB using an AABB and a transformation
    00676     deBoolean MakeOBBFromAABB(const deAABB & LocalBox, const deTransform & WorldMatrix, deOBB & WorldBox);
    00677     /// get the 8 corners of an AABB
    00678     deBoolean GetPointsOfAABB(const deAABB & BBox, deVec3d * ArrayOf8);
    00679     /// get the 8 corners of an OBB
    00680     deBoolean GetPointsOfOBB(const deOBB & WorldBox, deVec3d * ArrayOf8);
    00681     /// create an AABB that contains a set of points
    00682     static inline deBoolean ConstructAABB(const deVec3d * VecArray, long NumVecs, deAABB & Box)
    00683     { return ConstructAABB(VecArray, NumVecs, Box.Min, Box.Max); }
    00684     /// create an AABB that contains an OBB
    00685     static inline deBoolean MakeAABBFromOBB(const deOBB & InBox, deAABB & OutBox)
    00686     {
    00687         deVec3d vecarray[8];
    00688         if (!GetPointsOfOBB(InBox, vecarray)) return deFALSE;
    00689         if (!ConstructAABB(vecarray, 8, OutBox)) return deFALSE;
    00690         return deTRUE;
    00691     }
    00692     /// create a BSphere from an AABB
    00693     static inline void MakeBoundSphereFromAABB(const deAABB & BBox, deBoundSphere & OutSphere)
    00694     {
    00695         OutSphere.Radius = AABBDiagonal(BBox) * 0.5;
    00696         AABBCenter(BBox, OutSphere.Center);
    00697     }
    00698     /// intersect an OBB and a ray
    00699     deBoolean RayOBBIntersect(const deVec3d & RayStart, const deVec3d & RayDir, const deOBB & Box, deVec3d & Result, deVec3d & Normal, deDouble & Percent);
    00700
    00701     /// intersect a plane and a line segment
    00702     static inline deBoolean PlaneLineIntersect(const dePlane & Plane, const deVec3d & Pt1, const deVec3d & Pt2, deVec3d & Res, deDouble & Percent)
    00703     { return PlaneLineIntersect(Plane.Norm, Plane.Dist, Pt1, Pt2, Res, Percent); }
    00704     /// intersect a plane and a ray
    00705     static inline deBoolean PlaneRayIntersect(const dePlane & Plane, const deVec3d & Start, const deVec3d & Dir, deDouble & Multiple)
    00706     { return PlaneRayIntersect(Plane.Norm, Plane.Dist, Start, Dir, Multiple); }
    00707
    00708     /// interpolate a Vec3d over a range [0,1]
    00709     static inline void Vec3d_Interpolate(deVec3d & Output, const deVec3d & In1, const deVec3d& In2, deDouble Percent)
    00710     {
    00711         Output.x = In1.x*(1-Percent) + In2.x*Percent;
    00712         Output.y = In1.y*(1-Percent) + In2.y*Percent;
    00713         Output.z = In1.z*(1-Percent) + In2.z*Percent;
    00714     }
    00715     /// interpolate a Vertex over a range [0,1]
    00716     static inline void Vertex_Interpolate(deVertex & Output, const deVertex & In1, const deVertex& In2, deDouble Percent)
    00717     {
    00718         Output.x = deFloat(In1.x*(1-Percent) + In2.x*Percent);
    00719         Output.y = deFloat(In1.y*(1-Percent) + In2.y*Percent);
    00720         Output.z = deFloat(In1.z*(1-Percent) + In2.z*Percent);
    00721     }
    00722     /// interpolate a TexCoord2 over a range [0,1]
    00723     static inline void TexCoord_Interpolate(deTexCoord2 & Output, const deTexCoord2 & In1, const deTexCoord2& In2, deDouble Percent)
    00724     {
    00725         Output.u = deFloat(In1.u*(1-Percent) + In2.u*Percent);
    00726         Output.v = deFloat(In1.v*(1-Percent) + In2.v*Percent);
    00727     }
    00728     /// interpolate an ARGB over a range [0,1]
    00729     static inline void ARGB_Interpolate(deARGB& Output, deARGB Color1, deARGB Color2, deFloat Percent)
    00730     {
    00731         Output =
    00732             (deARGB((1-Percent)*((Color1>>24)&0xff) + (Percent)*((Color2>>24)&0xff)) << 24) |
    00733             (deARGB((1-Percent)*((Color1>>16)&0xff) + (Percent)*((Color2>>16)&0xff)) << 16) |
    00734             (deARGB((1-Percent)*((Color1>> 8)&0xff) + (Percent)*((Color2>> 8)&0xff)) << 8)  |
    00735             (deARGB((1-Percent)*((Color1    )&0xff) + (Percent)*((Color2    )&0xff)));
    00736     }
    00737 };
    00738
    00739
    00740 #endif