oculus1

diff libovr/Src/Kernel/OVR_Math.h @ 1:e2f9e4603129

added LibOVR and started a simple vr wrapper.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Sep 2013 16:14:59 +0300
parents
children b069a5c27388
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libovr/Src/Kernel/OVR_Math.h	Sat Sep 14 16:14:59 2013 +0300
     1.3 @@ -0,0 +1,1 @@
     1.4 +/************************************************************************************
     1.5 
     1.6 PublicHeader:   OVR.h
     1.7 Filename    :   OVR_Math.h
     1.8 Content     :   Implementation of 3D primitives such as vectors, matrices.
     1.9 Created     :   September 4, 2012
    1.10 Authors     :   Andrew Reisse, Michael Antonov, Steve LaValle, Anna Yershova
    1.11 
    1.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    1.13 
    1.14 Use of this software is subject to the terms of the Oculus license
    1.15 agreement provided at the time of installation or download, or which
    1.16 otherwise accompanies this software in either electronic or hard copy form.
    1.17 
    1.18 *************************************************************************************/
    1.19 
    1.20 #ifndef OVR_Math_h
    1.21 #define OVR_Math_h
    1.22 
    1.23 #include <assert.h>
    1.24 #include <stdlib.h>
    1.25 #include <math.h>
    1.26 
    1.27 #include "OVR_Types.h"
    1.28 #include "OVR_RefCount.h"
    1.29 
    1.30 namespace OVR {
    1.31 
    1.32 //-------------------------------------------------------------------------------------
    1.33 // Constants for 3D world/axis definitions.
    1.34 
    1.35 // Definitions of axes for coordinate and rotation conversions.
    1.36 enum Axis
    1.37 {
    1.38     Axis_X = 0, Axis_Y = 1, Axis_Z = 2
    1.39 };
    1.40 
    1.41 // RotateDirection describes the rotation direction around an axis, interpreted as follows:
    1.42 //  CW  - Clockwise while looking "down" from positive axis towards the origin.
    1.43 //  CCW - Counter-clockwise while looking from the positive axis towards the origin,
    1.44 //        which is in the negative axis direction.
    1.45 //  CCW is the default for the RHS coordinate system. Oculus standard RHS coordinate
    1.46 //  system defines Y up, X right, and Z back (pointing out from the screen). In this
    1.47 //  system Rotate_CCW around Z will specifies counter-clockwise rotation in XY plane.
    1.48 enum RotateDirection
    1.49 {
    1.50     Rotate_CCW = 1,
    1.51     Rotate_CW  = -1 
    1.52 };
    1.53 
    1.54 enum HandedSystem
    1.55 {
    1.56     Handed_R = 1, Handed_L = -1
    1.57 };
    1.58 
    1.59 // AxisDirection describes which way the axis points. Used by WorldAxes.
    1.60 enum AxisDirection
    1.61 {
    1.62     Axis_Up    =  2,
    1.63     Axis_Down  = -2,
    1.64     Axis_Right =  1,
    1.65     Axis_Left  = -1,
    1.66     Axis_In    =  3,
    1.67     Axis_Out   = -3
    1.68 };
    1.69 
    1.70 struct WorldAxes
    1.71 {
    1.72     AxisDirection XAxis, YAxis, ZAxis;
    1.73 
    1.74     WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z)
    1.75         : XAxis(x), YAxis(y), ZAxis(z) 
    1.76     { OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));}
    1.77 };
    1.78 
    1.79 
    1.80 //-------------------------------------------------------------------------------------
    1.81 // ***** Math
    1.82 
    1.83 // Math class contains constants and functions. This class is a template specialized
    1.84 // per type, with Math<float> and Math<double> being distinct.
    1.85 template<class Type>
    1.86 class Math
    1.87 {  
    1.88 };
    1.89 
    1.90 // Single-precision Math constants class.
    1.91 template<>
    1.92 class Math<float>
    1.93 {
    1.94 public:
    1.95     static const float Pi;
    1.96     static const float TwoPi;
    1.97     static const float PiOver2;
    1.98     static const float PiOver4;
    1.99     static const float E;
   1.100 
   1.101     static const float MaxValue;          // Largest positive float Value
   1.102     static const float MinPositiveValue;  // Smallest possible positive value
   1.103 
   1.104     static const float RadToDegreeFactor;
   1.105     static const float DegreeToRadFactor;
   1.106 
   1.107     static const float Tolerance; //  0.00001f;
   1.108     static const float SingularityRadius; //0.00000000001f for Gimbal lock numerical problems
   1.109 };
   1.110 
   1.111 // Double-precision Math constants class.
   1.112 template<>
   1.113 class Math<double>
   1.114 {
   1.115 public:
   1.116     static const double Pi;
   1.117     static const double TwoPi;
   1.118     static const double PiOver2;
   1.119     static const double PiOver4;
   1.120     static const double E;
   1.121 
   1.122     static const double MaxValue;          // Largest positive double Value
   1.123     static const double MinPositiveValue;  // Smallest possible positive value
   1.124 
   1.125     static const double RadToDegreeFactor;
   1.126     static const double DegreeToRadFactor;
   1.127 
   1.128     static const double Tolerance; //  0.00001f;
   1.129     static const double SingularityRadius; //0.00000000001 for Gimbal lock numerical problems
   1.130 };
   1.131 
   1.132 typedef Math<float>  Mathf;
   1.133 typedef Math<double> Mathd;
   1.134 
   1.135 // Conversion functions between degrees and radians
   1.136 template<class FT>
   1.137 FT RadToDegree(FT rads) { return rads * Math<FT>::RadToDegreeFactor; }
   1.138 template<class FT>
   1.139 FT DegreeToRad(FT rads) { return rads * Math<FT>::DegreeToRadFactor; }
   1.140 
   1.141 template<class T>
   1.142 class Quat;
   1.143 
   1.144 //-------------------------------------------------------------------------------------
   1.145 // ***** Vector2f - 2D Vector2f
   1.146 
   1.147 // Vector2f represents a 2-dimensional vector or point in space,
   1.148 // consisting of coordinates x and y,
   1.149 
   1.150 template<class T>
   1.151 class Vector2
   1.152 {
   1.153 public:
   1.154     T x, y;
   1.155 
   1.156     Vector2() : x(0), y(0) { }
   1.157     Vector2(T x_, T y_) : x(x_), y(y_) { }
   1.158     explicit Vector2(T s) : x(s), y(s) { }
   1.159 
   1.160     bool     operator== (const Vector2& b) const  { return x == b.x && y == b.y; }
   1.161     bool     operator!= (const Vector2& b) const  { return x != b.x || y != b.y; }
   1.162              
   1.163     Vector2  operator+  (const Vector2& b) const  { return Vector2(x + b.x, y + b.y); }
   1.164     Vector2& operator+= (const Vector2& b)        { x += b.x; y += b.y; return *this; }
   1.165     Vector2  operator-  (const Vector2& b) const  { return Vector2(x - b.x, y - b.y); }
   1.166     Vector2& operator-= (const Vector2& b)        { x -= b.x; y -= b.y; return *this; }
   1.167     Vector2  operator- () const                   { return Vector2(-x, -y); }
   1.168 
   1.169     // Scalar multiplication/division scales vector.
   1.170     Vector2  operator*  (T s) const               { return Vector2(x*s, y*s); }
   1.171     Vector2& operator*= (T s)                     { x *= s; y *= s; return *this; }
   1.172 
   1.173     Vector2  operator/  (T s) const               { T rcp = T(1)/s;
   1.174                                                     return Vector2(x*rcp, y*rcp); }
   1.175     Vector2& operator/= (T s)                     { T rcp = T(1)/s;
   1.176                                                     x *= rcp; y *= rcp;
   1.177                                                     return *this; }
   1.178 
   1.179     // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
   1.180     bool      Compare(const Vector2&b, T tolerance = Mathf::Tolerance)
   1.181     {
   1.182         return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance);
   1.183     }
   1.184     
   1.185     // Dot product overload.
   1.186     // Used to calculate angle q between two vectors among other things,
   1.187     // as (A dot B) = |a||b|cos(q).
   1.188     T     operator*  (const Vector2& b) const    { return x*b.x + y*b.y; }
   1.189 
   1.190     // Returns the angle from this vector to b, in radians.
   1.191     T       Angle(const Vector2& b) const        { return acos((*this * b)/(Length()*b.Length())); }
   1.192 
   1.193     // Return Length of the vector squared.
   1.194     T       LengthSq() const                     { return (x * x + y * y); }
   1.195     // Return vector length.
   1.196     T       Length() const                       { return sqrt(LengthSq()); }
   1.197 
   1.198     // Returns distance between two points represented by vectors.
   1.199     T       Distance(Vector2& b) const           { return (*this - b).Length(); }
   1.200     
   1.201     // Determine if this a unit vector.
   1.202     bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
   1.203     // Normalize, convention vector length to 1.    
   1.204     void    Normalize()                          { *this /= Length(); }
   1.205     // Returns normalized (unit) version of the vector without modifying itself.
   1.206     Vector2 Normalized() const                   { return *this / Length(); }
   1.207 
   1.208     // Linearly interpolates from this vector to another.
   1.209     // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
   1.210     Vector2 Lerp(const Vector2& b, T f) const    { return *this*(T(1) - f) + b*f; }
   1.211 
   1.212     // Projects this vector onto the argument; in other words,
   1.213     // A.Project(B) returns projection of vector A onto B.
   1.214     Vector2 ProjectTo(const Vector2& b) const    { return b * ((*this * b) / b.LengthSq()); }
   1.215 };
   1.216 
   1.217 
   1.218 typedef Vector2<float>  Vector2f;
   1.219 typedef Vector2<double> Vector2d;
   1.220 
   1.221 //-------------------------------------------------------------------------------------
   1.222 // ***** Vector3f - 3D Vector3f
   1.223 
   1.224 // Vector3f represents a 3-dimensional vector or point in space,
   1.225 // consisting of coordinates x, y and z.
   1.226 
   1.227 template<class T>
   1.228 class Vector3
   1.229 {
   1.230 public:
   1.231     T x, y, z;
   1.232 
   1.233     Vector3() : x(0), y(0), z(0) { }
   1.234     Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { }
   1.235     explicit Vector3(T s) : x(s), y(s), z(s) { }
   1.236 
   1.237     bool     operator== (const Vector3& b) const  { return x == b.x && y == b.y && z == b.z; }
   1.238     bool     operator!= (const Vector3& b) const  { return x != b.x || y != b.y || z != b.z; }
   1.239              
   1.240     Vector3  operator+  (const Vector3& b) const  { return Vector3(x + b.x, y + b.y, z + b.z); }
   1.241     Vector3& operator+= (const Vector3& b)        { x += b.x; y += b.y; z += b.z; return *this; }
   1.242     Vector3  operator-  (const Vector3& b) const  { return Vector3(x - b.x, y - b.y, z - b.z); }
   1.243     Vector3& operator-= (const Vector3& b)        { x -= b.x; y -= b.y; z -= b.z; return *this; }
   1.244     Vector3  operator- () const                   { return Vector3(-x, -y, -z); }
   1.245 
   1.246     // Scalar multiplication/division scales vector.
   1.247     Vector3  operator*  (T s) const               { return Vector3(x*s, y*s, z*s); }
   1.248     Vector3& operator*= (T s)                     { x *= s; y *= s; z *= s; return *this; }
   1.249 
   1.250     Vector3  operator/  (T s) const               { T rcp = T(1)/s;
   1.251                                                     return Vector3(x*rcp, y*rcp, z*rcp); }
   1.252     Vector3& operator/= (T s)                     { T rcp = T(1)/s;
   1.253                                                     x *= rcp; y *= rcp; z *= rcp;
   1.254                                                     return *this; }
   1.255 
   1.256     // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
   1.257     bool      Compare(const Vector3&b, T tolerance = Mathf::Tolerance)
   1.258     {
   1.259         return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance) && (fabs(b.z-z) < tolerance);
   1.260     }
   1.261     
   1.262     // Dot product overload.
   1.263     // Used to calculate angle q between two vectors among other things,
   1.264     // as (A dot B) = |a||b|cos(q).
   1.265     T     operator*  (const Vector3& b) const    { return x*b.x + y*b.y + z*b.z; }
   1.266 
   1.267     // Compute cross product, which generates a normal vector.
   1.268     // Direction vector can be determined by right-hand rule: Pointing index finder in
   1.269     // direction a and middle finger in direction b, thumb will point in a.Cross(b).
   1.270     Vector3 Cross(const Vector3& b) const        { return Vector3(y*b.z - z*b.y,
   1.271                                                                   z*b.x - x*b.z,
   1.272                                                                   x*b.y - y*b.x); }
   1.273 
   1.274     // Returns the angle from this vector to b, in radians.
   1.275     T       Angle(const Vector3& b) const        { return acos((*this * b)/(Length()*b.Length())); }
   1.276 
   1.277     // Return Length of the vector squared.
   1.278     T       LengthSq() const                     { return (x * x + y * y + z * z); }
   1.279     // Return vector length.
   1.280     T       Length() const                       { return sqrt(LengthSq()); }
   1.281 
   1.282     // Returns distance between two points represented by vectors.
   1.283     T       Distance(Vector3& b) const           { return (*this - b).Length(); }
   1.284     
   1.285     // Determine if this a unit vector.
   1.286     bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
   1.287     // Normalize, convention vector length to 1.    
   1.288     void    Normalize()                          { *this /= Length(); }
   1.289     // Returns normalized (unit) version of the vector without modifying itself.
   1.290     Vector3 Normalized() const                   { return *this / Length(); }
   1.291 
   1.292     // Linearly interpolates from this vector to another.
   1.293     // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
   1.294     Vector3 Lerp(const Vector3& b, T f) const    { return *this*(T(1) - f) + b*f; }
   1.295 
   1.296     // Projects this vector onto the argument; in other words,
   1.297     // A.Project(B) returns projection of vector A onto B.
   1.298     Vector3 ProjectTo(const Vector3& b) const    { return b * ((*this * b) / b.LengthSq()); }
   1.299 };
   1.300 
   1.301 
   1.302 typedef Vector3<float>  Vector3f;
   1.303 typedef Vector3<double> Vector3d;
   1.304 
   1.305 
   1.306 //-------------------------------------------------------------------------------------
   1.307 // ***** Matrix4f 
   1.308 
   1.309 // Matrix4f is a 4x4 matrix used for 3d transformations and projections.
   1.310 // Translation stored in the last column.
   1.311 // The matrix is stored in row-major order in memory, meaning that values
   1.312 // of the first row are stored before the next one.
   1.313 //
   1.314 // The arrangement of the matrix is chosen to be in Right-Handed 
   1.315 // coordinate system and counterclockwise rotations when looking down
   1.316 // the axis
   1.317 //
   1.318 // Transformation Order:
   1.319 //   - Transformations are applied from right to left, so the expression
   1.320 //     M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
   1.321 //     followed by M2 and M1. 
   1.322 //
   1.323 // Coordinate system: Right Handed
   1.324 //
   1.325 // Rotations: Counterclockwise when looking down the axis. All angles are in radians.
   1.326 //    
   1.327 //  | sx   01   02   tx |    // First column  (sx, 10, 20): Axis X basis vector.
   1.328 //  | 10   sy   12   ty |    // Second column (01, sy, 21): Axis Y basis vector.
   1.329 //  | 20   21   sz   tz |    // Third columnt (02, 12, sz): Axis Z basis vector.
   1.330 //  | 30   31   32   33 |
   1.331 //
   1.332 //  The basis vectors are first three columns.
   1.333 
   1.334 class Matrix4f
   1.335 {
   1.336     static Matrix4f IdentityValue;
   1.337 
   1.338 public:
   1.339     float M[4][4];    
   1.340 
   1.341     enum NoInitType { NoInit };
   1.342 
   1.343     // Construct with no memory initialization.
   1.344     Matrix4f(NoInitType) { }
   1.345 
   1.346     // By default, we construct identity matrix.
   1.347     Matrix4f()
   1.348     {
   1.349         SetIdentity();        
   1.350     }
   1.351 
   1.352     Matrix4f(float m11, float m12, float m13, float m14,
   1.353              float m21, float m22, float m23, float m24,
   1.354              float m31, float m32, float m33, float m34,
   1.355              float m41, float m42, float m43, float m44)
   1.356     {
   1.357         M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14;
   1.358         M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24;
   1.359         M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = m34;
   1.360         M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44;
   1.361     }
   1.362 
   1.363     Matrix4f(float m11, float m12, float m13,
   1.364              float m21, float m22, float m23,
   1.365              float m31, float m32, float m33)
   1.366     {
   1.367         M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = 0;
   1.368         M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = 0;
   1.369         M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = 0;
   1.370         M[3][0] = 0;   M[3][1] = 0;   M[3][2] = 0;   M[3][3] = 1;
   1.371     }
   1.372 
   1.373     static const Matrix4f& Identity()  { return IdentityValue; }
   1.374 
   1.375     void SetIdentity()
   1.376     {
   1.377         M[0][0] = M[1][1] = M[2][2] = M[3][3] = 1;
   1.378         M[0][1] = M[1][0] = M[2][3] = M[3][1] = 0;
   1.379         M[0][2] = M[1][2] = M[2][0] = M[3][2] = 0;
   1.380         M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0;
   1.381     }
   1.382 
   1.383     // Multiplies two matrices into destination with minimum copying.
   1.384     static Matrix4f& Multiply(Matrix4f* d, const Matrix4f& a, const Matrix4f& b)
   1.385     {
   1.386         OVR_ASSERT((d != &a) && (d != &b));
   1.387         int i = 0;
   1.388         do {
   1.389             d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0] + a.M[i][3] * b.M[3][0];
   1.390             d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1] + a.M[i][3] * b.M[3][1];
   1.391             d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2] + a.M[i][3] * b.M[3][2];
   1.392             d->M[i][3] = a.M[i][0] * b.M[0][3] + a.M[i][1] * b.M[1][3] + a.M[i][2] * b.M[2][3] + a.M[i][3] * b.M[3][3];
   1.393         } while((++i) < 4);
   1.394 
   1.395         return *d;
   1.396     }
   1.397 
   1.398     Matrix4f operator* (const Matrix4f& b) const
   1.399     {
   1.400         Matrix4f result(Matrix4f::NoInit);
   1.401         Multiply(&result, *this, b);
   1.402         return result;
   1.403     }
   1.404 
   1.405     Matrix4f& operator*= (const Matrix4f& b)
   1.406     {
   1.407         return Multiply(this, Matrix4f(*this), b);
   1.408     }
   1.409 
   1.410     Matrix4f operator* (float s) const
   1.411     {
   1.412         return Matrix4f(M[0][0] * s, M[0][1] * s, M[0][2] * s, M[0][3] * s,
   1.413                         M[1][0] * s, M[1][1] * s, M[1][2] * s, M[1][3] * s,
   1.414                         M[2][0] * s, M[2][1] * s, M[2][2] * s, M[2][3] * s,
   1.415                         M[3][0] * s, M[3][1] * s, M[3][2] * s, M[3][3] * s);
   1.416     }
   1.417 
   1.418     Matrix4f& operator*= (float s)
   1.419     {
   1.420         M[0][0] *= s; M[0][1] *= s; M[0][2] *= s; M[0][3] *= s;
   1.421         M[1][0] *= s; M[1][1] *= s; M[1][2] *= s; M[1][3] *= s;
   1.422         M[2][0] *= s; M[2][1] *= s; M[2][2] *= s; M[2][3] *= s;
   1.423         M[3][0] *= s; M[3][1] *= s; M[3][2] *= s; M[3][3] *= s;
   1.424         return *this;
   1.425     }
   1.426 
   1.427     Vector3f Transform(const Vector3f& v) const
   1.428     {
   1.429         return Vector3f(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3],
   1.430                         M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3],
   1.431                         M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]);
   1.432     }
   1.433 
   1.434     Matrix4f Transposed() const
   1.435     {
   1.436         return Matrix4f(M[0][0], M[1][0], M[2][0], M[3][0],
   1.437                         M[0][1], M[1][1], M[2][1], M[3][1],
   1.438                         M[0][2], M[1][2], M[2][2], M[3][2],
   1.439                         M[0][3], M[1][3], M[2][3], M[3][3]);
   1.440     }
   1.441 
   1.442     void     Transpose()
   1.443     {
   1.444         *this = Transposed();
   1.445     }
   1.446 
   1.447 
   1.448     float SubDet (const int* rows, const int* cols) const
   1.449     {
   1.450         return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]])
   1.451              - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]])
   1.452              + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]);
   1.453     }
   1.454 
   1.455     float Cofactor(int I, int J) const
   1.456     {
   1.457         const int indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}};
   1.458         return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]);
   1.459     }
   1.460 
   1.461     float    Determinant() const
   1.462     {
   1.463         return M[0][0] * Cofactor(0,0) + M[0][1] * Cofactor(0,1) + M[0][2] * Cofactor(0,2) + M[0][3] * Cofactor(0,3);
   1.464     }
   1.465 
   1.466     Matrix4f Adjugated() const
   1.467     {
   1.468         return Matrix4f(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), 
   1.469                         Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), 
   1.470                         Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2),
   1.471                         Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3));
   1.472     }
   1.473 
   1.474     Matrix4f Inverted() const
   1.475     {
   1.476         float det = Determinant();
   1.477         assert(det != 0);
   1.478         return Adjugated() * (1.0f/det);
   1.479     }
   1.480 
   1.481     void Invert()
   1.482     {
   1.483         *this = Inverted();
   1.484     }
   1.485 
   1.486     //AnnaSteve:
   1.487     // a,b,c, are the YawPitchRoll angles to be returned
   1.488     // rotation a around axis A1
   1.489     // is followed by rotation b around axis A2
   1.490     // is followed by rotation c around axis A3
   1.491     // rotations are CCW or CW (D) in LH or RH coordinate system (S)
   1.492     template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
   1.493     void ToEulerAngles(float *a, float *b, float *c)
   1.494     {
   1.495         OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
   1.496 
   1.497         float psign = -1.0f;
   1.498         if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation
   1.499         psign = 1.0f;
   1.500         
   1.501         float pm = psign*M[A1][A3];
   1.502         if (pm < -1.0f + Math<float>::SingularityRadius)
   1.503         { // South pole singularity
   1.504             *a = 0.0f;
   1.505             *b = -S*D*Math<float>::PiOver2;
   1.506             *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
   1.507         }
   1.508         else if (pm > 1.0 - Math<float>::SingularityRadius)
   1.509         { // North pole singularity
   1.510             *a = 0.0f;
   1.511             *b = S*D*Math<float>::PiOver2;
   1.512             *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
   1.513         }
   1.514         else
   1.515         { // Normal case (nonsingular)
   1.516             *a = S*D*atan2( -psign*M[A2][A3], M[A3][A3] );
   1.517             *b = S*D*asin(pm);
   1.518             *c = S*D*atan2( -psign*M[A1][A2], M[A1][A1] );
   1.519         }
   1.520 
   1.521         return;
   1.522     }
   1.523 
   1.524     //AnnaSteve:
   1.525     // a,b,c, are the YawPitchRoll angles to be returned
   1.526     // rotation a around axis A1
   1.527     // is followed by rotation b around axis A2
   1.528     // is followed by rotation c around axis A1
   1.529     // rotations are CCW or CW (D) in LH or RH coordinate system (S)
   1.530     template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
   1.531     void ToEulerAnglesABA(float *a, float *b, float *c)
   1.532     {        
   1.533          OVR_COMPILER_ASSERT(A1 != A2);
   1.534   
   1.535         // Determine the axis that was not supplied
   1.536         int m = 3 - A1 - A2;
   1.537 
   1.538         float psign = -1.0f;
   1.539         if ((A1 + 1) % 3 == A2) // Determine whether even permutation
   1.540             psign = 1.0f;
   1.541 
   1.542         float c2 = M[A1][A1];
   1.543         if (c2 < -1.0 + Math<float>::SingularityRadius)
   1.544         { // South pole singularity
   1.545             *a = 0.0f;
   1.546             *b = S*D*Math<float>::Pi;
   1.547             *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
   1.548         }
   1.549         else if (c2 > 1.0 - Math<float>::SingularityRadius)
   1.550         { // North pole singularity
   1.551             *a = 0.0f;
   1.552             *b = 0.0f;
   1.553             *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
   1.554         }
   1.555         else
   1.556         { // Normal case (nonsingular)
   1.557             *a = S*D*atan2( M[A2][A1],-psign*M[m][A1]);
   1.558             *b = S*D*acos(c2);
   1.559             *c = S*D*atan2( M[A1][A2],psign*M[A1][m]);
   1.560         }
   1.561         return;
   1.562     }
   1.563   
   1.564     // Creates a matrix that converts the vertices from one coordinate system
   1.565     // to another.
   1.566     // 
   1.567     static Matrix4f AxisConversion(const WorldAxes& to, const WorldAxes& from)
   1.568     {        
   1.569         // Holds axis values from the 'to' structure
   1.570         int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis };
   1.571 
   1.572         // The inverse of the toArray
   1.573         int inv[4]; 
   1.574         inv[0] = inv[abs(to.XAxis)] = 0;
   1.575         inv[abs(to.YAxis)] = 1;
   1.576         inv[abs(to.ZAxis)] = 2;
   1.577 
   1.578         Matrix4f m(0,  0,  0, 
   1.579                    0,  0,  0,
   1.580                    0,  0,  0);
   1.581 
   1.582         // Only three values in the matrix need to be changed to 1 or -1.
   1.583         m.M[inv[abs(from.XAxis)]][0] = float(from.XAxis/toArray[inv[abs(from.XAxis)]]);
   1.584         m.M[inv[abs(from.YAxis)]][1] = float(from.YAxis/toArray[inv[abs(from.YAxis)]]);
   1.585         m.M[inv[abs(from.ZAxis)]][2] = float(from.ZAxis/toArray[inv[abs(from.ZAxis)]]);
   1.586         return m;
   1.587     } 
   1.588 
   1.589 
   1.590 
   1.591     static Matrix4f Translation(const Vector3f& v)
   1.592     {
   1.593         Matrix4f t;
   1.594         t.M[0][3] = v.x;
   1.595         t.M[1][3] = v.y;
   1.596         t.M[2][3] = v.z;
   1.597         return t;
   1.598     }
   1.599 
   1.600     static Matrix4f Translation(float x, float y, float z = 0.0f)
   1.601     {
   1.602         Matrix4f t;
   1.603         t.M[0][3] = x;
   1.604         t.M[1][3] = y;
   1.605         t.M[2][3] = z;
   1.606         return t;
   1.607     }
   1.608 
   1.609     static Matrix4f Scaling(const Vector3f& v)
   1.610     {
   1.611         Matrix4f t;
   1.612         t.M[0][0] = v.x;
   1.613         t.M[1][1] = v.y;
   1.614         t.M[2][2] = v.z;
   1.615         return t;
   1.616     }
   1.617 
   1.618     static Matrix4f Scaling(float x, float y, float z)
   1.619     {
   1.620         Matrix4f t;
   1.621         t.M[0][0] = x;
   1.622         t.M[1][1] = y;
   1.623         t.M[2][2] = z;
   1.624         return t;
   1.625     }
   1.626 
   1.627     static Matrix4f Scaling(float s)
   1.628     {
   1.629         Matrix4f t;
   1.630         t.M[0][0] = s;
   1.631         t.M[1][1] = s;
   1.632         t.M[2][2] = s;
   1.633         return t;
   1.634     }
   1.635 
   1.636   
   1.637 
   1.638     //AnnaSteve : Just for quick testing.  Not for final API.  Need to remove case.
   1.639     static Matrix4f RotationAxis(Axis A, float angle, RotateDirection d, HandedSystem s)
   1.640     {
   1.641         float sina = s * d *sin(angle);
   1.642         float cosa = cos(angle);
   1.643         
   1.644         switch(A)
   1.645         {
   1.646         case Axis_X:
   1.647             return Matrix4f(1,  0,     0, 
   1.648                             0,  cosa,  -sina,
   1.649                             0,  sina,  cosa);
   1.650         case Axis_Y:
   1.651             return Matrix4f(cosa,  0,   sina, 
   1.652                             0,     1,   0,
   1.653                             -sina, 0,   cosa);
   1.654         case Axis_Z:
   1.655             return Matrix4f(cosa,  -sina,  0, 
   1.656                             sina,  cosa,   0,
   1.657                             0,     0,      1);
   1.658         }
   1.659     }
   1.660 
   1.661 
   1.662     // Creates a rotation matrix rotating around the X axis by 'angle' radians.
   1.663     // Rotation direction is depends on the coordinate system:
   1.664     //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
   1.665     //                        while looking in the negative axis direction. This is the
   1.666     //                        same as looking down from positive axis values towards origin.
   1.667     //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
   1.668     //       negative axis direction.
   1.669     static Matrix4f RotationX(float angle)
   1.670     {
   1.671         float sina = sin(angle);
   1.672         float cosa = cos(angle);
   1.673         return Matrix4f(1,  0,     0, 
   1.674                         0,  cosa,  -sina,
   1.675                         0,  sina,  cosa);
   1.676     }
   1.677 
   1.678     // Creates a rotation matrix rotating around the Y axis by 'angle' radians.
   1.679     // Rotation direction is depends on the coordinate system:
   1.680     //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
   1.681     //                        while looking in the negative axis direction. This is the
   1.682     //                        same as looking down from positive axis values towards origin.
   1.683     //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
   1.684     //       negative axis direction.
   1.685     static Matrix4f RotationY(float angle)
   1.686     {
   1.687         float sina = sin(angle);
   1.688         float cosa = cos(angle);
   1.689         return Matrix4f(cosa,  0,   sina, 
   1.690                         0,     1,   0,
   1.691                         -sina, 0,   cosa);
   1.692     }
   1.693 
   1.694     // Creates a rotation matrix rotating around the Z axis by 'angle' radians.
   1.695     // Rotation direction is depends on the coordinate system:
   1.696     //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
   1.697     //                        while looking in the negative axis direction. This is the
   1.698     //                        same as looking down from positive axis values towards origin.
   1.699     //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
   1.700     //       negative axis direction.
   1.701     static Matrix4f RotationZ(float angle)
   1.702     {
   1.703         float sina = sin(angle);
   1.704         float cosa = cos(angle);
   1.705         return Matrix4f(cosa,  -sina,  0, 
   1.706                         sina,  cosa,   0,
   1.707                         0,     0,      1);
   1.708     }
   1.709 
   1.710 
   1.711     // LookAtRH creates a View transformation matrix for right-handed coordinate system.
   1.712     // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
   1.713     // specifying the up vector. The resulting matrix should be used with PerspectiveRH
   1.714     // projection.
   1.715     static Matrix4f LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up);
   1.716 
   1.717     // LookAtLH creates a View transformation matrix for left-handed coordinate system.
   1.718     // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
   1.719     // specifying the up vector. 
   1.720     static Matrix4f LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up);
   1.721     
   1.722     
   1.723     // PerspectiveRH creates a right-handed perspective projection matrix that can be
   1.724     // used with the Oculus sample renderer. 
   1.725     //  yfov   - Specifies vertical field of view in radians.
   1.726     //  aspect - Screen aspect ration, which is usually width/height for square pixels.
   1.727     //           Note that xfov = yfov * aspect.
   1.728     //  znear  - Absolute value of near Z clipping clipping range.
   1.729     //  zfar   - Absolute value of far  Z clipping clipping range (larger then near).
   1.730     // Even though RHS usually looks in the direction of negative Z, positive values
   1.731     // are expected for znear and zfar.
   1.732     static Matrix4f PerspectiveRH(float yfov, float aspect, float znear, float zfar);
   1.733     
   1.734     
   1.735     // PerspectiveRH creates a left-handed perspective projection matrix that can be
   1.736     // used with the Oculus sample renderer. 
   1.737     //  yfov   - Specifies vertical field of view in radians.
   1.738     //  aspect - Screen aspect ration, which is usually width/height for square pixels.
   1.739     //           Note that xfov = yfov * aspect.
   1.740     //  znear  - Absolute value of near Z clipping clipping range.
   1.741     //  zfar   - Absolute value of far  Z clipping clipping range (larger then near).
   1.742     static Matrix4f PerspectiveLH(float yfov, float aspect, float znear, float zfar);
   1.743 
   1.744 
   1.745     static Matrix4f Ortho2D(float w, float h);
   1.746 };
   1.747 
   1.748 
   1.749 //-------------------------------------------------------------------------------------
   1.750 // ***** Quat
   1.751 
   1.752 // Quatf represents a quaternion class used for rotations.
   1.753 // 
   1.754 // Quaternion multiplications are done in right-to-left order, to match the
   1.755 // behavior of matrices.
   1.756 
   1.757 
   1.758 template<class T>
   1.759 class Quat
   1.760 {
   1.761 public:
   1.762     // w + Xi + Yj + Zk
   1.763     T x, y, z, w;    
   1.764 
   1.765     Quat() : x(0), y(0), z(0), w(1) {}
   1.766     Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) {}
   1.767 
   1.768 
   1.769     // Constructs rotation quaternion around the axis.
   1.770     Quat(const Vector3<T>& axis, T angle)
   1.771     {
   1.772         Vector3<T> unitAxis = axis.Normalized();
   1.773         T          sinHalfAngle = sin(angle * T(0.5));
   1.774 
   1.775         w = cos(angle * T(0.5));
   1.776         x = unitAxis.x * sinHalfAngle;
   1.777         y = unitAxis.y * sinHalfAngle;
   1.778         z = unitAxis.z * sinHalfAngle;
   1.779     }
   1.780 
   1.781     //AnnaSteve:
   1.782     void AxisAngle(Axis A, T angle, RotateDirection d, HandedSystem s)
   1.783     {
   1.784         T sinHalfAngle = s * d *sin(angle * (T)0.5);
   1.785         T v[3];
   1.786         v[0] = v[1] = v[2] = (T)0;
   1.787         v[A] = sinHalfAngle;
   1.788         //return Quat(v[0], v[1], v[2], cos(angle * (T)0.5));
   1.789         w = cos(angle * (T)0.5);
   1.790         x = v[0];
   1.791         y = v[1];
   1.792         z = v[2];
   1.793     }
   1.794 
   1.795 
   1.796     void GetAxisAngle(Vector3<T>* axis, T* angle) const
   1.797     {
   1.798         if (LengthSq() > Math<T>::Tolerance * Math<T>::Tolerance)
   1.799         {
   1.800             *axis  = Vector3<T>(x, y, z).Normalized();
   1.801             *angle = 2 * acos(w);
   1.802         }
   1.803         else
   1.804         {
   1.805             *axis = Vector3<T>(1, 0, 0);
   1.806             *angle= 0;
   1.807         }
   1.808     }
   1.809 
   1.810     bool operator== (const Quat& b) const   { return x == b.x && y == b.y && z == b.z && w == b.w; }
   1.811     bool operator!= (const Quat& b) const   { return x != b.x || y != b.y || z != b.z || w != b.w; }
   1.812 
   1.813     Quat  operator+  (const Quat& b) const  { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); }
   1.814     Quat& operator+= (const Quat& b)        { w += b.w; x += b.x; y += b.y; z += b.z; return *this; }
   1.815     Quat  operator-  (const Quat& b) const  { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); }
   1.816     Quat& operator-= (const Quat& b)        { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; }
   1.817 
   1.818     Quat  operator*  (T s) const            { return Quat(x * s, y * s, z * s, w * s); }
   1.819     Quat& operator*= (T s)                  { w *= s; x *= s; y *= s; z *= s; return *this; }
   1.820     Quat  operator/  (T s) const            { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); }
   1.821     Quat& operator/= (T s)                  { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; }
   1.822 
   1.823     // Get Imaginary part vector
   1.824     Vector3<T> Imag() const                 { return Vector3<T>(x,y,z); }
   1.825 
   1.826     // Get quaternion length.
   1.827     T       Length() const                  { return sqrt(x * x + y * y + z * z + w * w); }
   1.828     // Get quaternion length squared.
   1.829     T       LengthSq() const                { return (x * x + y * y + z * z + w * w); }
   1.830     // Simple Eulidean distance in R^4 (not SLERP distance, but at least respects Haar measure)
   1.831     T       Distance(const Quat& q) const
   1.832     {
   1.833         T d1 = (*this - q).Length();
   1.834         T d2 = (*this + q).Length(); // Antipoldal point check
   1.835         return (d1 < d2) ? d1 : d2;
   1.836     }
   1.837     T       DistanceSq(const Quat& q) const
   1.838     {
   1.839         T d1 = (*this - q).LengthSq();
   1.840         T d2 = (*this + q).LengthSq(); // Antipoldal point check
   1.841         return (d1 < d2) ? d1 : d2;
   1.842     }
   1.843 
   1.844     // Normalize
   1.845     bool    IsNormalized() const            { return fabs(LengthSq() - 1) < Math<T>::Tolerance; }
   1.846     void    Normalize()                     { *this /= Length(); }
   1.847     Quat    Normalized() const              { return *this / Length(); }
   1.848 
   1.849     // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized.
   1.850     Quat    Conj() const                    { return Quat(-x, -y, -z, w); }
   1.851 
   1.852     // AnnaSteve fixed: order of quaternion multiplication
   1.853     // Quaternion multiplication. Combines quaternion rotations, performing the one on the 
   1.854     // right hand side first.
   1.855     Quat  operator* (const Quat& b) const   { return Quat(w * b.x + x * b.w + y * b.z - z * b.y,
   1.856                                                           w * b.y - x * b.z + y * b.w + z * b.x,
   1.857                                                           w * b.z + x * b.y - y * b.x + z * b.w,
   1.858                                                           w * b.w - x * b.x - y * b.y - z * b.z); }
   1.859 
   1.860     // 
   1.861     // this^p normalized; same as rotating by this p times.
   1.862     Quat PowNormalized(T p) const
   1.863     {
   1.864         Vector3<T> v;
   1.865         T          a;
   1.866         GetAxisAngle(&v, &a);
   1.867         return Quat(v, a * p);
   1.868     }
   1.869     
   1.870     // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise,
   1.871     // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. 
   1.872     Vector3<T> Rotate(const Vector3<T>& v) const
   1.873     {
   1.874         return ((*this * Quat<T>(v.x, v.y, v.z, 0)) * Inverted()).Imag();
   1.875     }
   1.876 
   1.877     
   1.878     // Inversed quaternion rotates in the opposite direction.
   1.879     Quat        Inverted() const
   1.880     {
   1.881         return Quat(-x, -y, -z, w);
   1.882     }
   1.883 
   1.884     // Sets this quaternion to the one rotates in the opposite direction.
   1.885     void        Invert()
   1.886     {
   1.887         *this = Quat(-x, -y, -z, w);
   1.888     }
   1.889     
   1.890     // Converting quaternion to matrix.
   1.891     operator Matrix4f() const
   1.892     {
   1.893         T ww = w*w;
   1.894         T xx = x*x;
   1.895         T yy = y*y;
   1.896         T zz = z*z;
   1.897 
   1.898         return Matrix4f(float(ww + xx - yy - zz),  float(T(2) * (x*y - w*z)), float(T(2) * (x*z + w*y)),
   1.899                         float(T(2) * (x*y + w*z)), float(ww - xx + yy - zz),  float(T(2) * (y*z - w*x)),
   1.900                         float(T(2) * (x*z - w*y)), float(T(2) * (y*z + w*x)), float(ww - xx - yy + zz) );
   1.901     }
   1.902 
   1.903     
   1.904     // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of
   1.905     // axis rotations and the specified coordinate system. Right-handed coordinate system
   1.906     // is the default, with CCW rotations while looking in the negative axis direction.
   1.907     // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
   1.908     // rotation a around axis A1
   1.909     // is followed by rotation b around axis A2
   1.910     // is followed by rotation c around axis A3
   1.911     // rotations are CCW or CW (D) in LH or RH coordinate system (S)
   1.912     template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
   1.913     void GetEulerAngles(T *a, T *b, T *c)
   1.914     {
   1.915         OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
   1.916 
   1.917         T Q[3] = { x, y, z };  //Quaternion components x,y,z
   1.918 
   1.919         T ww  = w*w;
   1.920         T Q11 = Q[A1]*Q[A1];
   1.921         T Q22 = Q[A2]*Q[A2];
   1.922         T Q33 = Q[A3]*Q[A3];
   1.923 
   1.924         T psign = T(-1.0);
   1.925         // Determine whether even permutation
   1.926         if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3))
   1.927             psign = T(1.0);
   1.928         
   1.929         T s2 = psign * T(2.0) * (psign*w*Q[A2] + Q[A1]*Q[A3]);
   1.930 
   1.931         if (s2 < (T)-1.0 + Math<T>::SingularityRadius)
   1.932         { // South pole singularity
   1.933             *a = T(0.0);
   1.934             *b = -S*D*Math<T>::PiOver2;
   1.935             *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]),
   1.936 		                   ww + Q22 - Q11 - Q33 );
   1.937         }
   1.938         else if (s2 > (T)1.0 - Math<T>::SingularityRadius)
   1.939         {  // North pole singularity
   1.940             *a = (T)0.0;
   1.941             *b = S*D*Math<T>::PiOver2;
   1.942             *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]),
   1.943 		                   ww + Q22 - Q11 - Q33);
   1.944         }
   1.945         else
   1.946         {
   1.947             *a = -S*D*atan2((T)-2.0*(w*Q[A1] - psign*Q[A2]*Q[A3]),
   1.948 		                    ww + Q33 - Q11 - Q22);
   1.949             *b = S*D*asin(s2);
   1.950             *c = S*D*atan2((T)2.0*(w*Q[A3] - psign*Q[A1]*Q[A2]),
   1.951 		                   ww + Q11 - Q22 - Q33);
   1.952         }      
   1.953         return;
   1.954     }
   1.955 
   1.956     template <Axis A1, Axis A2, Axis A3, RotateDirection D>
   1.957     void GetEulerAngles(T *a, T *b, T *c)
   1.958     { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); }
   1.959 
   1.960     template <Axis A1, Axis A2, Axis A3>
   1.961     void GetEulerAngles(T *a, T *b, T *c)
   1.962     { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); }
   1.963 
   1.964 
   1.965     // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of
   1.966     // axis rotations and the specified coordinate system. Right-handed coordinate system
   1.967     // is the default, with CCW rotations while looking in the negative axis direction.
   1.968     // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
   1.969     // rotation a around axis A1
   1.970     // is followed by rotation b around axis A2
   1.971     // is followed by rotation c around axis A1
   1.972     // Rotations are CCW or CW (D) in LH or RH coordinate system (S)
   1.973     template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
   1.974     void GetEulerAnglesABA(T *a, T *b, T *c)
   1.975     {
   1.976         OVR_COMPILER_ASSERT(A1 != A2);
   1.977 
   1.978         T Q[3] = {x, y, z}; // Quaternion components
   1.979 
   1.980         // Determine the missing axis that was not supplied
   1.981         int m = 3 - A1 - A2;
   1.982 
   1.983         T ww = w*w;
   1.984         T Q11 = Q[A1]*Q[A1];
   1.985         T Q22 = Q[A2]*Q[A2];
   1.986         T Qmm = Q[m]*Q[m];
   1.987 
   1.988         T psign = T(-1.0);
   1.989         if ((A1 + 1) % 3 == A2) // Determine whether even permutation
   1.990         {
   1.991             psign = (T)1.0;
   1.992         }
   1.993 
   1.994         T c2 = ww + Q11 - Q22 - Qmm;
   1.995         if (c2 < (T)-1.0 + Math<T>::SingularityRadius)
   1.996         { // South pole singularity
   1.997             *a = (T)0.0;
   1.998             *b = S*D*Math<T>::Pi;
   1.999             *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]),
  1.1000 		                    ww + Q22 - Q11 - Qmm);
  1.1001         }
  1.1002         else if (c2 > (T)1.0 - Math<T>::SingularityRadius)
  1.1003         {  // North pole singularity
  1.1004             *a = (T)0.0;
  1.1005             *b = (T)0.0;
  1.1006             *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]),
  1.1007 		                   ww + Q22 - Q11 - Qmm);
  1.1008         }
  1.1009         else
  1.1010         {
  1.1011             *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2],
  1.1012 		                   w*Q[A2] -psign*Q[A1]*Q[m]);
  1.1013             *b = S*D*acos(c2);
  1.1014             *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2],
  1.1015 		                   w*Q[A2] + psign*Q[A1]*Q[m]);
  1.1016         }
  1.1017         return;
  1.1018     }
  1.1019 };
  1.1020 
  1.1021 
  1.1022 typedef Quat<float>  Quatf;
  1.1023 typedef Quat<double> Quatd;
  1.1024 
  1.1025 
  1.1026 
  1.1027 //-------------------------------------------------------------------------------------
  1.1028 // ***** Angle
  1.1029 
  1.1030 // Cleanly representing the algebra of 2D rotations.
  1.1031 // The operations maintain the angle between -Pi and Pi, the same range as atan2.
  1.1032 // 
  1.1033 
  1.1034 template<class T>
  1.1035 class Angle
  1.1036 {
  1.1037 public:
  1.1038 	enum AngularUnits
  1.1039 	{
  1.1040 		Radians = 0,
  1.1041 		Degrees = 1
  1.1042 	};
  1.1043 
  1.1044     Angle() : a(0) {}
  1.1045     
  1.1046 	// Fix the range to be between -Pi and Pi
  1.1047 	Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math<T>::DegreeToRadFactor) { FixRange(); }
  1.1048 
  1.1049 	T    Get(AngularUnits u = Radians) const       { return (u == Radians) ? a : a*Math<T>::RadToDegreeFactor; }
  1.1050 	void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math<T>::DegreeToRadFactor; FixRange(); }
  1.1051 	int Sign() const                               { if (a == 0) return 0; else return (a > 0) ? 1 : -1; }
  1.1052 	T   Abs() const                                { return (a > 0) ? a : -a; }
  1.1053 
  1.1054     bool operator== (const Angle& b) const    { return a == b.a; }
  1.1055     bool operator!= (const Angle& b) const    { return a != b.a; }
  1.1056 //	bool operator<  (const Angle& b) const    { return a < a.b; } 
  1.1057 //	bool operator>  (const Angle& b) const    { return a > a.b; } 
  1.1058 //	bool operator<= (const Angle& b) const    { return a <= a.b; } 
  1.1059 //	bool operator>= (const Angle& b) const    { return a >= a.b; } 
  1.1060 //	bool operator= (const T& x)               { a = x; FixRange(); }
  1.1061 
  1.1062 	// These operations assume a is already between -Pi and Pi.
  1.1063     Angle  operator+  (const Angle& b) const  { return Angle(a + b.a); }
  1.1064 	Angle  operator+  (const T& x) const      { return Angle(a + x); }
  1.1065 	Angle& operator+= (const Angle& b)        { a = a + b.a; FastFixRange(); return *this; }
  1.1066 	Angle& operator+= (const T& x)            { a = a + x; FixRange(); return *this; }
  1.1067 	Angle  operator-  (const Angle& b) const  { return Angle(a - b.a); }
  1.1068 	Angle  operator-  (const T& x) const      { return Angle(a - x); }
  1.1069 	Angle& operator-= (const Angle& b)        { a = a - b.a; FastFixRange(); return *this; }
  1.1070 	Angle& operator-= (const T& x)            { a = a - x; FixRange(); return *this; }
  1.1071 	
  1.1072 	T   Distance(const Angle& b)              { T c = fabs(a - b.a); return (c <= Math<T>::Pi) ? c : Math<T>::TwoPi - c; }
  1.1073 
  1.1074 private:
  1.1075 
  1.1076 	// The stored angle, which should be maintained between -Pi and Pi
  1.1077 	T a;
  1.1078 
  1.1079 	// Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side 
  1.1080 	inline void FastFixRange()
  1.1081 	{
  1.1082 		if (a < -Math<T>::Pi)
  1.1083 			a += Math<T>::TwoPi;
  1.1084 		else if (a > Math<T>::Pi)
  1.1085 			a -= Math<T>::TwoPi;
  1.1086 	}
  1.1087 
  1.1088 	// Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method
  1.1089 	inline void FixRange()
  1.1090 	{
  1.1091 		a = fmod(a,Math<T>::TwoPi);
  1.1092 		if (a < -Math<T>::Pi)
  1.1093 			a += Math<T>::TwoPi;
  1.1094 		else if (a > Math<T>::Pi)
  1.1095 			a -= Math<T>::TwoPi;
  1.1096 	}
  1.1097 };
  1.1098 
  1.1099 
  1.1100 typedef Angle<float>  Anglef;
  1.1101 typedef Angle<double> Angled;
  1.1102 
  1.1103 
  1.1104 //-------------------------------------------------------------------------------------
  1.1105 // ***** Plane
  1.1106 
  1.1107 // Consists of a normal vector and distance from the origin where the plane is located.
  1.1108 
  1.1109 template<class T>
  1.1110 class Plane : public RefCountBase<Plane<T> >
  1.1111 {
  1.1112 public:
  1.1113     Vector3<T> N;
  1.1114     T          D;
  1.1115 
  1.1116     Plane() : D(0) {}
  1.1117 
  1.1118     // Normals must already be normalized
  1.1119     Plane(const Vector3<T>& n, T d) : N(n), D(d) {}
  1.1120     Plane(T x, T y, T z, T d) : N(x,y,z), D(d) {}
  1.1121 
  1.1122     // construct from a point on the plane and the normal
  1.1123     Plane(const Vector3<T>& p, const Vector3<T>& n) : N(n), D(-(p * n)) {}
  1.1124 
  1.1125     // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane).
  1.1126     T TestSide(const Vector3<T>& p) const
  1.1127     {
  1.1128         return (N * p) + D;
  1.1129     }
  1.1130 
  1.1131     Plane<T> Flipped() const
  1.1132     {
  1.1133         return Plane(-N, -D);
  1.1134     }
  1.1135 
  1.1136     void Flip()
  1.1137     {
  1.1138         N = -N;
  1.1139         D = -D;
  1.1140     }
  1.1141 
  1.1142 	bool operator==(const Plane<T>& rhs) const
  1.1143 	{
  1.1144 		return (this->D == rhs.D && this->N == rhs.N);
  1.1145 	}
  1.1146 };
  1.1147 
  1.1148 typedef Plane<float> Planef;
  1.1149 
  1.1150 }
  1.1151 
  1.1152 #endif
  1.1153 \ No newline at end of file