You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

285 rivejä
9.7 KiB

  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (assimp)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2012, assimp team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the assimp team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the assimp team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file aiQuaterniont.inl
  35. * @brief Inline implementation of aiQuaterniont<TReal> operators
  36. */
  37. #ifndef AI_QUATERNION_INL_INC
  38. #define AI_QUATERNION_INL_INC
  39. #ifdef __cplusplus
  40. #include "quaternion.h"
  41. #include <cmath>
  42. // ---------------------------------------------------------------------------
  43. template<typename TReal>
  44. bool aiQuaterniont<TReal>::operator== (const aiQuaterniont& o) const
  45. {
  46. return x == o.x && y == o.y && z == o.z && w == o.w;
  47. }
  48. // ---------------------------------------------------------------------------
  49. template<typename TReal>
  50. bool aiQuaterniont<TReal>::operator!= (const aiQuaterniont& o) const
  51. {
  52. return !(*this == o);
  53. }
  54. // ---------------------------------------------------------------------------
  55. template<typename TReal>
  56. inline bool aiQuaterniont<TReal>::Equal(const aiQuaterniont& o, TReal epsilon) const {
  57. return
  58. std::abs(x - o.x) <= epsilon &&
  59. std::abs(y - o.y) <= epsilon &&
  60. std::abs(z - o.z) <= epsilon &&
  61. std::abs(w - o.w) <= epsilon;
  62. }
  63. // ---------------------------------------------------------------------------
  64. // Constructs a quaternion from a rotation matrix
  65. template<typename TReal>
  66. inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatrix)
  67. {
  68. TReal t = pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
  69. // large enough
  70. if( t > static_cast<TReal>(0))
  71. {
  72. TReal s = sqrt(1 + t) * static_cast<TReal>(2.0);
  73. x = (pRotMatrix.c2 - pRotMatrix.b3) / s;
  74. y = (pRotMatrix.a3 - pRotMatrix.c1) / s;
  75. z = (pRotMatrix.b1 - pRotMatrix.a2) / s;
  76. w = static_cast<TReal>(0.25) * s;
  77. } // else we have to check several cases
  78. else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )
  79. {
  80. // Column 0:
  81. TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * static_cast<TReal>(2.0);
  82. x = static_cast<TReal>(0.25) * s;
  83. y = (pRotMatrix.b1 + pRotMatrix.a2) / s;
  84. z = (pRotMatrix.a3 + pRotMatrix.c1) / s;
  85. w = (pRotMatrix.c2 - pRotMatrix.b3) / s;
  86. }
  87. else if( pRotMatrix.b2 > pRotMatrix.c3)
  88. {
  89. // Column 1:
  90. TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * static_cast<TReal>(2.0);
  91. x = (pRotMatrix.b1 + pRotMatrix.a2) / s;
  92. y = static_cast<TReal>(0.25) * s;
  93. z = (pRotMatrix.c2 + pRotMatrix.b3) / s;
  94. w = (pRotMatrix.a3 - pRotMatrix.c1) / s;
  95. } else
  96. {
  97. // Column 2:
  98. TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * static_cast<TReal>(2.0);
  99. x = (pRotMatrix.a3 + pRotMatrix.c1) / s;
  100. y = (pRotMatrix.c2 + pRotMatrix.b3) / s;
  101. z = static_cast<TReal>(0.25) * s;
  102. w = (pRotMatrix.b1 - pRotMatrix.a2) / s;
  103. }
  104. }
  105. // ---------------------------------------------------------------------------
  106. // Construction from euler angles
  107. template<typename TReal>
  108. inline aiQuaterniont<TReal>::aiQuaterniont( TReal fPitch, TReal fYaw, TReal fRoll )
  109. {
  110. const TReal fSinPitch(sin(fPitch*static_cast<TReal>(0.5)));
  111. const TReal fCosPitch(cos(fPitch*static_cast<TReal>(0.5)));
  112. const TReal fSinYaw(sin(fYaw*static_cast<TReal>(0.5)));
  113. const TReal fCosYaw(cos(fYaw*static_cast<TReal>(0.5)));
  114. const TReal fSinRoll(sin(fRoll*static_cast<TReal>(0.5)));
  115. const TReal fCosRoll(cos(fRoll*static_cast<TReal>(0.5)));
  116. const TReal fCosPitchCosYaw(fCosPitch*fCosYaw);
  117. const TReal fSinPitchSinYaw(fSinPitch*fSinYaw);
  118. x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw;
  119. y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
  120. z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
  121. w = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw;
  122. }
  123. // ---------------------------------------------------------------------------
  124. // Returns a matrix representation of the quaternion
  125. template<typename TReal>
  126. inline aiMatrix3x3t<TReal> aiQuaterniont<TReal>::GetMatrix() const
  127. {
  128. aiMatrix3x3t<TReal> resMatrix;
  129. resMatrix.a1 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (y * y + z * z);
  130. resMatrix.a2 = static_cast<TReal>(2.0) * (x * y - z * w);
  131. resMatrix.a3 = static_cast<TReal>(2.0) * (x * z + y * w);
  132. resMatrix.b1 = static_cast<TReal>(2.0) * (x * y + z * w);
  133. resMatrix.b2 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + z * z);
  134. resMatrix.b3 = static_cast<TReal>(2.0) * (y * z - x * w);
  135. resMatrix.c1 = static_cast<TReal>(2.0) * (x * z - y * w);
  136. resMatrix.c2 = static_cast<TReal>(2.0) * (y * z + x * w);
  137. resMatrix.c3 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + y * y);
  138. return resMatrix;
  139. }
  140. // ---------------------------------------------------------------------------
  141. // Construction from an axis-angle pair
  142. template<typename TReal>
  143. inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> axis, TReal angle)
  144. {
  145. axis.Normalize();
  146. const TReal sin_a = sin( angle / 2 );
  147. const TReal cos_a = cos( angle / 2 );
  148. x = axis.x * sin_a;
  149. y = axis.y * sin_a;
  150. z = axis.z * sin_a;
  151. w = cos_a;
  152. }
  153. // ---------------------------------------------------------------------------
  154. // Construction from am existing, normalized quaternion
  155. template<typename TReal>
  156. inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> normalized)
  157. {
  158. x = normalized.x;
  159. y = normalized.y;
  160. z = normalized.z;
  161. const TReal t = static_cast<TReal>(1.0) - (x*x) - (y*y) - (z*z);
  162. if (t < static_cast<TReal>(0.0)) {
  163. w = static_cast<TReal>(0.0);
  164. }
  165. else w = sqrt (t);
  166. }
  167. // ---------------------------------------------------------------------------
  168. // Performs a spherical interpolation between two quaternions
  169. // Implementation adopted from the gmtl project. All others I found on the net fail in some cases.
  170. // Congrats, gmtl!
  171. template<typename TReal>
  172. inline void aiQuaterniont<TReal>::Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart, const aiQuaterniont& pEnd, TReal pFactor)
  173. {
  174. // calc cosine theta
  175. TReal cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
  176. // adjust signs (if necessary)
  177. aiQuaterniont end = pEnd;
  178. if( cosom < static_cast<TReal>(0.0))
  179. {
  180. cosom = -cosom;
  181. end.x = -end.x; // Reverse all signs
  182. end.y = -end.y;
  183. end.z = -end.z;
  184. end.w = -end.w;
  185. }
  186. // Calculate coefficients
  187. TReal sclp, sclq;
  188. if( (static_cast<TReal>(1.0) - cosom) > static_cast<TReal>(0.0001)) // 0.0001 -> some epsillon
  189. {
  190. // Standard case (slerp)
  191. TReal omega, sinom;
  192. omega = acos( cosom); // extract theta from dot product's cos theta
  193. sinom = sin( omega);
  194. sclp = sin( (static_cast<TReal>(1.0) - pFactor) * omega) / sinom;
  195. sclq = sin( pFactor * omega) / sinom;
  196. } else
  197. {
  198. // Very close, do linear interp (because it's faster)
  199. sclp = static_cast<TReal>(1.0) - pFactor;
  200. sclq = pFactor;
  201. }
  202. pOut.x = sclp * pStart.x + sclq * end.x;
  203. pOut.y = sclp * pStart.y + sclq * end.y;
  204. pOut.z = sclp * pStart.z + sclq * end.z;
  205. pOut.w = sclp * pStart.w + sclq * end.w;
  206. }
  207. // ---------------------------------------------------------------------------
  208. template<typename TReal>
  209. inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Normalize()
  210. {
  211. // compute the magnitude and divide through it
  212. const TReal mag = sqrt(x*x + y*y + z*z + w*w);
  213. if (mag)
  214. {
  215. const TReal invMag = static_cast<TReal>(1.0)/mag;
  216. x *= invMag;
  217. y *= invMag;
  218. z *= invMag;
  219. w *= invMag;
  220. }
  221. return *this;
  222. }
  223. // ---------------------------------------------------------------------------
  224. template<typename TReal>
  225. inline aiQuaterniont<TReal> aiQuaterniont<TReal>::operator* (const aiQuaterniont& t) const
  226. {
  227. return aiQuaterniont(w*t.w - x*t.x - y*t.y - z*t.z,
  228. w*t.x + x*t.w + y*t.z - z*t.y,
  229. w*t.y + y*t.w + z*t.x - x*t.z,
  230. w*t.z + z*t.w + x*t.y - y*t.x);
  231. }
  232. // ---------------------------------------------------------------------------
  233. template<typename TReal>
  234. inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Conjugate ()
  235. {
  236. x = -x;
  237. y = -y;
  238. z = -z;
  239. return *this;
  240. }
  241. // ---------------------------------------------------------------------------
  242. template<typename TReal>
  243. inline aiVector3t<TReal> aiQuaterniont<TReal>::Rotate (const aiVector3t<TReal>& v)
  244. {
  245. aiQuaterniont q2(0.f,v.x,v.y,v.z), q = *this, qinv = q;
  246. q.Conjugate();
  247. q = q*q2*qinv;
  248. return aiVector3t<TReal>(q.x,q.y,q.z);
  249. }
  250. #endif
  251. #endif