arcball.h 15 KB

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