mQuat.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "math/mQuat.h"
  23. #include "math/mMatrix.h"
  24. QuatF& QuatF::set( const EulerF & e )
  25. {
  26. F32 cx, sx;
  27. F32 cy, sy;
  28. F32 cz, sz;
  29. mSinCos( -e.x * F32(0.5), sx, cx );
  30. mSinCos( -e.y * F32(0.5), sy, cy );
  31. mSinCos( -e.z * F32(0.5), sz, cz );
  32. // Qyaw(z) = [ (0, 0, sin z/2), cos z/2 ]
  33. // Qpitch(x) = [ (sin x/2, 0, 0), cos x/2 ]
  34. // Qroll(y) = [ (0, sin y/2, 0), cos y/2 ]
  35. // this = Qresult = Qyaw*Qpitch*Qroll ZXY
  36. //
  37. // The code that folows is a simplification of:
  38. // roll*=pitch;
  39. // roll*=yaw;
  40. // *this = roll;
  41. F32 cycz, sysz, sycz, cysz;
  42. cycz = cy*cz;
  43. sysz = sy*sz;
  44. sycz = sy*cz;
  45. cysz = cy*sz;
  46. w = cycz*cx + sysz*sx;
  47. x = cycz*sx + sysz*cx;
  48. y = sycz*cx - cysz*sx;
  49. z = cysz*cx - sycz*sx;
  50. return *this;
  51. }
  52. AngAxisF & AngAxisF::set( const QuatF & q )
  53. {
  54. angle = mAcos( q.w ) * 2;
  55. F32 sinHalfAngle = mSqrt(1 - q.w * q.w);
  56. if (sinHalfAngle != 0)
  57. axis.set( q.x / sinHalfAngle, q.y / sinHalfAngle, q.z / sinHalfAngle );
  58. else
  59. axis.set(1,0,0);
  60. return *this;
  61. }
  62. AngAxisF & AngAxisF::set( const MatrixF & mat )
  63. {
  64. QuatF q( mat );
  65. set( q );
  66. return *this;
  67. }
  68. MatrixF * AngAxisF::setMatrix( MatrixF * mat ) const
  69. {
  70. QuatF q( *this );
  71. return q.setMatrix( mat );
  72. }
  73. QuatF& QuatF::operator *=( const QuatF & b )
  74. {
  75. QuatF prod;
  76. prod.w = w * b.w - x * b.x - y * b.y - z * b.z;
  77. prod.x = w * b.x + x * b.w + y * b.z - z * b.y;
  78. prod.y = w * b.y + y * b.w + z * b.x - x * b.z;
  79. prod.z = w * b.z + z * b.w + x * b.y - y * b.x;
  80. *this = prod;
  81. return (*this);
  82. }
  83. QuatF& QuatF::operator /=( const QuatF & c )
  84. {
  85. QuatF temp = c;
  86. return ( (*this) *= temp.inverse() );
  87. }
  88. QuatF& QuatF::operator +=( const QuatF & c )
  89. {
  90. x += c.x;
  91. y += c.y;
  92. z += c.z;
  93. w += c.w;
  94. return *this;
  95. }
  96. QuatF& QuatF::operator -=( const QuatF & c )
  97. {
  98. x -= c.x;
  99. y -= c.y;
  100. z -= c.z;
  101. w -= c.w;
  102. return *this;
  103. }
  104. QuatF& QuatF::operator *=( F32 a )
  105. {
  106. x *= a;
  107. y *= a;
  108. z *= a;
  109. w *= a;
  110. return *this;
  111. }
  112. QuatF& QuatF::operator /=( F32 a )
  113. {
  114. x /= a;
  115. y /= a;
  116. z /= a;
  117. w /= a;
  118. return *this;
  119. }
  120. QuatF& QuatF::square()
  121. {
  122. F32 t = w*2.0f;
  123. w = (w*w) - (x*x + y*y + z*z);
  124. x *= t;
  125. y *= t;
  126. z *= t;
  127. return *this;
  128. }
  129. QuatF& QuatF::inverse()
  130. {
  131. F32 magnitude = w*w + x*x + y*y + z*z;
  132. F32 invMagnitude;
  133. if( magnitude == 1.0f ) // special case unit quaternion
  134. {
  135. x = -x;
  136. y = -y;
  137. z = -z;
  138. }
  139. else // else scale
  140. {
  141. if( magnitude == 0.0f )
  142. invMagnitude = 1.0f;
  143. else
  144. invMagnitude = 1.0f / magnitude;
  145. w *= invMagnitude;
  146. x *= -invMagnitude;
  147. y *= -invMagnitude;
  148. z *= -invMagnitude;
  149. }
  150. return *this;
  151. }
  152. QuatF& QuatF::set( const AngAxisF & a )
  153. {
  154. F32 sinHalfAngle, cosHalfAngle;
  155. mSinCos( a.angle * F32(0.5), sinHalfAngle, cosHalfAngle );
  156. x = a.axis.x * sinHalfAngle;
  157. y = a.axis.y * sinHalfAngle;
  158. z = a.axis.z * sinHalfAngle;
  159. w = cosHalfAngle;
  160. return *this;
  161. }
  162. QuatF & QuatF::normalize()
  163. {
  164. F32 l = mSqrt( x*x + y*y + z*z + w*w );
  165. if( l == F32(0.0) )
  166. identity();
  167. else
  168. {
  169. x /= l;
  170. y /= l;
  171. z /= l;
  172. w /= l;
  173. }
  174. return *this;
  175. }
  176. #define idx(r,c) (r*4 + c)
  177. QuatF& QuatF::set( const MatrixF & mat )
  178. {
  179. F32 const *m = mat;
  180. F32 trace = m[idx(0, 0)] + m[idx(1, 1)] + m[idx(2, 2)];
  181. if (trace > 0.0) {
  182. F32 s = mSqrt(trace + F32(1));
  183. w = s * 0.5f;
  184. s = 0.5f / s;
  185. x = (m[idx(1,2)] - m[idx(2,1)]) * s;
  186. y = (m[idx(2,0)] - m[idx(0,2)]) * s;
  187. z = (m[idx(0,1)] - m[idx(1,0)]) * s;
  188. } else {
  189. F32* q = &x;
  190. U32 i = 0;
  191. if (m[idx(1, 1)] > m[idx(0, 0)]) i = 1;
  192. if (m[idx(2, 2)] > m[idx(i, i)]) i = 2;
  193. U32 j = (i + 1) % 3;
  194. U32 k = (j + 1) % 3;
  195. F32 s = mSqrt((m[idx(i, i)] - (m[idx(j, j)] + m[idx(k, k)])) + 1.0f);
  196. q[i] = s * 0.5f;
  197. s = 0.5f / s;
  198. q[j] = (m[idx(i,j)] + m[idx(j,i)]) * s;
  199. q[k] = (m[idx(i,k)] + m[idx(k, i)]) * s;
  200. w = (m[idx(j,k)] - m[idx(k, j)]) * s;
  201. }
  202. return *this;
  203. }
  204. MatrixF * QuatF::setMatrix( MatrixF * mat ) const
  205. {
  206. if( x*x + y*y + z*z < 10E-20f) // isIdentity() -- substituted code a little more stringent but a lot faster
  207. mat->identity();
  208. else
  209. m_quatF_set_matF( x, y, z, w, *mat );
  210. return mat;
  211. }
  212. QuatF & QuatF::slerp( const QuatF & q, F32 t )
  213. {
  214. return interpolate( *this, q, t );
  215. }
  216. QuatF & QuatF::extrapolate( const QuatF & q1, const QuatF & q2, F32 t )
  217. {
  218. // assert t >= 0 && t <= 1
  219. // q1 is value at time = 0
  220. // q2 is value at time = t
  221. // Computes quaternion at time = 1
  222. F64 flip,cos = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
  223. if (cos < 0) {
  224. cos = -cos;
  225. flip = -1;
  226. }
  227. else
  228. flip = 1;
  229. F64 s1,s2;
  230. if ((1.0 - cos) > 0.00001) {
  231. F64 om = mAcos(cos) / t;
  232. F64 sd = 1 / mSin(t * om);
  233. s1 = flip * mSin(om) * sd;
  234. s2 = mSin((1 - t) * om) * sd;
  235. }
  236. else {
  237. // If quats are very close, do linear interpolation
  238. s1 = flip / t;
  239. s2 = (1 - t) / t;
  240. }
  241. x = F32(s1 * q2.x - s2 * q1.x);
  242. y = F32(s1 * q2.y - s2 * q1.y);
  243. z = F32(s1 * q2.z - s2 * q1.z);
  244. w = F32(s1 * q2.w - s2 * q1.w);
  245. return *this;
  246. }
  247. QuatF & QuatF::interpolate( const QuatF & q1, const QuatF & q2, F32 t )
  248. {
  249. //-----------------------------------
  250. // Calculate the cosine of the angle:
  251. double cosOmega = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
  252. //-----------------------------------
  253. // adjust signs if necessary:
  254. F32 sign2;
  255. if ( cosOmega < 0.0 )
  256. {
  257. cosOmega = -cosOmega;
  258. sign2 = -1.0f;
  259. }
  260. else
  261. sign2 = 1.0f;
  262. //-----------------------------------
  263. // calculate interpolating coeffs:
  264. double scale1, scale2;
  265. if ( (1.0 - cosOmega) > 0.00001 )
  266. {
  267. // standard case
  268. double omega = mAcos(cosOmega);
  269. double sinOmega = mSin(omega);
  270. scale1 = mSin((1.0 - t) * omega) / sinOmega;
  271. scale2 = sign2 * mSin(t * omega) / sinOmega;
  272. }
  273. else
  274. {
  275. // if quats are very close, just do linear interpolation
  276. scale1 = 1.0 - t;
  277. scale2 = sign2 * t;
  278. }
  279. //-----------------------------------
  280. // actually do the interpolation:
  281. x = F32(scale1 * q1.x + scale2 * q2.x);
  282. y = F32(scale1 * q1.y + scale2 * q2.y);
  283. z = F32(scale1 * q1.z + scale2 * q2.z);
  284. w = F32(scale1 * q1.w + scale2 * q2.w);
  285. return *this;
  286. }
  287. Point3F& QuatF::mulP(const Point3F& p, Point3F* r)
  288. {
  289. QuatF qq;
  290. QuatF qi = *this;
  291. QuatF qv( p.x, p.y, p.z, 0);
  292. qi.inverse();
  293. qq.mul(qi, qv);
  294. qv.mul(qq, *this);
  295. r->set(qv.x, qv.y, qv.z);
  296. return *r;
  297. }
  298. QuatF& QuatF::mul( const QuatF &a, const QuatF &b)
  299. {
  300. AssertFatal( &a != this && &b != this, "QuatF::mul: dest should not be same as source" );
  301. w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;
  302. x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y;
  303. y = a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z;
  304. z = a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x;
  305. return *this;
  306. }
  307. Point3F& TQuatF::mulP(const Point3F& pt, Point3F* r)
  308. {
  309. QuatF a;
  310. QuatF i = *this;
  311. QuatF v( pt.x, pt.y, pt.z, 0.0f);
  312. i.inverse();
  313. a.mul(i, v);
  314. v.mul(a, *this);
  315. v.normalize();
  316. r->set(v.x, v.y, v.z);
  317. *r += p;
  318. return ( *r );
  319. }