00001
00018
00019
00020 #ifndef _ArcBall_h
00021 #define _ArcBall_h
00022 #include <stdlib.h>
00023
00024
00025
00026 #ifdef _DEBUG
00027 # include "assert.h"
00028 #else
00029 # define assert(x) { }
00030 #endif
00031
00032
00033 typedef union Tuple2f_t
00034 {
00035 struct
00036 {
00037 GLfloat X, Y;
00038 } s;
00039
00040 GLfloat T[2];
00041 } Tuple2fT;
00042
00043 typedef union Tuple3f_t
00044 {
00045 struct
00046 {
00047 GLfloat X, Y, Z;
00048 } s;
00049
00050 GLfloat T[3];
00051 } Tuple3fT;
00052
00053 typedef union Tuple4f_t
00054 {
00055 struct
00056 {
00057 GLfloat X, Y, Z, W;
00058 } s;
00059
00060 GLfloat T[4];
00061 } Tuple4fT;
00062
00063 typedef union Matrix3f_t
00064 {
00065 struct
00066 {
00067
00068 union { GLfloat M00; GLfloat XX; GLfloat SX; };
00069 union { GLfloat M10; GLfloat XY; };
00070 union { GLfloat M20; GLfloat XZ; };
00071 union { GLfloat M01; GLfloat YX; };
00072 union { GLfloat M11; GLfloat YY; GLfloat SY; };
00073 union { GLfloat M21; GLfloat YZ; };
00074 union { GLfloat M02; GLfloat ZX; };
00075 union { GLfloat M12; GLfloat ZY; };
00076 union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };
00077 } s;
00078 GLfloat M[9];
00079 } Matrix3fT;
00080
00081 typedef union Matrix4f_t
00082 {
00083 struct
00084 {
00085
00086 union { GLfloat M00; GLfloat XX; GLfloat SX; };
00087 union { GLfloat M10; GLfloat XY; };
00088 union { GLfloat M20; GLfloat XZ; };
00089 union { GLfloat M30; GLfloat XW; };
00090 union { GLfloat M01; GLfloat YX; };
00091 union { GLfloat M11; GLfloat YY; GLfloat SY; };
00092 union { GLfloat M21; GLfloat YZ; };
00093 union { GLfloat M31; GLfloat YW; };
00094 union { GLfloat M02; GLfloat ZX; };
00095 union { GLfloat M12; GLfloat ZY; };
00096 union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };
00097 union { GLfloat M32; GLfloat ZW; };
00098 union { GLfloat M03; GLfloat TX; };
00099 union { GLfloat M13; GLfloat TY; };
00100 union { GLfloat M23; GLfloat TZ; };
00101 union { GLfloat M33; GLfloat TW; GLfloat SW; };
00102 } s;
00103 GLfloat M[16];
00104 } Matrix4fT;
00105
00106
00107
00108 #define Point2fT Tuple2fT //A 2 element point that is represented by single precision floating point x,y coordinates.
00109
00110 #define Quat4fT Tuple4fT //A 4 element unit quaternion represented by single precision floating point x,y,z,w coordinates.
00111
00112 #define Vector2fT Tuple2fT //A 2-element vector that is represented by single-precision floating point x,y coordinates.
00113 #define Vector3fT Tuple3fT //A 3-element vector that is represented by single-precision floating point x,y,z coordinates.
00114
00115
00116 #define FuncSqrt sqrtf
00117
00118
00119
00120 # define Epsilon 1.0e-5
00121
00122
00123
00128 inline
00129 static void Point2fAdd(Point2fT* NewObj, const Tuple2fT* t1)
00130 {
00131 assert(NewObj && t1);
00132
00133 NewObj->s.X += t1->s.X;
00134 NewObj->s.Y += t1->s.Y;
00135 }
00136
00141 inline
00142 static void Point2fSub(Point2fT* NewObj, const Tuple2fT* t1)
00143 {
00144 assert(NewObj && t1);
00145
00146 NewObj->s.X -= t1->s.X;
00147 NewObj->s.Y -= t1->s.Y;
00148 }
00149
00155 inline
00156 static void Vector3fCross(Vector3fT* NewObj, const Vector3fT* v1, const Vector3fT* v2)
00157 {
00158 Vector3fT Result;
00159
00160 assert(NewObj && v1 && v2);
00161
00162
00163
00164
00165 Result.s.X = (v1->s.Y * v2->s.Z) - (v1->s.Z * v2->s.Y);
00166 Result.s.Y = (v1->s.Z * v2->s.X) - (v1->s.X * v2->s.Z);
00167 Result.s.Z = (v1->s.X * v2->s.Y) - (v1->s.Y * v2->s.X);
00168
00169
00170 *NewObj = Result;
00171 }
00172
00177 inline
00178 static GLfloat Vector3fDot(const Vector3fT* NewObj, const Vector3fT* v1)
00179 {
00180 assert(NewObj && v1);
00181
00182 return (NewObj->s.X * v1->s.X) +
00183 (NewObj->s.Y * v1->s.Y) +
00184 (NewObj->s.Z * v1->s.Z);
00185 }
00186
00191 inline
00192 static GLfloat Vector3fLengthSquared(const Vector3fT* NewObj)
00193 {
00194 assert(NewObj);
00195
00196 return (NewObj->s.X * NewObj->s.X) +
00197 (NewObj->s.Y * NewObj->s.Y) +
00198 (NewObj->s.Z * NewObj->s.Z);
00199 }
00200
00205 inline
00206 static GLfloat Vector3fLength(const Vector3fT* NewObj)
00207 {
00208 assert(NewObj);
00209
00210 return FuncSqrt(Vector3fLengthSquared(NewObj));
00211 }
00212
00213 inline
00214 static void Matrix3fSetZero(Matrix3fT* NewObj)
00215 {
00216 NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 =
00217 NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 =
00218 NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 0.0f;
00219 }
00220
00224 inline
00225 static void Matrix3fSetIdentity(Matrix3fT* NewObj)
00226 {
00227 Matrix3fSetZero(NewObj);
00228
00229
00230 NewObj->s.M00 =
00231 NewObj->s.M11 =
00232 NewObj->s.M22 = 1.0f;
00233 }
00234
00240
00241 inline
00242 static void Matrix3fSetRotationFromQuat4f(Matrix3fT* NewObj, const Quat4fT* q1)
00243 {
00244 GLfloat n, s;
00245 GLfloat xs, ys, zs;
00246 GLfloat wx, wy, wz;
00247 GLfloat xx, xy, xz;
00248 GLfloat yy, yz, zz;
00249
00250 assert(NewObj && q1);
00251
00252 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);
00253 s = (n > 0.0f) ? (2.0f / n) : 0.0f;
00254
00255 xs = q1->s.X * s; ys = q1->s.Y * s; zs = q1->s.Z * s;
00256 wx = q1->s.W * xs; wy = q1->s.W * ys; wz = q1->s.W * zs;
00257 xx = q1->s.X * xs; xy = q1->s.X * ys; xz = q1->s.X * zs;
00258 yy = q1->s.Y * ys; yz = q1->s.Y * zs; zz = q1->s.Z * zs;
00259
00260 NewObj->s.XX = 1.0f - (yy + zz); NewObj->s.YX = xy - wz; NewObj->s.ZX = xz + wy;
00261 NewObj->s.XY = xy + wz; NewObj->s.YY = 1.0f - (xx + zz); NewObj->s.ZY = yz - wx;
00262 NewObj->s.XZ = xz - wy; NewObj->s.YZ = yz + wx; NewObj->s.ZZ = 1.0f - (xx + yy);
00263 }
00264
00270 inline
00271 static void Matrix3fMulMatrix3f(Matrix3fT* NewObj, const Matrix3fT* m1)
00272 {
00273 Matrix3fT Result;
00274
00275 assert(NewObj && m1);
00276
00277
00278 Result.s.M00 = (NewObj->s.M00 * m1->s.M00) + (NewObj->s.M01 * m1->s.M10) + (NewObj->s.M02 * m1->s.M20);
00279 Result.s.M01 = (NewObj->s.M00 * m1->s.M01) + (NewObj->s.M01 * m1->s.M11) + (NewObj->s.M02 * m1->s.M21);
00280 Result.s.M02 = (NewObj->s.M00 * m1->s.M02) + (NewObj->s.M01 * m1->s.M12) + (NewObj->s.M02 * m1->s.M22);
00281
00282 Result.s.M10 = (NewObj->s.M10 * m1->s.M00) + (NewObj->s.M11 * m1->s.M10) + (NewObj->s.M12 * m1->s.M20);
00283 Result.s.M11 = (NewObj->s.M10 * m1->s.M01) + (NewObj->s.M11 * m1->s.M11) + (NewObj->s.M12 * m1->s.M21);
00284 Result.s.M12 = (NewObj->s.M10 * m1->s.M02) + (NewObj->s.M11 * m1->s.M12) + (NewObj->s.M12 * m1->s.M22);
00285
00286 Result.s.M20 = (NewObj->s.M20 * m1->s.M00) + (NewObj->s.M21 * m1->s.M10) + (NewObj->s.M22 * m1->s.M20);
00287 Result.s.M21 = (NewObj->s.M20 * m1->s.M01) + (NewObj->s.M21 * m1->s.M11) + (NewObj->s.M22 * m1->s.M21);
00288 Result.s.M22 = (NewObj->s.M20 * m1->s.M02) + (NewObj->s.M21 * m1->s.M12) + (NewObj->s.M22 * m1->s.M22);
00289
00290
00291 *NewObj = Result;
00292 }
00293
00294 inline
00295 static void Matrix4fSetRotationScaleFromMatrix4f(Matrix4fT* NewObj, const Matrix4fT* m1)
00296 {
00297 assert(NewObj && m1);
00298
00299 NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;
00300 NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;
00301 NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;
00302 }
00303
00311 inline
00312 static GLfloat Matrix4fSVD(const Matrix4fT* NewObj, Matrix3fT* rot3, Matrix4fT* rot4)
00313 {
00314 GLfloat s, n;
00315
00316 assert(NewObj);
00317
00318
00319
00320
00321
00322 s = FuncSqrt(
00323 ( (NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ) +
00324 (NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ) +
00325 (NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ) ) / 3.0f );
00326
00327 if (rot3)
00328 {
00329
00330 rot3->s.XX = NewObj->s.XX; rot3->s.XY = NewObj->s.XY; rot3->s.XZ = NewObj->s.XZ;
00331 rot3->s.YX = NewObj->s.YX; rot3->s.YY = NewObj->s.YY; rot3->s.YZ = NewObj->s.YZ;
00332 rot3->s.ZX = NewObj->s.ZX; rot3->s.ZY = NewObj->s.ZY; rot3->s.ZZ = NewObj->s.ZZ;
00333
00334
00335
00336 n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +
00337 (NewObj->s.XY * NewObj->s.XY) +
00338 (NewObj->s.XZ * NewObj->s.XZ) );
00339 rot3->s.XX *= n;
00340 rot3->s.XY *= n;
00341 rot3->s.XZ *= n;
00342
00343 n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +
00344 (NewObj->s.YY * NewObj->s.YY) +
00345 (NewObj->s.YZ * NewObj->s.YZ) );
00346 rot3->s.YX *= n;
00347 rot3->s.YY *= n;
00348 rot3->s.YZ *= n;
00349
00350 n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +
00351 (NewObj->s.ZY * NewObj->s.ZY) +
00352 (NewObj->s.ZZ * NewObj->s.ZZ) );
00353 rot3->s.ZX *= n;
00354 rot3->s.ZY *= n;
00355 rot3->s.ZZ *= n;
00356 }
00357
00358 if (rot4)
00359 {
00360 if (rot4 != NewObj)
00361 {
00362 Matrix4fSetRotationScaleFromMatrix4f(rot4, NewObj);
00363 }
00364
00365
00366
00367 n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +
00368 (NewObj->s.XY * NewObj->s.XY) +
00369 (NewObj->s.XZ * NewObj->s.XZ) );
00370 rot4->s.XX *= n;
00371 rot4->s.XY *= n;
00372 rot4->s.XZ *= n;
00373
00374 n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +
00375 (NewObj->s.YY * NewObj->s.YY) +
00376 (NewObj->s.YZ * NewObj->s.YZ) );
00377 rot4->s.YX *= n;
00378 rot4->s.YY *= n;
00379 rot4->s.YZ *= n;
00380
00381 n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +
00382 (NewObj->s.ZY * NewObj->s.ZY) +
00383 (NewObj->s.ZZ * NewObj->s.ZZ) );
00384 rot4->s.ZX *= n;
00385 rot4->s.ZY *= n;
00386 rot4->s.ZZ *= n;
00387 }
00388
00389 return s;
00390 }
00391
00392 inline
00393 static void Matrix4fSetRotationScaleFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)
00394 {
00395 assert(NewObj && m1);
00396
00397 NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;
00398 NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;
00399 NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;
00400 }
00401
00402 inline
00403 static void Matrix4fMulRotationScale(Matrix4fT* NewObj, GLfloat scale)
00404 {
00405 assert(NewObj);
00406
00407 NewObj->s.XX *= scale; NewObj->s.YX *= scale; NewObj->s.ZX *= scale;
00408 NewObj->s.XY *= scale; NewObj->s.YY *= scale; NewObj->s.ZY *= scale;
00409 NewObj->s.XZ *= scale; NewObj->s.YZ *= scale; NewObj->s.ZZ *= scale;
00410 }
00411
00422 inline
00423 static void Matrix4fSetRotationFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)
00424 {
00425 GLfloat scale;
00426
00427 assert(NewObj && m1);
00428
00429 scale = Matrix4fSVD(NewObj, NULL, NULL);
00430
00431 Matrix4fSetRotationScaleFromMatrix3f(NewObj, m1);
00432 Matrix4fMulRotationScale(NewObj, scale);
00433 }
00434
00435
00436
00437 typedef class ArcBall_t
00438 {
00439 protected:
00440 inline
00441 void _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const;
00442
00443 public:
00444
00445 ArcBall_t(GLfloat NewWidth, GLfloat NewHeight);
00446 ~ArcBall_t() { };
00447
00448
00449 inline
00450 void setBounds(GLfloat NewWidth, GLfloat NewHeight)
00451 {
00452 assert((NewWidth > 1.0f) && (NewHeight > 1.0f));
00453
00454
00455 this->AdjustWidth = 1.0f / ((NewWidth - 1.0f) * 0.5f);
00456 this->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
00457 }
00458
00459
00460 void click(const Point2fT* NewPt);
00461
00462
00463 void drag(const Point2fT* NewPt, Quat4fT* NewRot);
00464
00465 protected:
00466 Vector3fT StVec;
00467 Vector3fT EnVec;
00468 GLfloat AdjustWidth;
00469 GLfloat AdjustHeight;
00470
00471 } ArcBallT;
00472
00473 #endif
00474