hkQuaternion.inl
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:11k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /* 
  2.  * 
  3.  * Confidential Information of Telekinesys Research Limited (t/a Havok). Not for disclosure or distribution without Havok's
  4.  * prior written consent. This software contains code, techniques and know-how which is confidential and proprietary to Havok.
  5.  * Level 2 and Level 3 source code contains trade secrets of Havok. Havok Software (C) Copyright 1999-2009 Telekinesys Research Limited t/a Havok. All Rights Reserved. Use of this software is subject to the terms of an end user license agreement.
  6.  * 
  7.  */
  8. // construction
  9. inline const hkVector4& hkQuaternion::getImag() const
  10. {
  11. return m_vec;
  12. }
  13. inline void hkQuaternion::setImag(const hkVector4& i)
  14. {
  15. m_vec.setXYZ(i);
  16. }
  17. inline hkReal hkQuaternion::getReal() const
  18. {
  19. return m_vec(3);
  20. }
  21. inline void hkQuaternion::setReal(hkReal r)
  22. {
  23. m_vec(3) = r;
  24. }
  25. inline hkQuaternion::hkQuaternion(const hkRotation& r)
  26. {
  27. set(r);
  28. }
  29. inline hkQuaternion::hkQuaternion(hkReal x, hkReal y, hkReal z, hkReal w)
  30. {
  31. m_vec.set(x,y,z,w);
  32. HK_ASSERT2(0x3c15eca2,  isOk(), "hkQuaternion components were not normalized." );
  33. }
  34. inline hkQuaternion::hkQuaternion(const hkVector4& axis, hkReal angle)
  35. {
  36. setAxisAngle(axis,angle);
  37. }
  38. inline void hkQuaternion::operator= (const hkQuaternion& q)
  39. {
  40. m_vec = q.m_vec;
  41. }
  42. inline void hkQuaternion::set(hkReal x, hkReal y, hkReal z, hkReal w)
  43. {
  44. m_vec.set(x,y,z,w);
  45. HK_ASSERT2(0x1adaad0e,  isOk(), "hkQuaternion components were not normalized." );
  46. }
  47. inline void hkQuaternion::setIdentity()
  48. {
  49. #if HK_CONFIG_SIMD == HK_CONFIG_SIMD_ENABLED
  50. extern const hkQuadReal hkQuadReal0001;
  51. m_vec.getQuad() = hkQuadReal0001;
  52. #else
  53. m_vec.set(0,0,0,1);
  54. #endif
  55. }
  56. inline void hkQuaternion::normalize()
  57. {
  58. m_vec.normalize4();
  59. }
  60. inline void hkQuaternion::setMul(hkSimdRealParameter r, const hkQuaternion& q)
  61. {
  62. m_vec.setMul4(r,q.m_vec);
  63. }
  64. inline void hkQuaternion::addMul(hkSimdRealParameter r, const hkQuaternion& q)
  65. {
  66. m_vec.addMul4(r,q.m_vec);
  67. }
  68. inline void hkQuaternion::setMul(const hkQuaternion& q0, const hkQuaternion& q1)
  69. {
  70. hkVector4 vec;
  71. vec.setCross(q0.getImag(), q1.getImag());
  72. //vec.zeroElement(3);
  73. vec.addMul4(q0.m_vec.getSimdAt(3), q1.getImag());
  74. vec.addMul4(q1.m_vec.getSimdAt(3), q0.getImag());
  75. #if HK_CONFIG_SIMD == HK_CONFIG_SIMD_ENABLED
  76. hkVector4 dot;
  77. dot.setAll(q0.m_vec.dot3( q1.m_vec ));
  78. hkVector4 w;
  79. w.setMul4(q0.m_vec, q1.m_vec);
  80. w.sub4(dot);
  81. m_vec.setXYZW(vec, w);
  82. #else
  83. hkReal real = q0.getReal() * q1.getReal() - hkReal( q0.m_vec.dot3( q1.m_vec ) );
  84. m_vec = vec;
  85. m_vec(3) = real;
  86. #endif
  87. }
  88. inline void hkQuaternion::mul(const hkQuaternion& q)
  89. {
  90. hkVector4 vec;
  91. vec.setCross(getImag(), q.getImag());
  92. vec.addMul4(m_vec.getSimdAt(3), q.getImag());
  93. vec.addMul4(q.m_vec.getSimdAt(3), getImag());
  94. #if HK_CONFIG_SIMD == HK_CONFIG_SIMD_ENABLED
  95. hkVector4 dot;  dot.setAll(getImag().dot3( q.getImag() ));
  96. hkVector4 w;  w.setMul4(m_vec, q.m_vec);
  97. w.sub4(dot);
  98. m_vec.setXYZW(vec, w);
  99. #else
  100. hkReal w = getReal() * q.getReal() - hkReal(getImag().dot3( q.getImag() ));
  101. m_vec = vec;
  102. m_vec(3) = w;
  103. #endif
  104. }
  105. inline void hkQuaternion::setMulInverse(const hkQuaternion& q0, const hkQuaternion& q1)
  106. {
  107. hkVector4 h; h.setCross(q1.getImag(), q0.getImag());
  108. h.subMul4(q0.m_vec.getSimdAt(3), q1.getImag());
  109. h.addMul4(q1.m_vec.getSimdAt(3), q0.getImag());
  110. #if HK_CONFIG_SIMD == HK_CONFIG_SIMD_ENABLED
  111. hkVector4 w; w.setAll( q0.m_vec.dot4(q1.m_vec) );
  112. m_vec.setXYZW(h, w);
  113. #else
  114. m_vec.setXYZ( h );
  115. m_vec(3) = q0.m_vec.dot4(q1.m_vec);
  116. #endif
  117. }
  118. inline void hkQuaternion::setInverseMul(const hkQuaternion& q0, const hkQuaternion& q1)
  119. {
  120. hkVector4 vec;
  121. vec.setCross(q1.getImag(), q0.getImag());
  122. vec.addMul4(q0.m_vec.getSimdAt(3), q1.getImag());
  123. vec.subMul4(q1.m_vec.getSimdAt(3), q0.getImag());
  124. #if HK_CONFIG_SIMD == HK_CONFIG_SIMD_ENABLED
  125. hkVector4 w; w.setAll( q0.m_vec.dot4(q1.m_vec) );
  126. m_vec.setXYZW(vec,w);
  127. #else
  128. m_vec.setXYZ( vec );
  129. m_vec(3) = q0.m_vec.dot4(q1.m_vec);
  130. #endif
  131. }
  132. inline void hkQuaternion::estimateAngleTo(const hkQuaternion& to, hkVector4& angleOut) const
  133. {
  134. const hkQuaternion& from = *this;
  135. angleOut.setCross(from.getImag(),         to.getImag());
  136. angleOut.subMul4(to.m_vec.getSimdAt(3),   from.getImag());
  137. angleOut.addMul4(from.m_vec.getSimdAt(3), to.getImag());
  138. angleOut.add4(angleOut);
  139. if ( hkMath::isNegative(  to.getImag().dot4( from.getImag() ) ) )
  140. {
  141. angleOut.setNeg4( angleOut );
  142. }
  143. }
  144. void hkQuaternion::setInverse( const hkQuaternion &q )
  145. {
  146. m_vec.setNeg3( q.getImag() );
  147. }
  148. const hkReal& hkQuaternion::operator()(int i) const
  149. {
  150. return m_vec(i);
  151. }
  152. inline hkReal hkQuaternion::getAngle() const
  153. {
  154. hkReal angle = hkMath::fabs( m_vec(3) );
  155. angle = hkMath::acos(angle);
  156. angle *= 2.0f;
  157. return(angle);
  158. }
  159. inline hkBool hkQuaternion::hasValidAxis() const
  160. {
  161. return m_vec.length3() > HK_REAL_EPSILON;
  162. }
  163. inline void hkQuaternion::getAxis(hkVector4 &axisOut) const
  164. {
  165. hkVector4 axisTmp;
  166. HK_ASSERT2(0x266e2bd7, hasValidAxis(), "Cannot extract axis from a Quaternion representing (within numerical tolerance) the Identity rotation (or Quaternion may not be normalized).");
  167. axisTmp = m_vec;
  168. axisTmp.normalize3();
  169. #if HK_CONFIG_SIMD == HK_CONFIG_SIMD_ENABLED
  170. hkVector4 zero; zero.setZero4();
  171. if( m_vec.compareLessThan4( zero ).anyIsSet( hkVector4Comparison::MASK_W ) )
  172. {
  173. axisTmp.setNeg4(axisTmp);
  174. }
  175. #else
  176. if(m_vec(3) < 0.0f)
  177. {
  178. axisTmp.setNeg4(axisTmp);
  179. }
  180. #endif
  181. axisOut = axisTmp;
  182. }
  183. #if HK_CONFIG_SIMD == HK_CONFIG_SIMD_ENABLED
  184. static const hkQuadReal nearlyOneQuad = HK_QUADREAL_CONSTANT(1.0f - 1e-5f, 1.0f - 1e-5f, 1.0f - 1e-5f, 1.0f - 1e-5f);
  185. static const hkQuadReal somewhatNearlyNegOneQuad = HK_QUADREAL_CONSTANT(-(1.0f - 1e-3f), -(1.0f - 1e-3f), -(1.0f - 1e-3f), -(1.0f - 1e-3f));
  186. inline void hkQuaternion::setShortestRotation(const hkVector4& from, const hkVector4& to)
  187. {
  188. HK_ASSERT2(0xad87ba22, from.isNormalized3() && to.isNormalized3(), "The input vectors are not normalized.");
  189. hkVector4 dotProd; dotProd.setAll( from.dot3( to ) ); // cos(theta)
  190. hkVector4 nearlyOne, somewhatNearlyNegOne;
  191. nearlyOne.getQuad() = nearlyOneQuad;
  192. somewhatNearlyNegOne.getQuad() = somewhatNearlyNegOneQuad;
  193. hkVector4Comparison isNearlyOne = dotProd.compareGreaterThan4(nearlyOne);
  194. nearlyOne.setNeg4(nearlyOne);
  195. hkVector4Comparison isNearlyNegativeOne = dotProd.compareLessThan4(nearlyOne);
  196. if( isNearlyOne.anyIsSet() )
  197. {
  198. setIdentity();
  199. }
  200. else if( isNearlyNegativeOne.anyIsSet() )
  201. {
  202. setFlippedRotation( from );
  203. }
  204. else
  205. {
  206. // Using cos(theta) = 2*cos^2(theta/2) - 1
  207. hkVector4 oneHalf; oneHalf.getQuad() = hkQuadRealHalf;
  208. hkVector4 c; c.setAddMul4(oneHalf, oneHalf, dotProd); // .5 * ( 1 + dotProd) 
  209. hkVector4 sqrtInverseC; sqrtInverseC.setSqrtInverse4(c);
  210. //const hkReal cosT2 = hkMath::sqrt( c );
  211. hkVector4 cross;
  212. cross.setCross( from, to ); // ~sin(theta)* axis -- this is not exact sin(theta) .. error around 1-e2 for angles close to 180deg
  213. //hkReal rescaleSin  = 0.5f / cosT2;
  214. hkVector4 rescaleSin; rescaleSin.setMul4(oneHalf, sqrtInverseC);
  215. hkVector4Comparison isSomewhatNearlyNegativeOne = dotProd.compareLessThan4(somewhatNearlyNegOne);
  216. //if (dotProd < -somewhatNearlyOne)
  217. if(isSomewhatNearlyNegativeOne.anyIsSet())
  218. {
  219. // Extra correction needed for angles around 180deg
  220. //
  221. //const hkReal sinT2 = hkMath::sqrt( cosT2 * cosT2 - dotProd );
  222. hkVector4 sinT4; sinT4.setSub4( c, dotProd );
  223. const hkSimdReal invApproxSinT = cross.lengthInverse3(); // this has errors around 1-e2 for angles around 180 deg.
  224. //const hkReal sinT = 2 * sinT2 * cosT2;
  225. //rescaleSin *= (sinT / approxSinT);
  226. hkVector4 invSinT2; invSinT2.setSqrtInverse4(sinT4);
  227. //rescaleSin = sinT2 / approxSinT;
  228. rescaleSin.setMul4(invSinT2, sinT4);
  229. rescaleSin.mul4(invApproxSinT);
  230. }
  231. // Using sin(theta) = 2*cos(theta/2)*sin(theta/2)
  232. cross.mul4( rescaleSin );
  233. hkVector4 cosT2; cosT2.setMul4(c, sqrtInverseC); // = sqrt(c)
  234. cross.setW( cosT2 );
  235. m_vec = cross;
  236. }
  237. HK_ASSERT2(0xad78999d, isOk(), "Resulting quaternion is not normalized.");
  238. }
  239. #else
  240. inline void hkQuaternion::setShortestRotation(const hkVector4& from, const hkVector4& to)
  241. {
  242. HK_ASSERT2(0xad87ba22, from.isNormalized3() && to.isNormalized3(), "The input vectors are not normalized.");
  243. const hkReal dotProd = from.dot3( to ); // cos(theta)
  244. const hkReal nearlyOne = 1.0f - 1e-5f;
  245. const hkReal somewhatNearlyOne = 1.0f - 1e-3f;
  246. if( dotProd > nearlyOne )
  247. {
  248. setIdentity();
  249. }
  250. else if( dotProd < -nearlyOne )
  251. {
  252. setFlippedRotation( from );
  253. }
  254. else
  255. {
  256. // Using cos(theta) = 2*cos^2(theta/2) - 1
  257. const hkReal c = (dotProd + 1.0f) * 0.5f;
  258. const hkReal cosT2 = hkMath::sqrt( c );
  259. hkVector4 cross;
  260. cross.setCross( from, to ); // ~sin(theta)* axis -- this is not exact sin(theta) .. error around 1-e2 for angles close to 180deg
  261. hkReal rescaleSin  = 0.5f / cosT2;
  262. if (dotProd < -somewhatNearlyOne)
  263. {
  264. // Extra correction needed for angles around 180deg
  265. //
  266. const hkReal sinT2 = hkMath::sqrt( cosT2 * cosT2 - dotProd );
  267. const hkReal approxSinT = cross.length3(); // this has errors around 1-e2 for angles around 180 deg.
  268. const hkReal sinT = 2 * sinT2 * cosT2;
  269. rescaleSin *= (sinT / approxSinT);
  270. }
  271. // Using sin(theta) = 2*cos(theta/2)*sin(theta/2)
  272. cross.mul4( rescaleSin );
  273. cross(3) = cosT2;
  274. m_vec = cross;
  275. }
  276. HK_ASSERT2(0xad78999d, isOk(), "Resulting quaternion is not normalized.");
  277. }
  278. #endif
  279. inline void hkQuaternion::setShortestRotationDamped(hkReal gain, const hkVector4& from, const hkVector4& to)
  280. {
  281. const hkReal dotProd = from.dot3( to ); // cos(theta)
  282. const hkReal dampedDot = 1.0f - gain + gain * dotProd;
  283. const hkReal nearlyOne = 1.0f - 1e-6f;
  284. const hkReal c = (dampedDot + 1.0f) * 0.5f;
  285. if( (c <= 0.0f) || (dotProd < -nearlyOne) )
  286. {
  287. setFlippedRotation( from );
  288. }
  289. else
  290. {
  291. if( dotProd > nearlyOne )
  292. {
  293. setIdentity();
  294. }
  295. else
  296. {
  297. const hkReal cosT2 = hkMath::sqrt( c );
  298. hkVector4 cross;
  299. cross.setCross( from, to ); // sin(theta)* axis
  300. // Using sin(theta) = 2*cos(theta/2)*sin(theta/2)
  301. const hkReal rescaleSin  = gain * 0.5f / cosT2;
  302. cross.mul4( rescaleSin );
  303. cross(3) = cosT2;
  304. // renormalize for gain.
  305. cross.normalize4();
  306. m_vec = cross;
  307. }
  308. }
  309. HK_ASSERT2(0xad78999e, isOk(), "Resulting quaternion is not normalized.");
  310. }
  311. /*
  312. * Havok SDK - NO SOURCE PC DOWNLOAD, BUILD(#20090216)
  313. * Confidential Information of Havok.  (C) Copyright 1999-2009
  314. * Telekinesys Research Limited t/a Havok. All Rights Reserved. The Havok
  315. * Logo, and the Havok buzzsaw logo are trademarks of Havok.  Title, ownership
  316. * rights, and intellectual property rights in the Havok software remain in
  317. * Havok and/or its suppliers.
  318. * Use of this software for evaluation purposes is subject to and indicates
  319. * acceptance of the End User licence Agreement for this product. A copy of
  320. * the license is included with this software and is also available at www.havok.com/tryhavok.
  321. */