quaternion.inl 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #include "../trigonometric.hpp"
  2. #include "../geometric.hpp"
  3. #include "../exponential.hpp"
  4. #include "epsilon.hpp"
  5. #include <limits>
  6. namespace glm
  7. {
  8. template<typename T, qualifier Q>
  9. GLM_FUNC_QUALIFIER vec<3, T, Q> eulerAngles(qua<T, Q> const& x)
  10. {
  11. return vec<3, T, Q>(pitch(x), yaw(x), roll(x));
  12. }
  13. template<typename T, qualifier Q>
  14. GLM_FUNC_QUALIFIER T roll(qua<T, Q> const& q)
  15. {
  16. T const y = static_cast<T>(2) * (q.x * q.y + q.w * q.z);
  17. T const x = q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z;
  18. if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon<T>()))) //avoid atan2(0,0) - handle singularity - Matiis
  19. return static_cast<T>(0);
  20. return static_cast<T>(atan(y, x));
  21. }
  22. template<typename T, qualifier Q>
  23. GLM_FUNC_QUALIFIER T pitch(qua<T, Q> const& q)
  24. {
  25. //return T(atan(T(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z));
  26. T const y = static_cast<T>(2) * (q.y * q.z + q.w * q.x);
  27. T const x = q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z;
  28. if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon<T>()))) //avoid atan2(0,0) - handle singularity - Matiis
  29. return static_cast<T>(static_cast<T>(2) * atan(q.x, q.w));
  30. return static_cast<T>(atan(y, x));
  31. }
  32. template<typename T, qualifier Q>
  33. GLM_FUNC_QUALIFIER T yaw(qua<T, Q> const& q)
  34. {
  35. return asin(clamp(static_cast<T>(-2) * (q.x * q.z - q.w * q.y), static_cast<T>(-1), static_cast<T>(1)));
  36. }
  37. template<typename T, qualifier Q>
  38. GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat3_cast(qua<T, Q> const& q)
  39. {
  40. mat<3, 3, T, Q> Result(T(1));
  41. T qxx(q.x * q.x);
  42. T qyy(q.y * q.y);
  43. T qzz(q.z * q.z);
  44. T qxz(q.x * q.z);
  45. T qxy(q.x * q.y);
  46. T qyz(q.y * q.z);
  47. T qwx(q.w * q.x);
  48. T qwy(q.w * q.y);
  49. T qwz(q.w * q.z);
  50. Result[0][0] = T(1) - T(2) * (qyy + qzz);
  51. Result[0][1] = T(2) * (qxy + qwz);
  52. Result[0][2] = T(2) * (qxz - qwy);
  53. Result[1][0] = T(2) * (qxy - qwz);
  54. Result[1][1] = T(1) - T(2) * (qxx + qzz);
  55. Result[1][2] = T(2) * (qyz + qwx);
  56. Result[2][0] = T(2) * (qxz + qwy);
  57. Result[2][1] = T(2) * (qyz - qwx);
  58. Result[2][2] = T(1) - T(2) * (qxx + qyy);
  59. return Result;
  60. }
  61. template<typename T, qualifier Q>
  62. GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat4_cast(qua<T, Q> const& q)
  63. {
  64. return mat<4, 4, T, Q>(mat3_cast(q));
  65. }
  66. template<typename T, qualifier Q>
  67. GLM_FUNC_QUALIFIER qua<T, Q> quat_cast(mat<3, 3, T, Q> const& m)
  68. {
  69. T fourXSquaredMinus1 = m[0][0] - m[1][1] - m[2][2];
  70. T fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2];
  71. T fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1];
  72. T fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2];
  73. int biggestIndex = 0;
  74. T fourBiggestSquaredMinus1 = fourWSquaredMinus1;
  75. if(fourXSquaredMinus1 > fourBiggestSquaredMinus1)
  76. {
  77. fourBiggestSquaredMinus1 = fourXSquaredMinus1;
  78. biggestIndex = 1;
  79. }
  80. if(fourYSquaredMinus1 > fourBiggestSquaredMinus1)
  81. {
  82. fourBiggestSquaredMinus1 = fourYSquaredMinus1;
  83. biggestIndex = 2;
  84. }
  85. if(fourZSquaredMinus1 > fourBiggestSquaredMinus1)
  86. {
  87. fourBiggestSquaredMinus1 = fourZSquaredMinus1;
  88. biggestIndex = 3;
  89. }
  90. T biggestVal = sqrt(fourBiggestSquaredMinus1 + static_cast<T>(1)) * static_cast<T>(0.5);
  91. T mult = static_cast<T>(0.25) / biggestVal;
  92. switch(biggestIndex)
  93. {
  94. case 0:
  95. return qua<T, Q>(biggestVal, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult);
  96. case 1:
  97. return qua<T, Q>((m[1][2] - m[2][1]) * mult, biggestVal, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult);
  98. case 2:
  99. return qua<T, Q>((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggestVal, (m[1][2] + m[2][1]) * mult);
  100. case 3:
  101. return qua<T, Q>((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggestVal);
  102. default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity.
  103. assert(false);
  104. return qua<T, Q>(1, 0, 0, 0);
  105. }
  106. }
  107. template<typename T, qualifier Q>
  108. GLM_FUNC_QUALIFIER qua<T, Q> quat_cast(mat<4, 4, T, Q> const& m4)
  109. {
  110. return quat_cast(mat<3, 3, T, Q>(m4));
  111. }
  112. template<typename T, qualifier Q>
  113. GLM_FUNC_QUALIFIER vec<4, bool, Q> lessThan(qua<T, Q> const& x, qua<T, Q> const& y)
  114. {
  115. vec<4, bool, Q> Result;
  116. for(length_t i = 0; i < x.length(); ++i)
  117. Result[i] = x[i] < y[i];
  118. return Result;
  119. }
  120. template<typename T, qualifier Q>
  121. GLM_FUNC_QUALIFIER vec<4, bool, Q> lessThanEqual(qua<T, Q> const& x, qua<T, Q> const& y)
  122. {
  123. vec<4, bool, Q> Result;
  124. for(length_t i = 0; i < x.length(); ++i)
  125. Result[i] = x[i] <= y[i];
  126. return Result;
  127. }
  128. template<typename T, qualifier Q>
  129. GLM_FUNC_QUALIFIER vec<4, bool, Q> greaterThan(qua<T, Q> const& x, qua<T, Q> const& y)
  130. {
  131. vec<4, bool, Q> Result;
  132. for(length_t i = 0; i < x.length(); ++i)
  133. Result[i] = x[i] > y[i];
  134. return Result;
  135. }
  136. template<typename T, qualifier Q>
  137. GLM_FUNC_QUALIFIER vec<4, bool, Q> greaterThanEqual(qua<T, Q> const& x, qua<T, Q> const& y)
  138. {
  139. vec<4, bool, Q> Result;
  140. for(length_t i = 0; i < x.length(); ++i)
  141. Result[i] = x[i] >= y[i];
  142. return Result;
  143. }
  144. template<typename T, qualifier Q>
  145. GLM_FUNC_QUALIFIER qua<T, Q> quatLookAt(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
  146. {
  147. # if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT
  148. return quatLookAtLH(direction, up);
  149. # else
  150. return quatLookAtRH(direction, up);
  151. # endif
  152. }
  153. template<typename T, qualifier Q>
  154. GLM_FUNC_QUALIFIER qua<T, Q> quatLookAtRH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
  155. {
  156. mat<3, 3, T, Q> Result;
  157. Result[2] = -direction;
  158. vec<3, T, Q> const& Right = cross(up, Result[2]);
  159. Result[0] = Right * inversesqrt(max(static_cast<T>(0.00001), dot(Right, Right)));
  160. Result[1] = cross(Result[2], Result[0]);
  161. return quat_cast(Result);
  162. }
  163. template<typename T, qualifier Q>
  164. GLM_FUNC_QUALIFIER qua<T, Q> quatLookAtLH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
  165. {
  166. mat<3, 3, T, Q> Result;
  167. Result[2] = direction;
  168. vec<3, T, Q> const& Right = cross(up, Result[2]);
  169. Result[0] = Right * inversesqrt(max(static_cast<T>(0.00001), dot(Right, Right)));
  170. Result[1] = cross(Result[2], Result[0]);
  171. return quat_cast(Result);
  172. }
  173. }//namespace glm
  174. #if GLM_CONFIG_SIMD == GLM_ENABLE
  175. # include "quaternion_simd.inl"
  176. #endif