Main Page | Class Hierarchy | Class List | Directories | File List | Class Members

ArcBall.h

00001 
00018 /*************************************************************/
00019 
00020 #ifndef _ArcBall_h
00021 #define _ArcBall_h
00022 
00023 #include <math.h>
00024 
00025 // 8<--Snip here if you have your own math types/funcs-->8 
00026 
00027 //Only support assertions in debug builds
00028 #ifdef _DEBUG
00029 # include "assert.h"
00030 #else
00031 # define assert(x) { }
00032 #endif
00033 
00034 //Math types derived from the KempoApi tMath library
00035     typedef union Tuple2f_t
00036     {
00037         struct
00038         {
00039             GLfloat X, Y;
00040         } s;
00041 
00042         GLfloat T[2];
00043     } Tuple2fT;      //A generic 2-element tuple that is represented by single-precision floating point x,y coordinates. 
00044 
00045     typedef union Tuple3f_t
00046     {
00047         struct
00048         {
00049             GLfloat X, Y, Z;
00050         } s;
00051 
00052         GLfloat T[3];
00053     } Tuple3fT;      //A generic 3-element tuple that is represented by single precision-floating point x,y,z coordinates. 
00054 
00055     typedef union Tuple4f_t
00056     {
00057         struct
00058         {
00059             GLfloat X, Y, Z, W;
00060         } s;
00061 
00062         GLfloat T[4];
00063     } Tuple4fT;      //A 4-element tuple represented by single-precision floating point x,y,z,w coordinates. 
00064 
00065     typedef union Matrix3f_t
00066     {
00067             struct
00068             {
00069                 //column major
00070                 union { GLfloat M00; GLfloat XX; GLfloat SX; };  //XAxis.X and Scale X
00071                 union { GLfloat M10; GLfloat XY;             };  //XAxis.Y
00072                 union { GLfloat M20; GLfloat XZ;             };  //XAxis.Z
00073                 union { GLfloat M01; GLfloat YX;             };  //YAxis.X
00074                 union { GLfloat M11; GLfloat YY; GLfloat SY; };  //YAxis.Y and Scale Y
00075                 union { GLfloat M21; GLfloat YZ;             };  //YAxis.Z
00076                 union { GLfloat M02; GLfloat ZX;             };  //ZAxis.X
00077                 union { GLfloat M12; GLfloat ZY;             };  //ZAxis.Y
00078                 union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };  //ZAxis.Z and Scale Z
00079             } s;
00080             GLfloat M[9];
00081     } Matrix3fT;     //A single precision floating point 3 by 3 matrix. 
00082 
00083     typedef union Matrix4f_t
00084     {
00085             struct
00086             {
00087                 //column major
00088                 union { GLfloat M00; GLfloat XX; GLfloat SX; };  //XAxis.X and Scale X
00089                 union { GLfloat M10; GLfloat XY;             };  //XAxis.Y
00090                 union { GLfloat M20; GLfloat XZ;             };  //XAxis.Z
00091                 union { GLfloat M30; GLfloat XW;             };  //XAxis.W
00092                 union { GLfloat M01; GLfloat YX;             };  //YAxis.X
00093                 union { GLfloat M11; GLfloat YY; GLfloat SY; };  //YAxis.Y and Scale Y
00094                 union { GLfloat M21; GLfloat YZ;             };  //YAxis.Z
00095                 union { GLfloat M31; GLfloat YW;             };  //YAxis.W
00096                 union { GLfloat M02; GLfloat ZX;             };  //ZAxis.X
00097                 union { GLfloat M12; GLfloat ZY;             };  //ZAxis.Y
00098                 union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };  //ZAxis.Z and Scale Z
00099                 union { GLfloat M32; GLfloat ZW;             };  //ZAxis.W
00100                 union { GLfloat M03; GLfloat TX;             };  //Trans.X
00101                 union { GLfloat M13; GLfloat TY;             };  //Trans.Y
00102                 union { GLfloat M23; GLfloat TZ;             };  //Trans.Z
00103                 union { GLfloat M33; GLfloat TW; GLfloat SW; };  //Trans.W and Scale W
00104             } s;
00105             GLfloat M[16];
00106     } Matrix4fT;     //A single precision floating point 4 by 4 matrix. 
00107 
00108 
00109 //"Inherited" types
00110 #define Point2fT    Tuple2fT   //A 2 element point that is represented by single precision floating point x,y coordinates. 
00111 
00112 #define Quat4fT     Tuple4fT   //A 4 element unit quaternion represented by single precision floating point x,y,z,w coordinates. 
00113 
00114 #define Vector2fT   Tuple2fT   //A 2-element vector that is represented by single-precision floating point x,y coordinates. 
00115 #define Vector3fT   Tuple3fT   //A 3-element vector that is represented by single-precision floating point x,y,z coordinates. 
00116 
00117 //Custom math, or speed overrides
00118 #define FuncSqrt    sqrtf
00119 
00120 //utility macros
00121 //assuming IEEE-754(GLfloat), which i believe has max precision of 7 bits
00122 # define Epsilon 1.0e-5
00123 
00124 //Math functions
00125 
00130     inline
00131     static void Point2fAdd(Point2fT* NewObj, const Tuple2fT* t1)
00132     {
00133         assert(NewObj && t1);
00134 
00135         NewObj->s.X += t1->s.X;
00136         NewObj->s.Y += t1->s.Y;
00137     }
00138 
00143     inline
00144     static void Point2fSub(Point2fT* NewObj, const Tuple2fT* t1)
00145     {
00146         assert(NewObj && t1);
00147 
00148         NewObj->s.X -= t1->s.X;
00149         NewObj->s.Y -= t1->s.Y;
00150     }
00151 
00157     inline
00158     static void Vector3fCross(Vector3fT* NewObj, const Vector3fT* v1, const Vector3fT* v2)
00159     {
00160         Vector3fT Result; //safe not to initialize
00161 
00162         assert(NewObj && v1 && v2);
00163 
00164         // store on stack once for aliasing-safty
00165         // i.e. safe when a.cross(a, b)
00166 
00167         Result.s.X = (v1->s.Y * v2->s.Z) - (v1->s.Z * v2->s.Y);
00168         Result.s.Y = (v1->s.Z * v2->s.X) - (v1->s.X * v2->s.Z);
00169         Result.s.Z = (v1->s.X * v2->s.Y) - (v1->s.Y * v2->s.X);
00170 
00171         //copy result back
00172         *NewObj = Result;
00173     }
00174 
00179     inline
00180     static GLfloat Vector3fDot(const Vector3fT* NewObj, const Vector3fT* v1)
00181     {
00182         assert(NewObj && v1);
00183 
00184         return  (NewObj->s.X * v1->s.X) +
00185                 (NewObj->s.Y * v1->s.Y) +
00186                 (NewObj->s.Z * v1->s.Z);
00187     }
00188 
00193     inline
00194     static GLfloat Vector3fLengthSquared(const Vector3fT* NewObj)
00195     {
00196         assert(NewObj);
00197 
00198         return  (NewObj->s.X * NewObj->s.X) +
00199                 (NewObj->s.Y * NewObj->s.Y) +
00200                 (NewObj->s.Z * NewObj->s.Z);
00201     }
00202 
00207     inline
00208     static GLfloat Vector3fLength(const Vector3fT* NewObj)
00209     {
00210         assert(NewObj);
00211 
00212         return FuncSqrt(Vector3fLengthSquared(NewObj));
00213     }
00214 
00215     inline
00216     static void Matrix3fSetZero(Matrix3fT* NewObj)
00217     {
00218         NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 = 
00219         NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 = 
00220         NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 0.0f;
00221     }
00222 
00226     inline
00227     static void Matrix3fSetIdentity(Matrix3fT* NewObj)
00228     {
00229         Matrix3fSetZero(NewObj);
00230 
00231         //then set diagonal as 1
00232         NewObj->s.M00 = 
00233         NewObj->s.M11 = 
00234         NewObj->s.M22 = 1.0f;
00235     }
00236 
00242     //$hack this can be optimized some(if s == 0)
00243     inline
00244     static void Matrix3fSetRotationFromQuat4f(Matrix3fT* NewObj, const Quat4fT* q1)
00245     {
00246         GLfloat n, s;
00247         GLfloat xs, ys, zs;
00248         GLfloat wx, wy, wz;
00249         GLfloat xx, xy, xz;
00250         GLfloat yy, yz, zz;
00251 
00252         assert(NewObj && q1);
00253 
00254         n = (q1->s.X * q1->s.X) + (q1->s.Y * q1->s.Y) + (q1->s.Z * q1->s.Z) + (q1->s.W * q1->s.W);
00255         s = (n > 0.0f) ? (2.0f / n) : 0.0f;
00256 
00257         xs = q1->s.X * s;  ys = q1->s.Y * s;  zs = q1->s.Z * s;
00258         wx = q1->s.W * xs; wy = q1->s.W * ys; wz = q1->s.W * zs;
00259         xx = q1->s.X * xs; xy = q1->s.X * ys; xz = q1->s.X * zs;
00260         yy = q1->s.Y * ys; yz = q1->s.Y * zs; zz = q1->s.Z * zs;
00261 
00262         NewObj->s.XX = 1.0f - (yy + zz); NewObj->s.YX =         xy - wz;  NewObj->s.ZX =         xz + wy;
00263         NewObj->s.XY =         xy + wz;  NewObj->s.YY = 1.0f - (xx + zz); NewObj->s.ZY =         yz - wx;
00264         NewObj->s.XZ =         xz - wy;  NewObj->s.YZ =         yz + wx;  NewObj->s.ZZ = 1.0f - (xx + yy);
00265     }
00266 
00272     inline
00273     static void Matrix3fMulMatrix3f(Matrix3fT* NewObj, const Matrix3fT* m1)
00274     {
00275         Matrix3fT Result; //safe not to initialize
00276 
00277         assert(NewObj && m1);
00278 
00279         // alias-safe way.
00280         Result.s.M00 = (NewObj->s.M00 * m1->s.M00) + (NewObj->s.M01 * m1->s.M10) + (NewObj->s.M02 * m1->s.M20);
00281         Result.s.M01 = (NewObj->s.M00 * m1->s.M01) + (NewObj->s.M01 * m1->s.M11) + (NewObj->s.M02 * m1->s.M21);
00282         Result.s.M02 = (NewObj->s.M00 * m1->s.M02) + (NewObj->s.M01 * m1->s.M12) + (NewObj->s.M02 * m1->s.M22);
00283 
00284         Result.s.M10 = (NewObj->s.M10 * m1->s.M00) + (NewObj->s.M11 * m1->s.M10) + (NewObj->s.M12 * m1->s.M20);
00285         Result.s.M11 = (NewObj->s.M10 * m1->s.M01) + (NewObj->s.M11 * m1->s.M11) + (NewObj->s.M12 * m1->s.M21);
00286         Result.s.M12 = (NewObj->s.M10 * m1->s.M02) + (NewObj->s.M11 * m1->s.M12) + (NewObj->s.M12 * m1->s.M22);
00287 
00288         Result.s.M20 = (NewObj->s.M20 * m1->s.M00) + (NewObj->s.M21 * m1->s.M10) + (NewObj->s.M22 * m1->s.M20);
00289         Result.s.M21 = (NewObj->s.M20 * m1->s.M01) + (NewObj->s.M21 * m1->s.M11) + (NewObj->s.M22 * m1->s.M21);
00290         Result.s.M22 = (NewObj->s.M20 * m1->s.M02) + (NewObj->s.M21 * m1->s.M12) + (NewObj->s.M22 * m1->s.M22);
00291 
00292         //copy result back to this
00293         *NewObj = Result;
00294     }
00295 
00296     inline
00297     static void Matrix4fSetRotationScaleFromMatrix4f(Matrix4fT* NewObj, const Matrix4fT* m1)
00298     {
00299         assert(NewObj && m1);
00300 
00301         NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;
00302         NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;
00303         NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;
00304     }
00305 
00313     inline
00314     static GLfloat Matrix4fSVD(const Matrix4fT* NewObj, Matrix3fT* rot3, Matrix4fT* rot4)
00315     {
00316         GLfloat s, n;
00317 
00318         assert(NewObj);
00319 
00320         // this is a simple svd.
00321         // Not complete but fast and reasonable.
00322         // See comment in Matrix3d.
00323 
00324         s = FuncSqrt(
00325                 ( (NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ) + 
00326                   (NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ) +
00327                   (NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ) ) / 3.0f );
00328 
00329         if (rot3)   //if pointer not null
00330         {
00331             //this->getRotationScale(rot3);
00332             rot3->s.XX = NewObj->s.XX; rot3->s.XY = NewObj->s.XY; rot3->s.XZ = NewObj->s.XZ;
00333             rot3->s.YX = NewObj->s.YX; rot3->s.YY = NewObj->s.YY; rot3->s.YZ = NewObj->s.YZ;
00334             rot3->s.ZX = NewObj->s.ZX; rot3->s.ZY = NewObj->s.ZY; rot3->s.ZZ = NewObj->s.ZZ;
00335 
00336             // zero-div may occur.
00337 
00338             n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +
00339                                       (NewObj->s.XY * NewObj->s.XY) +
00340                                       (NewObj->s.XZ * NewObj->s.XZ) );
00341             rot3->s.XX *= n;
00342             rot3->s.XY *= n;
00343             rot3->s.XZ *= n;
00344 
00345             n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +
00346                                       (NewObj->s.YY * NewObj->s.YY) +
00347                                       (NewObj->s.YZ * NewObj->s.YZ) );
00348             rot3->s.YX *= n;
00349             rot3->s.YY *= n;
00350             rot3->s.YZ *= n;
00351 
00352             n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +
00353                                       (NewObj->s.ZY * NewObj->s.ZY) +
00354                                       (NewObj->s.ZZ * NewObj->s.ZZ) );
00355             rot3->s.ZX *= n;
00356             rot3->s.ZY *= n;
00357             rot3->s.ZZ *= n;
00358         }
00359 
00360         if (rot4)   //if pointer not null
00361         {
00362             if (rot4 != NewObj)
00363             {
00364                 Matrix4fSetRotationScaleFromMatrix4f(rot4, NewObj);  // private method
00365             }
00366 
00367             // zero-div may occur.
00368 
00369             n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +
00370                                       (NewObj->s.XY * NewObj->s.XY) +
00371                                       (NewObj->s.XZ * NewObj->s.XZ) );
00372             rot4->s.XX *= n;
00373             rot4->s.XY *= n;
00374             rot4->s.XZ *= n;
00375 
00376             n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +
00377                                       (NewObj->s.YY * NewObj->s.YY) +
00378                                       (NewObj->s.YZ * NewObj->s.YZ) );
00379             rot4->s.YX *= n;
00380             rot4->s.YY *= n;
00381             rot4->s.YZ *= n;
00382 
00383             n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +
00384                                       (NewObj->s.ZY * NewObj->s.ZY) +
00385                                       (NewObj->s.ZZ * NewObj->s.ZZ) );
00386             rot4->s.ZX *= n;
00387             rot4->s.ZY *= n;
00388             rot4->s.ZZ *= n;
00389         }
00390 
00391         return s;
00392     }
00393 
00394     inline
00395     static void Matrix4fSetRotationScaleFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)
00396     {
00397         assert(NewObj && m1);
00398 
00399         NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;
00400         NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;
00401         NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;
00402     }
00403 
00404     inline
00405     static void Matrix4fMulRotationScale(Matrix4fT* NewObj, GLfloat scale)
00406     {
00407         assert(NewObj);
00408 
00409         NewObj->s.XX *= scale; NewObj->s.YX *= scale; NewObj->s.ZX *= scale;
00410         NewObj->s.XY *= scale; NewObj->s.YY *= scale; NewObj->s.ZY *= scale;
00411         NewObj->s.XZ *= scale; NewObj->s.YZ *= scale; NewObj->s.ZZ *= scale;
00412     }
00413 
00424     inline
00425     static void Matrix4fSetRotationFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)
00426     {
00427         GLfloat scale;
00428 
00429         assert(NewObj && m1);
00430 
00431         scale = Matrix4fSVD(NewObj, NULL, NULL);
00432 
00433         Matrix4fSetRotationScaleFromMatrix3f(NewObj, m1);
00434         Matrix4fMulRotationScale(NewObj, scale);
00435     }
00436 
00437 // 8<--Snip here if you have your own math types/funcs-->8 
00438 
00439     typedef class ArcBall_t
00440     {
00441         protected:
00442             inline
00443             void _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const;
00444 
00445         public:
00446             //Create/Destroy
00447                     ArcBall_t(GLfloat NewWidth, GLfloat NewHeight);
00448                    ~ArcBall_t() { /* nothing to do */ };
00449 
00450             //Set new bounds
00451             inline
00452             void    setBounds(GLfloat NewWidth, GLfloat NewHeight)
00453             {
00454                 assert((NewWidth > 1.0f) && (NewHeight > 1.0f));
00455 
00456                 //Set adjustment factor for width/height
00457                 this->AdjustWidth  = 1.0f / ((NewWidth  - 1.0f) * 0.5f);
00458                 this->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
00459             }
00460             
00461 
00462             //Mouse down
00463             void    click(const Point2fT* NewPt);
00464 
00465             //Mouse drag, calculate rotation
00466             void    drag(const Point2fT* NewPt, Quat4fT* NewRot);
00467 
00468 
00469 
00470         protected:
00471             Vector3fT   StVec;          //Saved click vector
00472             Vector3fT   EnVec;          //Saved drag vector
00473             GLfloat     AdjustWidth;    //Mouse bounds width
00474             GLfloat     AdjustHeight;   //Mouse bounds height
00475 
00476     } ArcBallT;
00477 
00478 #endif
00479 

Generated on Mon Dec 12 15:20:26 2005 for CCube by  doxygen 1.4.1