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