type_quat.inl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. #include "../trigonometric.hpp"
  2. #include "../exponential.hpp"
  3. #include "../ext/quaternion_geometric.hpp"
  4. #include <limits>
  5. namespace glm{
  6. namespace detail
  7. {
  8. template <typename T>
  9. struct genTypeTrait<qua<T> >
  10. {
  11. static const genTypeEnum GENTYPE = GENTYPE_QUAT;
  12. };
  13. template<typename T, qualifier Q, bool Aligned>
  14. struct compute_dot<qua<T, Q>, T, Aligned>
  15. {
  16. GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(qua<T, Q> const& a, qua<T, Q> const& b)
  17. {
  18. vec<4, T, Q> tmp(a.w * b.w, a.x * b.x, a.y * b.y, a.z * b.z);
  19. return (tmp.x + tmp.y) + (tmp.z + tmp.w);
  20. }
  21. };
  22. template<typename T, qualifier Q, bool Aligned>
  23. struct compute_quat_add
  24. {
  25. GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p)
  26. {
  27. return qua<T, Q>(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z);
  28. }
  29. };
  30. template<typename T, qualifier Q, bool Aligned>
  31. struct compute_quat_sub
  32. {
  33. GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p)
  34. {
  35. return qua<T, Q>(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z);
  36. }
  37. };
  38. template<typename T, qualifier Q, bool Aligned>
  39. struct compute_quat_mul_scalar
  40. {
  41. GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, T s)
  42. {
  43. return qua<T, Q>(q.w * s, q.x * s, q.y * s, q.z * s);
  44. }
  45. };
  46. template<typename T, qualifier Q, bool Aligned>
  47. struct compute_quat_div_scalar
  48. {
  49. GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, T s)
  50. {
  51. return qua<T, Q>(q.w / s, q.x / s, q.y / s, q.z / s);
  52. }
  53. };
  54. template<typename T, qualifier Q, bool Aligned>
  55. struct compute_quat_mul_vec4
  56. {
  57. GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(qua<T, Q> const& q, vec<4, T, Q> const& v)
  58. {
  59. return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w);
  60. }
  61. };
  62. }//namespace detail
  63. // -- Component accesses --
  64. template<typename T, qualifier Q>
  65. GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & qua<T, Q>::operator[](typename qua<T, Q>::length_type i)
  66. {
  67. assert(i >= 0 && i < this->length());
  68. # ifdef GLM_FORCE_QUAT_DATA_WXYZ
  69. return (&w)[i];
  70. # else
  71. return (&x)[i];
  72. # endif
  73. }
  74. template<typename T, qualifier Q>
  75. GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& qua<T, Q>::operator[](typename qua<T, Q>::length_type i) const
  76. {
  77. assert(i >= 0 && i < this->length());
  78. # ifdef GLM_FORCE_QUAT_DATA_WXYZ
  79. return (&w)[i];
  80. # else
  81. return (&x)[i];
  82. # endif
  83. }
  84. // -- Implicit basic constructors --
  85. # if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE
  86. template<typename T, qualifier Q>
  87. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua()
  88. # if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE
  89. # ifdef GLM_FORCE_QUAT_DATA_WXYZ
  90. : w(1), x(0), y(0), z(0)
  91. # else
  92. : x(0), y(0), z(0), w(1)
  93. # endif
  94. # endif
  95. {}
  96. template<typename T, qualifier Q>
  97. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, Q> const& q)
  98. # ifdef GLM_FORCE_QUAT_DATA_WXYZ
  99. : w(q.w), x(q.x), y(q.y), z(q.z)
  100. # else
  101. : x(q.x), y(q.y), z(q.z), w(q.w)
  102. # endif
  103. {}
  104. # endif
  105. template<typename T, qualifier Q>
  106. template<qualifier P>
  107. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, P> const& q)
  108. # ifdef GLM_FORCE_QUAT_DATA_WXYZ
  109. : w(q.w), x(q.x), y(q.y), z(q.z)
  110. # else
  111. : x(q.x), y(q.y), z(q.z), w(q.w)
  112. # endif
  113. {}
  114. // -- Explicit basic constructors --
  115. template<typename T, qualifier Q>
  116. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T s, vec<3, T, Q> const& v)
  117. # ifdef GLM_FORCE_QUAT_DATA_WXYZ
  118. : w(s), x(v.x), y(v.y), z(v.z)
  119. # else
  120. : x(v.x), y(v.y), z(v.z), w(s)
  121. # endif
  122. {}
  123. template <typename T, qualifier Q>
  124. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T _w, T _x, T _y, T _z)
  125. # ifdef GLM_FORCE_QUAT_DATA_WXYZ
  126. : w(_w), x(_x), y(_y), z(_z)
  127. # else
  128. : x(_x), y(_y), z(_z), w(_w)
  129. # endif
  130. {}
  131. // -- Conversion constructors --
  132. template<typename T, qualifier Q>
  133. template<typename U, qualifier P>
  134. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<U, P> const& q)
  135. # ifdef GLM_FORCE_QUAT_DATA_WXYZ
  136. : w(static_cast<T>(q.w)), x(static_cast<T>(q.x)), y(static_cast<T>(q.y)), z(static_cast<T>(q.z))
  137. # else
  138. : x(static_cast<T>(q.x)), y(static_cast<T>(q.y)), z(static_cast<T>(q.z)), w(static_cast<T>(q.w))
  139. # endif
  140. {}
  141. //template<typename valType>
  142. //GLM_FUNC_QUALIFIER qua<valType>::qua
  143. //(
  144. // valType const& pitch,
  145. // valType const& yaw,
  146. // valType const& roll
  147. //)
  148. //{
  149. // vec<3, valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5));
  150. // vec<3, valType> c = glm::cos(eulerAngle * valType(0.5));
  151. // vec<3, valType> s = glm::sin(eulerAngle * valType(0.5));
  152. //
  153. // this->w = c.x * c.y * c.z + s.x * s.y * s.z;
  154. // this->x = s.x * c.y * c.z - c.x * s.y * s.z;
  155. // this->y = c.x * s.y * c.z + s.x * c.y * s.z;
  156. // this->z = c.x * c.y * s.z - s.x * s.y * c.z;
  157. //}
  158. template<typename T, qualifier Q>
  159. GLM_FUNC_QUALIFIER qua<T, Q>::qua(vec<3, T, Q> const& u, vec<3, T, Q> const& v)
  160. {
  161. T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v));
  162. T real_part = norm_u_norm_v + dot(u, v);
  163. vec<3, T, Q> t;
  164. if(real_part < static_cast<T>(1.e-6f) * norm_u_norm_v)
  165. {
  166. // If u and v are exactly opposite, rotate 180 degrees
  167. // around an arbitrary orthogonal axis. Axis normalisation
  168. // can happen later, when we normalise the quaternion.
  169. real_part = static_cast<T>(0);
  170. t = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast<T>(0)) : vec<3, T, Q>(static_cast<T>(0), -u.z, u.y);
  171. }
  172. else
  173. {
  174. // Otherwise, build quaternion the standard way.
  175. t = cross(u, v);
  176. }
  177. *this = normalize(qua<T, Q>(real_part, t.x, t.y, t.z));
  178. }
  179. template<typename T, qualifier Q>
  180. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(vec<3, T, Q> const& eulerAngle)
  181. {
  182. vec<3, T, Q> c = glm::cos(eulerAngle * T(0.5));
  183. vec<3, T, Q> s = glm::sin(eulerAngle * T(0.5));
  184. this->w = c.x * c.y * c.z + s.x * s.y * s.z;
  185. this->x = s.x * c.y * c.z - c.x * s.y * s.z;
  186. this->y = c.x * s.y * c.z + s.x * c.y * s.z;
  187. this->z = c.x * c.y * s.z - s.x * s.y * c.z;
  188. }
  189. template<typename T, qualifier Q>
  190. GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<3, 3, T, Q> const& m)
  191. {
  192. *this = quat_cast(m);
  193. }
  194. template<typename T, qualifier Q>
  195. GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<4, 4, T, Q> const& m)
  196. {
  197. *this = quat_cast(m);
  198. }
  199. # if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS
  200. template<typename T, qualifier Q>
  201. GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<3, 3, T, Q>() const
  202. {
  203. return mat3_cast(*this);
  204. }
  205. template<typename T, qualifier Q>
  206. GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<4, 4, T, Q>() const
  207. {
  208. return mat4_cast(*this);
  209. }
  210. # endif//GLM_HAS_EXPLICIT_CONVERSION_OPERATORS
  211. // -- Unary arithmetic operators --
  212. # if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE
  213. template<typename T, qualifier Q>
  214. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator=(qua<T, Q> const& q)
  215. {
  216. this->w = q.w;
  217. this->x = q.x;
  218. this->y = q.y;
  219. this->z = q.z;
  220. return *this;
  221. }
  222. # endif
  223. template<typename T, qualifier Q>
  224. template<typename U>
  225. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator=(qua<U, Q> const& q)
  226. {
  227. this->w = static_cast<T>(q.w);
  228. this->x = static_cast<T>(q.x);
  229. this->y = static_cast<T>(q.y);
  230. this->z = static_cast<T>(q.z);
  231. return *this;
  232. }
  233. template<typename T, qualifier Q>
  234. template<typename U>
  235. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator+=(qua<U, Q> const& q)
  236. {
  237. return (*this = detail::compute_quat_add<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q)));
  238. }
  239. template<typename T, qualifier Q>
  240. template<typename U>
  241. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator-=(qua<U, Q> const& q)
  242. {
  243. return (*this = detail::compute_quat_sub<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q)));
  244. }
  245. template<typename T, qualifier Q>
  246. template<typename U>
  247. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator*=(qua<U, Q> const& r)
  248. {
  249. qua<T, Q> const p(*this);
  250. qua<T, Q> const q(r);
  251. this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z;
  252. this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y;
  253. this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z;
  254. this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x;
  255. return *this;
  256. }
  257. template<typename T, qualifier Q>
  258. template<typename U>
  259. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator*=(U s)
  260. {
  261. return (*this = detail::compute_quat_mul_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s)));
  262. }
  263. template<typename T, qualifier Q>
  264. template<typename U>
  265. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator/=(U s)
  266. {
  267. return (*this = detail::compute_quat_div_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s)));
  268. }
  269. // -- Unary bit operators --
  270. template<typename T, qualifier Q>
  271. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q)
  272. {
  273. return q;
  274. }
  275. template<typename T, qualifier Q>
  276. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q)
  277. {
  278. return qua<T, Q>(-q.w, -q.x, -q.y, -q.z);
  279. }
  280. // -- Binary operators --
  281. template<typename T, qualifier Q>
  282. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q, qua<T, Q> const& p)
  283. {
  284. return qua<T, Q>(q) += p;
  285. }
  286. template<typename T, qualifier Q>
  287. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q, qua<T, Q> const& p)
  288. {
  289. return qua<T, Q>(q) -= p;
  290. }
  291. template<typename T, qualifier Q>
  292. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, qua<T, Q> const& p)
  293. {
  294. return qua<T, Q>(q) *= p;
  295. }
  296. template<typename T, qualifier Q>
  297. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v)
  298. {
  299. vec<3, T, Q> const QuatVector(q.x, q.y, q.z);
  300. vec<3, T, Q> const uv(glm::cross(QuatVector, v));
  301. vec<3, T, Q> const uuv(glm::cross(QuatVector, uv));
  302. return v + ((uv * q.w) + uuv) * static_cast<T>(2);
  303. }
  304. template<typename T, qualifier Q>
  305. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua<T, Q> const& q)
  306. {
  307. return glm::inverse(q) * v;
  308. }
  309. template<typename T, qualifier Q>
  310. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(qua<T, Q> const& q, vec<4, T, Q> const& v)
  311. {
  312. return detail::compute_quat_mul_vec4<T, Q, detail::is_aligned<Q>::value>::call(q, v);
  313. }
  314. template<typename T, qualifier Q>
  315. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua<T, Q> const& q)
  316. {
  317. return glm::inverse(q) * v;
  318. }
  319. template<typename T, qualifier Q>
  320. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, T const& s)
  321. {
  322. return qua<T, Q>(
  323. q.w * s, q.x * s, q.y * s, q.z * s);
  324. }
  325. template<typename T, qualifier Q>
  326. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(T const& s, qua<T, Q> const& q)
  327. {
  328. return q * s;
  329. }
  330. template<typename T, qualifier Q>
  331. GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator/(qua<T, Q> const& q, T const& s)
  332. {
  333. return qua<T, Q>(
  334. q.w / s, q.x / s, q.y / s, q.z / s);
  335. }
  336. // -- Boolean operators --
  337. template<typename T, qualifier Q>
  338. GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(qua<T, Q> const& q1, qua<T, Q> const& q2)
  339. {
  340. return q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w;
  341. }
  342. template<typename T, qualifier Q>
  343. GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(qua<T, Q> const& q1, qua<T, Q> const& q2)
  344. {
  345. return q1.x != q2.x || q1.y != q2.y || q1.z != q2.z || q1.w != q2.w;
  346. }
  347. }//namespace glm
  348. #if GLM_CONFIG_SIMD == GLM_ENABLE
  349. # include "type_quat_simd.inl"
  350. #endif