1 /** KempoApi: The Turloc Toolkit *****************************/ 2 /** * * **/ 3 /** ** ** Filename: arcball.h **/ 4 /** ** Version: Common **/ 5 /** ** **/ 6 /** **/ 7 /** Arcball class for mouse manipulation. **/ 8 /** **/ 9 /** **/ 10 /** **/ 11 /** **/ 12 /** (C) 1999-2003 Tatewake.com **/ 13 /** History: **/ 14 /** 08/17/2003 - (TJG) - Creation **/ 15 /** 09/23/2003 - (TJG) - Bug fix and optimization **/ 16 /** 09/25/2003 - (TJG) - Version for NeHe Basecode users **/ 17 /** **/ 18 /*************************************************************/ 19 /* 20 MIT License: 21 22 Permission is hereby granted, free of charge, to any person obtaining a copy 23 of this software and associated documentation files (the "Software"), to deal 24 in the Software without restriction, including without limitation the rights 25 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26 copies of the Software, and to permit persons to whom the Software is 27 furnished to do so, subject to the following conditions: 28 29 The above copyright notice and this permission notice shall be included in 30 all copies or substantial portions of the Software. 31 32 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 38 THE SOFTWARE. 39 */ 40 #ifndef _ArcBall_h 41 #define _ArcBall_h 42 43 #ifdef _MSC_VER // Visual C++ compiler 44 # pragma comment( lib, "opengl32.lib" ) // Search For OpenGL32.lib While Linking 45 # pragma comment( lib, "glu32.lib" ) // Search For GLu32.lib While Linking 46 #endif 47 48 // 8<--Snip here if you have your own math types/funcs-->8 49 50 //Only support assertions in debug builds 51 #ifdef _DEBUG 52 # include "assert.h" 53 #else 54 #ifndef assert 55 # define assert(x) { } 56 #endif 57 #endif 58 59 //Math types derived from the KempoApi tMath library 60 typedef union Tuple2f_t 61 { 62 struct 63 { 64 GLfloat X, Y; 65 } s; 66 67 GLfloat T[2]; 68 } Tuple2fT; //A generic 2-element tuple that is represented by single-precision floating point x,y coordinates. 69 70 typedef union Tuple3f_t 71 { 72 struct 73 { 74 GLfloat X, Y, Z; 75 } s; 76 77 GLfloat T[3]; 78 } Tuple3fT; //A generic 3-element tuple that is represented by single precision-floating point x,y,z coordinates. 79 80 typedef union Tuple4f_t 81 { 82 struct 83 { 84 GLfloat X, Y, Z, W; 85 } s; 86 87 GLfloat T[4]; 88 } Tuple4fT; //A 4-element tuple represented by single-precision floating point x,y,z,w coordinates. 89 90 typedef union Matrix3f_t 91 { 92 struct 93 { 94 //column major 95 union { GLfloat M00; GLfloat XX; GLfloat SX; }; //XAxis.X and Scale X 96 union { GLfloat M10; GLfloat XY; }; //XAxis.Y 97 union { GLfloat M20; GLfloat XZ; }; //XAxis.Z 98 union { GLfloat M01; GLfloat YX; }; //YAxis.X 99 union { GLfloat M11; GLfloat YY; GLfloat SY; }; //YAxis.Y and Scale Y 100 union { GLfloat M21; GLfloat YZ; }; //YAxis.Z 101 union { GLfloat M02; GLfloat ZX; }; //ZAxis.X 102 union { GLfloat M12; GLfloat ZY; }; //ZAxis.Y 103 union { GLfloat M22; GLfloat ZZ; GLfloat SZ; }; //ZAxis.Z and Scale Z 104 } s; 105 GLfloat M[9]; 106 } Matrix3fT; //A single precision floating point 3 by 3 matrix. 107 108 typedef union Matrix4f_t 109 { 110 struct 111 { 112 //column major 113 union { GLfloat M00; GLfloat XX; GLfloat SX; }; //XAxis.X and Scale X 114 union { GLfloat M10; GLfloat XY; }; //XAxis.Y 115 union { GLfloat M20; GLfloat XZ; }; //XAxis.Z 116 union { GLfloat M30; GLfloat XW; }; //XAxis.W 117 union { GLfloat M01; GLfloat YX; }; //YAxis.X 118 union { GLfloat M11; GLfloat YY; GLfloat SY; }; //YAxis.Y and Scale Y 119 union { GLfloat M21; GLfloat YZ; }; //YAxis.Z 120 union { GLfloat M31; GLfloat YW; }; //YAxis.W 121 union { GLfloat M02; GLfloat ZX; }; //ZAxis.X 122 union { GLfloat M12; GLfloat ZY; }; //ZAxis.Y 123 union { GLfloat M22; GLfloat ZZ; GLfloat SZ; }; //ZAxis.Z and Scale Z 124 union { GLfloat M32; GLfloat ZW; }; //ZAxis.W 125 union { GLfloat M03; GLfloat TX; }; //Trans.X 126 union { GLfloat M13; GLfloat TY; }; //Trans.Y 127 union { GLfloat M23; GLfloat TZ; }; //Trans.Z 128 union { GLfloat M33; GLfloat TW; GLfloat SW; }; //Trans.W and Scale W 129 } s; 130 GLfloat M[16]; 131 } Matrix4fT; //A single precision floating point 4 by 4 matrix. 132 133 typedef union Matrix4d_t 134 { 135 struct 136 { 137 //column major 138 union { GLdouble M00; GLdouble XX; GLdouble SX; }; //XAxis.X and Scale X 139 union { GLdouble M10; GLdouble XY; }; //XAxis.Y 140 union { GLdouble M20; GLdouble XZ; }; //XAxis.Z 141 union { GLdouble M30; GLdouble XW; }; //XAxis.W 142 union { GLdouble M01; GLdouble YX; }; //YAxis.X 143 union { GLdouble M11; GLdouble YY; GLdouble SY; }; //YAxis.Y and Scale Y 144 union { GLdouble M21; GLdouble YZ; }; //YAxis.Z 145 union { GLdouble M31; GLdouble YW; }; //YAxis.W 146 union { GLdouble M02; GLdouble ZX; }; //ZAxis.X 147 union { GLdouble M12; GLdouble ZY; }; //ZAxis.Y 148 union { GLdouble M22; GLdouble ZZ; GLdouble SZ; }; //ZAxis.Z and Scale Z 149 union { GLdouble M32; GLdouble ZW; }; //ZAxis.W 150 union { GLdouble M03; GLdouble TX; }; //Trans.X 151 union { GLdouble M13; GLdouble TY; }; //Trans.Y 152 union { GLdouble M23; GLdouble TZ; }; //Trans.Z 153 union { GLdouble M33; GLdouble TW; GLdouble SW; }; //Trans.W and Scale W 154 } s; 155 GLdouble M[16]; 156 } Matrix4dT; //A double precision floating point 4 by 4 matrix. 157 158 159 //"Inherited" types 160 #define Point2fT Tuple2fT //A 2 element point that is represented by single precision floating point x,y coordinates. 161 162 #define Quat4fT Tuple4fT //A 4 element unit quaternion represented by single precision floating point x,y,z,w coordinates. 163 164 #define Vector2fT Tuple2fT //A 2-element vector that is represented by single-precision floating point x,y coordinates. 165 #define Vector3fT Tuple3fT //A 3-element vector that is represented by single-precision floating point x,y,z coordinates. 166 167 //Custom math, or speed overrides 168 #define FuncSqrt sqrtf 169 170 //Math functions 171 172 /** 173 * Sets the value of this tuple to the vector sum of itself and tuple t1. 174 * @param t1 the other tuple 175 */ 176 inline Point2fAdd(Point2fT * NewObj,const Tuple2fT * t1)177 static void Point2fAdd(Point2fT* NewObj, const Tuple2fT* t1) 178 { 179 assert(NewObj && t1); 180 181 NewObj->s.X += t1->s.X; 182 NewObj->s.Y += t1->s.Y; 183 } 184 185 /** 186 * Sets the value of this tuple to the vector difference of itself and tuple t1 (this = this - t1). 187 * @param t1 the other tuple 188 */ 189 inline Point2fSub(Point2fT * NewObj,const Tuple2fT * t1)190 static void Point2fSub(Point2fT* NewObj, const Tuple2fT* t1) 191 { 192 assert(NewObj && t1); 193 194 NewObj->s.X -= t1->s.X; 195 NewObj->s.Y -= t1->s.Y; 196 } 197 198 /** 199 * Sets this vector to be the vector cross product of vectors v1 and v2. 200 * @param v1 the first vector 201 * @param v2 the second vector 202 */ 203 inline Vector3fCross(Vector3fT * NewObj,const Vector3fT * v1,const Vector3fT * v2)204 static void Vector3fCross(Vector3fT* NewObj, const Vector3fT* v1, const Vector3fT* v2) 205 { 206 Vector3fT Result; //safe not to initialize 207 208 assert(NewObj && v1 && v2); 209 210 // store on stack once for aliasing-safty 211 // i.e. safe when a.cross(a, b) 212 213 Result.s.X = (v1->s.Y * v2->s.Z) - (v1->s.Z * v2->s.Y); 214 Result.s.Y = (v1->s.Z * v2->s.X) - (v1->s.X * v2->s.Z); 215 Result.s.Z = (v1->s.X * v2->s.Y) - (v1->s.Y * v2->s.X); 216 217 //copy result back 218 *NewObj = Result; 219 } 220 221 /** 222 * Computes the dot product of the this vector and vector v1. 223 * @param v1 the other vector 224 */ 225 inline Vector3fDot(const Vector3fT * NewObj,const Vector3fT * v1)226 static GLfloat Vector3fDot(const Vector3fT* NewObj, const Vector3fT* v1) 227 { 228 assert(NewObj && v1); 229 230 return (NewObj->s.X * v1->s.X) + 231 (NewObj->s.Y * v1->s.Y) + 232 (NewObj->s.Z * v1->s.Z); 233 } 234 235 /** 236 * Returns the squared length of this vector. 237 * @return the squared length of this vector 238 */ 239 inline Vector3fLengthSquared(const Vector3fT * NewObj)240 static GLfloat Vector3fLengthSquared(const Vector3fT* NewObj) 241 { 242 assert(NewObj); 243 244 return (NewObj->s.X * NewObj->s.X) + 245 (NewObj->s.Y * NewObj->s.Y) + 246 (NewObj->s.Z * NewObj->s.Z); 247 } 248 249 /** 250 * Returns the length of this vector. 251 * @return the length of this vector 252 */ 253 inline Vector3fLength(const Vector3fT * NewObj)254 static GLfloat Vector3fLength(const Vector3fT* NewObj) 255 { 256 assert(NewObj); 257 258 return FuncSqrt(Vector3fLengthSquared(NewObj)); 259 } 260 261 inline Matrix3fSetZero(Matrix3fT * NewObj)262 static void Matrix3fSetZero(Matrix3fT* NewObj) 263 { 264 NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 = 265 NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 = 266 NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 0.0f; 267 } 268 269 /** 270 * Sets this Matrix3 to identity. 271 */ 272 inline Matrix3fSetIdentity(Matrix3fT * NewObj)273 static void Matrix3fSetIdentity(Matrix3fT* NewObj) 274 { 275 Matrix3fSetZero(NewObj); 276 277 //then set diagonal as 1 278 NewObj->s.M00 = 279 NewObj->s.M11 = 280 NewObj->s.M22 = 1.0f; 281 } 282 283 /** 284 * Sets the value of this matrix to the matrix conversion of the 285 * quaternion argument. 286 * @param q1 the quaternion to be converted 287 */ 288 //$hack this can be optimized some(if s == 0) 289 inline Matrix3fSetRotationFromQuat4f(Matrix3fT * NewObj,const Quat4fT * q1)290 static void Matrix3fSetRotationFromQuat4f(Matrix3fT* NewObj, const Quat4fT* q1) 291 { 292 GLfloat n, s; 293 GLfloat xs, ys, zs; 294 GLfloat wx, wy, wz; 295 GLfloat xx, xy, xz; 296 GLfloat yy, yz, zz; 297 298 assert(NewObj && q1); 299 300 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); 301 s = (n > 0.0f) ? (2.0f / n) : 0.0f; 302 303 xs = q1->s.X * s; ys = q1->s.Y * s; zs = q1->s.Z * s; 304 wx = q1->s.W * xs; wy = q1->s.W * ys; wz = q1->s.W * zs; 305 xx = q1->s.X * xs; xy = q1->s.X * ys; xz = q1->s.X * zs; 306 yy = q1->s.Y * ys; yz = q1->s.Y * zs; zz = q1->s.Z * zs; 307 308 NewObj->s.XX = 1.0f - (yy + zz); NewObj->s.YX = xy - wz; NewObj->s.ZX = xz + wy; 309 NewObj->s.XY = xy + wz; NewObj->s.YY = 1.0f - (xx + zz); NewObj->s.ZY = yz - wx; 310 NewObj->s.XZ = xz - wy; NewObj->s.YZ = yz + wx; NewObj->s.ZZ = 1.0f - (xx + yy); 311 } 312 313 inline Matrix4fSetRotationScaleFromMatrix4f(Matrix4fT * NewObj,const Matrix4fT * m1)314 static void Matrix4fSetRotationScaleFromMatrix4f(Matrix4fT* NewObj, const Matrix4fT* m1) 315 { 316 assert(NewObj && m1); 317 318 NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX; 319 NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY; 320 NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ; 321 } 322 323 /** 324 * Performs SVD on this matrix and gets scale and rotation. 325 * Rotation is placed into rot3, and rot4. 326 * @param rot3 the rotation factor(Matrix3d). if null, ignored 327 * @param rot4 the rotation factor(Matrix4) only upper 3x3 elements are changed. if null, ignored 328 * @return scale factor 329 */ 330 inline Matrix4fSVD(const Matrix4fT * NewObj,Matrix3fT * rot3,Matrix4fT * rot4)331 static GLfloat Matrix4fSVD(const Matrix4fT* NewObj, Matrix3fT* rot3, Matrix4fT* rot4) 332 { 333 GLfloat s, n; 334 335 assert(NewObj); 336 337 // this is a simple svd. 338 // Not complete but fast and reasonable. 339 // See comment in Matrix3d. 340 341 s = FuncSqrt( 342 ( (NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ) + 343 (NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ) + 344 (NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ) ) / 3.0f ); 345 346 if (rot3) //if pointer not null 347 { 348 //this->getRotationScale(rot3); 349 rot3->s.XX = NewObj->s.XX; rot3->s.XY = NewObj->s.XY; rot3->s.XZ = NewObj->s.XZ; 350 rot3->s.YX = NewObj->s.YX; rot3->s.YY = NewObj->s.YY; rot3->s.YZ = NewObj->s.YZ; 351 rot3->s.ZX = NewObj->s.ZX; rot3->s.ZY = NewObj->s.ZY; rot3->s.ZZ = NewObj->s.ZZ; 352 353 // zero-div may occur. 354 355 n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) + 356 (NewObj->s.XY * NewObj->s.XY) + 357 (NewObj->s.XZ * NewObj->s.XZ) ); 358 rot3->s.XX *= n; 359 rot3->s.XY *= n; 360 rot3->s.XZ *= n; 361 362 n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) + 363 (NewObj->s.YY * NewObj->s.YY) + 364 (NewObj->s.YZ * NewObj->s.YZ) ); 365 rot3->s.YX *= n; 366 rot3->s.YY *= n; 367 rot3->s.YZ *= n; 368 369 n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) + 370 (NewObj->s.ZY * NewObj->s.ZY) + 371 (NewObj->s.ZZ * NewObj->s.ZZ) ); 372 rot3->s.ZX *= n; 373 rot3->s.ZY *= n; 374 rot3->s.ZZ *= n; 375 } 376 377 if (rot4) //if pointer not null 378 { 379 if (rot4 != NewObj) 380 { 381 Matrix4fSetRotationScaleFromMatrix4f(rot4, NewObj); // private method 382 } 383 384 // zero-div may occur. 385 386 n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) + 387 (NewObj->s.XY * NewObj->s.XY) + 388 (NewObj->s.XZ * NewObj->s.XZ) ); 389 rot4->s.XX *= n; 390 rot4->s.XY *= n; 391 rot4->s.XZ *= n; 392 393 n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) + 394 (NewObj->s.YY * NewObj->s.YY) + 395 (NewObj->s.YZ * NewObj->s.YZ) ); 396 rot4->s.YX *= n; 397 rot4->s.YY *= n; 398 rot4->s.YZ *= n; 399 400 n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) + 401 (NewObj->s.ZY * NewObj->s.ZY) + 402 (NewObj->s.ZZ * NewObj->s.ZZ) ); 403 rot4->s.ZX *= n; 404 rot4->s.ZY *= n; 405 rot4->s.ZZ *= n; 406 } 407 408 return s; 409 } 410 411 inline Matrix4fSetRotationScaleFromMatrix3f(Matrix4fT * NewObj,const Matrix3fT * m1)412 static void Matrix4fSetRotationScaleFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1) 413 { 414 assert(NewObj && m1); 415 416 NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX; 417 NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY; 418 NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ; 419 } 420 421 inline Matrix4fMulRotationScale(Matrix4fT * NewObj,GLfloat scale)422 static void Matrix4fMulRotationScale(Matrix4fT* NewObj, GLfloat scale) 423 { 424 assert(NewObj); 425 426 NewObj->s.XX *= scale; NewObj->s.YX *= scale; NewObj->s.ZX *= scale; 427 NewObj->s.XY *= scale; NewObj->s.YY *= scale; NewObj->s.ZY *= scale; 428 NewObj->s.XZ *= scale; NewObj->s.YZ *= scale; NewObj->s.ZZ *= scale; 429 } 430 431 /** 432 * Sets the rotational component (upper 3x3) of this matrix to the matrix 433 * values in the T precision Matrix3d argument; the other elements of 434 * this matrix are unchanged; a singular value decomposition is performed 435 * on this object's upper 3x3 matrix to factor out the scale, then this 436 * object's upper 3x3 matrix components are replaced by the passed rotation 437 * components, and then the scale is reapplied to the rotational 438 * components. 439 * @param m1 T precision 3x3 matrix 440 */ 441 inline Matrix4fSetRotationFromMatrix3f(Matrix4fT * NewObj,const Matrix3fT * m1)442 static void Matrix4fSetRotationFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1) 443 { 444 GLfloat scale; 445 446 assert(NewObj && m1); 447 448 scale = Matrix4fSVD(NewObj, NULL, NULL); 449 450 Matrix4fSetRotationScaleFromMatrix3f(NewObj, m1); 451 Matrix4fMulRotationScale(NewObj, scale); 452 } 453 454 inline Matrix3fMulMatrix3f(Matrix3fT * NewObj,const Matrix3fT * m1)455 static void Matrix3fMulMatrix3f(Matrix3fT* NewObj, const Matrix3fT* m1) 456 { 457 Matrix3fT Result; //safe not to initialize 458 459 assert(NewObj && m1); 460 461 // alias-safe way. 462 Result.s.M00 = (NewObj->s.M00 * m1->s.M00) + (NewObj->s.M01 * m1->s.M10) + (NewObj->s.M02 * m1->s.M20); 463 Result.s.M01 = (NewObj->s.M00 * m1->s.M01) + (NewObj->s.M01 * m1->s.M11) + (NewObj->s.M02 * m1->s.M21); 464 Result.s.M02 = (NewObj->s.M00 * m1->s.M02) + (NewObj->s.M01 * m1->s.M12) + (NewObj->s.M02 * m1->s.M22); 465 466 Result.s.M10 = (NewObj->s.M10 * m1->s.M00) + (NewObj->s.M11 * m1->s.M10) + (NewObj->s.M12 * m1->s.M20); 467 Result.s.M11 = (NewObj->s.M10 * m1->s.M01) + (NewObj->s.M11 * m1->s.M11) + (NewObj->s.M12 * m1->s.M21); 468 Result.s.M12 = (NewObj->s.M10 * m1->s.M02) + (NewObj->s.M11 * m1->s.M12) + (NewObj->s.M12 * m1->s.M22); 469 470 Result.s.M20 = (NewObj->s.M20 * m1->s.M00) + (NewObj->s.M21 * m1->s.M10) + (NewObj->s.M22 * m1->s.M20); 471 Result.s.M21 = (NewObj->s.M20 * m1->s.M01) + (NewObj->s.M21 * m1->s.M11) + (NewObj->s.M22 * m1->s.M21); 472 Result.s.M22 = (NewObj->s.M20 * m1->s.M02) + (NewObj->s.M21 * m1->s.M12) + (NewObj->s.M22 * m1->s.M22); 473 474 //copy result back to this 475 *NewObj = Result; 476 } 477 478 /* Apply the Matrix3f rotation to the existing values in NewObj */ 479 inline Matrix4fMulRotationFromMatrix3f(Matrix4fT * NewObj,const Matrix3fT * m1)480 static void Matrix4fMulRotationFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1) 481 { 482 Matrix3fT tmp, tmp2; 483 GLfloat scale; 484 485 assert(NewObj && m1); 486 487 scale = Matrix4fSVD(NewObj, &tmp, NULL); 488 489 tmp2 = *m1; 490 491 Matrix3fMulMatrix3f(&tmp2, &tmp); 492 Matrix4fSetRotationScaleFromMatrix3f(NewObj, &tmp2); 493 Matrix4fMulRotationScale(NewObj, scale); 494 } 495 496 497 // 8<--Snip here if you have your own math types/funcs-->8 498 499 class ArcBall 500 { 501 protected: 502 inline 503 void _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const; 504 505 public: 506 //Create/Destroy 507 ArcBall(GLfloat NewWidth = 2.0, GLfloat NewHeight = 2.0); ~ArcBall()508 ~ArcBall() { /* nothing to do */ }; 509 510 //Set new bounds 511 inline setBounds(GLfloat NewWidth,GLfloat NewHeight)512 void setBounds(GLfloat NewWidth, GLfloat NewHeight) 513 { 514 assert((NewWidth > 1.0f) && (NewHeight > 1.0f)); 515 516 //Set adjustment factor for width/height 517 this->AdjustWidth = 1.0f / ((NewWidth - 1.0f) * 0.5f); 518 this->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f); 519 } 520 521 //Mouse down 522 void click(GLfloat x, GLfloat y, Matrix4fT *startTransform); 523 524 //Mouse drag, calculate rotation 525 void drag(GLfloat x, GLfloat y, Quat4fT* NewRot); 526 void dragAccumulate(GLfloat x, GLfloat y, Matrix4fT *transform); 527 528 protected: 529 Vector3fT StVec; //Saved click vector 530 Matrix4fT StTransform; //Reference start transform 531 Vector3fT EnVec; //Saved drag vector 532 GLfloat AdjustWidth; //Mouse bounds width 533 GLfloat AdjustHeight; //Mouse bounds height 534 535 }; 536 #endif 537 538