quaternion_common.inl 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. namespace glm
  2. {
  3. template<typename T, qualifier Q>
  4. GLM_FUNC_QUALIFIER qua<T, Q> mix(qua<T, Q> const& x, qua<T, Q> const& y, T a)
  5. {
  6. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'mix' only accept floating-point inputs");
  7. T const cosTheta = dot(x, y);
  8. // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator
  9. if(cosTheta > static_cast<T>(1) - epsilon<T>())
  10. {
  11. // Linear interpolation
  12. return qua<T, Q>(
  13. mix(x.w, y.w, a),
  14. mix(x.x, y.x, a),
  15. mix(x.y, y.y, a),
  16. mix(x.z, y.z, a));
  17. }
  18. else
  19. {
  20. // Essential Mathematics, page 467
  21. T angle = acos(cosTheta);
  22. return (sin((static_cast<T>(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle);
  23. }
  24. }
  25. template<typename T, qualifier Q>
  26. GLM_FUNC_QUALIFIER qua<T, Q> lerp(qua<T, Q> const& x, qua<T, Q> const& y, T a)
  27. {
  28. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'lerp' only accept floating-point inputs");
  29. // Lerp is only defined in [0, 1]
  30. assert(a >= static_cast<T>(0));
  31. assert(a <= static_cast<T>(1));
  32. return x * (static_cast<T>(1) - a) + (y * a);
  33. }
  34. template<typename T, qualifier Q>
  35. GLM_FUNC_QUALIFIER qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> const& y, T a)
  36. {
  37. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'slerp' only accept floating-point inputs");
  38. qua<T, Q> z = y;
  39. T cosTheta = dot(x, y);
  40. // If cosTheta < 0, the interpolation will take the long way around the sphere.
  41. // To fix this, one quat must be negated.
  42. if(cosTheta < static_cast<T>(0))
  43. {
  44. z = -y;
  45. cosTheta = -cosTheta;
  46. }
  47. // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator
  48. if(cosTheta > static_cast<T>(1) - epsilon<T>())
  49. {
  50. // Linear interpolation
  51. return qua<T, Q>(
  52. mix(x.w, z.w, a),
  53. mix(x.x, z.x, a),
  54. mix(x.y, z.y, a),
  55. mix(x.z, z.z, a));
  56. }
  57. else
  58. {
  59. // Essential Mathematics, page 467
  60. T angle = acos(cosTheta);
  61. return (sin((static_cast<T>(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle);
  62. }
  63. }
  64. template<typename T, qualifier Q>
  65. GLM_FUNC_QUALIFIER qua<T, Q> conjugate(qua<T, Q> const& q)
  66. {
  67. return qua<T, Q>(q.w, -q.x, -q.y, -q.z);
  68. }
  69. template<typename T, qualifier Q>
  70. GLM_FUNC_QUALIFIER qua<T, Q> inverse(qua<T, Q> const& q)
  71. {
  72. return conjugate(q) / dot(q, q);
  73. }
  74. template<typename T, qualifier Q>
  75. GLM_FUNC_QUALIFIER vec<4, bool, Q> isnan(qua<T, Q> const& q)
  76. {
  77. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs");
  78. return vec<4, bool, Q>(isnan(q.x), isnan(q.y), isnan(q.z), isnan(q.w));
  79. }
  80. template<typename T, qualifier Q>
  81. GLM_FUNC_QUALIFIER vec<4, bool, Q> isinf(qua<T, Q> const& q)
  82. {
  83. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isinf' only accept floating-point inputs");
  84. return vec<4, bool, Q>(isinf(q.x), isinf(q.y), isinf(q.z), isinf(q.w));
  85. }
  86. }//namespace glm
  87. #if GLM_CONFIG_SIMD == GLM_ENABLE
  88. # include "quaternion_common_simd.inl"
  89. #endif