quaternion_common.inl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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, typename S, qualifier Q>
  65. GLM_FUNC_QUALIFIER qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> const& y, T a, S k)
  66. {
  67. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'slerp' only accept floating-point inputs");
  68. GLM_STATIC_ASSERT(std::numeric_limits<S>::is_integer, "'slerp' only accept integer for spin count");
  69. qua<T, Q> z = y;
  70. T cosTheta = dot(x, y);
  71. // If cosTheta < 0, the interpolation will take the long way around the sphere.
  72. // To fix this, one quat must be negated.
  73. if (cosTheta < static_cast<T>(0))
  74. {
  75. z = -y;
  76. cosTheta = -cosTheta;
  77. }
  78. // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator
  79. if (cosTheta > static_cast<T>(1) - epsilon<T>())
  80. {
  81. // Linear interpolation
  82. return qua<T, Q>(
  83. mix(x.w, z.w, a),
  84. mix(x.x, z.x, a),
  85. mix(x.y, z.y, a),
  86. mix(x.z, z.z, a));
  87. }
  88. else
  89. {
  90. // Graphics Gems III, page 96
  91. T angle = acos(cosTheta);
  92. T phi = angle + k * glm::pi<T>();
  93. return (sin(angle - a * phi)* x + sin(a * phi) * z) / sin(angle);
  94. }
  95. }
  96. template<typename T, qualifier Q>
  97. GLM_FUNC_QUALIFIER qua<T, Q> conjugate(qua<T, Q> const& q)
  98. {
  99. return qua<T, Q>(q.w, -q.x, -q.y, -q.z);
  100. }
  101. template<typename T, qualifier Q>
  102. GLM_FUNC_QUALIFIER qua<T, Q> inverse(qua<T, Q> const& q)
  103. {
  104. return conjugate(q) / dot(q, q);
  105. }
  106. template<typename T, qualifier Q>
  107. GLM_FUNC_QUALIFIER vec<4, bool, Q> isnan(qua<T, Q> const& q)
  108. {
  109. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs");
  110. return vec<4, bool, Q>(isnan(q.x), isnan(q.y), isnan(q.z), isnan(q.w));
  111. }
  112. template<typename T, qualifier Q>
  113. GLM_FUNC_QUALIFIER vec<4, bool, Q> isinf(qua<T, Q> const& q)
  114. {
  115. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isinf' only accept floating-point inputs");
  116. return vec<4, bool, Q>(isinf(q.x), isinf(q.y), isinf(q.z), isinf(q.w));
  117. }
  118. }//namespace glm
  119. #if GLM_CONFIG_SIMD == GLM_ENABLE
  120. # include "quaternion_common_simd.inl"
  121. #endif