00001
00018
00019
00020 #ifndef _ArcBall_h
00021 #define _ArcBall_h
00022
00023 #include <math.h>
00024
00025
00026
00027
00028 #ifdef _DEBUG
00029 # include "assert.h"
00030 #else
00031 # define assert(x) { }
00032 #endif
00033
00034
00035 typedef union Tuple2f_t
00036 {
00037 struct
00038 {
00039 GLfloat X, Y;
00040 } s;
00041
00042 GLfloat T[2];
00043 } Tuple2fT;
00044
00045 typedef union Tuple3f_t
00046 {
00047 struct
00048 {
00049 GLfloat X, Y, Z;
00050 } s;
00051
00052 GLfloat T[3];
00053 } Tuple3fT;
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;
00064
00065 typedef union Matrix3f_t
00066 {
00067 struct
00068 {
00069
00070 union { GLfloat M00; GLfloat XX; GLfloat SX; };
00071 union { GLfloat M10; GLfloat XY; };
00072 union { GLfloat M20; GLfloat XZ; };
00073 union { GLfloat M01; GLfloat YX; };
00074 union { GLfloat M11; GLfloat YY; GLfloat SY; };
00075 union { GLfloat M21; GLfloat YZ; };
00076 union { GLfloat M02; GLfloat ZX; };
00077 union { GLfloat M12; GLfloat ZY; };
00078 union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };
00079 } s;
00080 GLfloat M[9];
00081 } Matrix3fT;
00082
00083 typedef union Matrix4f_t
00084 {
00085 struct
00086 {
00087
00088 union { GLfloat M00; GLfloat XX; GLfloat SX; };
00089 union { GLfloat M10; GLfloat XY; };
00090 union { GLfloat M20; GLfloat XZ; };
00091 union { GLfloat M30; GLfloat XW; };
00092 union { GLfloat M01; GLfloat YX; };
00093 union { GLfloat M11; GLfloat YY; GLfloat SY; };
00094 union { GLfloat M21; GLfloat YZ; };
00095 union { GLfloat M31; GLfloat YW; };
00096 union { GLfloat M02; GLfloat ZX; };
00097 union { GLfloat M12; GLfloat ZY; };
00098 union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };
00099 union { GLfloat M32; GLfloat ZW; };
00100 union { GLfloat M03; GLfloat TX; };
00101 union { GLfloat M13; GLfloat TY; };
00102 union { GLfloat M23; GLfloat TZ; };
00103 union { GLfloat M33; GLfloat TW; GLfloat SW; };
00104 } s;
00105 GLfloat M[16];
00106 } Matrix4fT;
00107
00108
00109
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
00118 #define FuncSqrt sqrtf
00119
00120
00121
00122 # define Epsilon 1.0e-5
00123
00124
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;
00161
00162 assert(NewObj && v1 && v2);
00163
00164
00165
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
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
00232 NewObj->s.M00 =
00233 NewObj->s.M11 =
00234 NewObj->s.M22 = 1.0f;
00235 }
00236
00242
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;
00276
00277 assert(NewObj && m1);
00278
00279
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
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
00321
00322
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)
00330 {
00331
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
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)
00361 {
00362 if (rot4 != NewObj)
00363 {
00364 Matrix4fSetRotationScaleFromMatrix4f(rot4, NewObj);
00365 }
00366
00367
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
00438
00439 typedef class ArcBall_t
00440 {
00441 protected:
00442 inline
00443 void _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const;
00444
00445 public:
00446
00447 ArcBall_t(GLfloat NewWidth, GLfloat NewHeight);
00448 ~ArcBall_t() { };
00449
00450
00451 inline
00452 void setBounds(GLfloat NewWidth, GLfloat NewHeight)
00453 {
00454 assert((NewWidth > 1.0f) && (NewHeight > 1.0f));
00455
00456
00457 this->AdjustWidth = 1.0f / ((NewWidth - 1.0f) * 0.5f);
00458 this->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
00459 }
00460
00461
00462
00463 void click(const Point2fT* NewPt);
00464
00465
00466 void drag(const Point2fT* NewPt, Quat4fT* NewRot);
00467
00468
00469
00470 protected:
00471 Vector3fT StVec;
00472 Vector3fT EnVec;
00473 GLfloat AdjustWidth;
00474 GLfloat AdjustHeight;
00475
00476 } ArcBallT;
00477
00478 #endif
00479