Collection of DPF-based plugins for packaging
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.

809 lines
22KB

  1. /// @ref gtc_quaternion
  2. /// @file glm/gtc/quaternion.inl
  3. #include "../trigonometric.hpp"
  4. #include "../geometric.hpp"
  5. #include "../exponential.hpp"
  6. #include "../detail/compute_vector_relational.hpp"
  7. #include "epsilon.hpp"
  8. #include <limits>
  9. namespace glm{
  10. namespace detail
  11. {
  12. template<typename T, qualifier Q, bool Aligned>
  13. struct compute_dot<tquat<T, Q>, T, Aligned>
  14. {
  15. static GLM_FUNC_QUALIFIER T call(tquat<T, Q> const& a, tquat<T, Q> const& b)
  16. {
  17. vec<4, T, Q> tmp(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
  18. return (tmp.x + tmp.y) + (tmp.z + tmp.w);
  19. }
  20. };
  21. template<typename T, qualifier Q, bool Aligned>
  22. struct compute_quat_add
  23. {
  24. static tquat<T, Q> call(tquat<T, Q> const& q, tquat<T, Q> const& p)
  25. {
  26. return tquat<T, Q>(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z);
  27. }
  28. };
  29. template<typename T, qualifier Q, bool Aligned>
  30. struct compute_quat_sub
  31. {
  32. static tquat<T, Q> call(tquat<T, Q> const& q, tquat<T, Q> const& p)
  33. {
  34. return tquat<T, Q>(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z);
  35. }
  36. };
  37. template<typename T, qualifier Q, bool Aligned>
  38. struct compute_quat_mul_scalar
  39. {
  40. static tquat<T, Q> call(tquat<T, Q> const& q, T s)
  41. {
  42. return tquat<T, Q>(q.w * s, q.x * s, q.y * s, q.z * s);
  43. }
  44. };
  45. template<typename T, qualifier Q, bool Aligned>
  46. struct compute_quat_div_scalar
  47. {
  48. static tquat<T, Q> call(tquat<T, Q> const& q, T s)
  49. {
  50. return tquat<T, Q>(q.w / s, q.x / s, q.y / s, q.z / s);
  51. }
  52. };
  53. template<typename T, qualifier Q, bool Aligned>
  54. struct compute_quat_mul_vec4
  55. {
  56. static vec<4, T, Q> call(tquat<T, Q> const& q, vec<4, T, Q> const& v)
  57. {
  58. return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w);
  59. }
  60. };
  61. }//namespace detail
  62. // -- Component accesses --
  63. template<typename T, qualifier Q>
  64. GLM_FUNC_QUALIFIER T & tquat<T, Q>::operator[](typename tquat<T, Q>::length_type i)
  65. {
  66. assert(i >= 0 && i < this->length());
  67. return (&x)[i];
  68. }
  69. template<typename T, qualifier Q>
  70. GLM_FUNC_QUALIFIER T const& tquat<T, Q>::operator[](typename tquat<T, Q>::length_type i) const
  71. {
  72. assert(i >= 0 && i < this->length());
  73. return (&x)[i];
  74. }
  75. // -- Implicit basic constructors --
  76. # if !GLM_HAS_DEFAULTED_FUNCTIONS || defined(GLM_FORCE_CTOR_INIT)
  77. template<typename T, qualifier Q>
  78. GLM_FUNC_QUALIFIER GLM_CONSTEXPR tquat<T, Q>::tquat()
  79. # ifdef GLM_FORCE_CTOR_INIT
  80. : x(0), y(0), z(0), w(1)
  81. # endif
  82. {}
  83. # endif
  84. # if !GLM_HAS_DEFAULTED_FUNCTIONS
  85. template<typename T, qualifier Q>
  86. GLM_FUNC_QUALIFIER GLM_CONSTEXPR tquat<T, Q>::tquat(tquat<T, Q> const& q)
  87. : x(q.x), y(q.y), z(q.z), w(q.w)
  88. {}
  89. # endif//!GLM_HAS_DEFAULTED_FUNCTIONS
  90. template<typename T, qualifier Q>
  91. template<qualifier P>
  92. GLM_FUNC_QUALIFIER GLM_CONSTEXPR tquat<T, Q>::tquat(tquat<T, P> const& q)
  93. : x(q.x), y(q.y), z(q.z), w(q.w)
  94. {}
  95. // -- Explicit basic constructors --
  96. template<typename T, qualifier Q>
  97. GLM_FUNC_QUALIFIER GLM_CONSTEXPR tquat<T, Q>::tquat(T s, vec<3, T, Q> const& v)
  98. : x(v.x), y(v.y), z(v.z), w(s)
  99. {}
  100. template <typename T, qualifier Q>
  101. GLM_FUNC_QUALIFIER GLM_CONSTEXPR tquat<T, Q>::tquat(T _w, T _x, T _y, T _z)
  102. : x(_x), y(_y), z(_z), w(_w)
  103. {}
  104. // -- Conversion constructors --
  105. template<typename T, qualifier Q>
  106. template<typename U, qualifier P>
  107. GLM_FUNC_QUALIFIER GLM_CONSTEXPR tquat<T, Q>::tquat(tquat<U, P> const& q)
  108. : x(static_cast<T>(q.x))
  109. , y(static_cast<T>(q.y))
  110. , z(static_cast<T>(q.z))
  111. , w(static_cast<T>(q.w))
  112. {}
  113. //template<typename valType>
  114. //GLM_FUNC_QUALIFIER tquat<valType>::tquat
  115. //(
  116. // valType const& pitch,
  117. // valType const& yaw,
  118. // valType const& roll
  119. //)
  120. //{
  121. // vec<3, valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5));
  122. // vec<3, valType> c = glm::cos(eulerAngle * valType(0.5));
  123. // vec<3, valType> s = glm::sin(eulerAngle * valType(0.5));
  124. //
  125. // this->w = c.x * c.y * c.z + s.x * s.y * s.z;
  126. // this->x = s.x * c.y * c.z - c.x * s.y * s.z;
  127. // this->y = c.x * s.y * c.z + s.x * c.y * s.z;
  128. // this->z = c.x * c.y * s.z - s.x * s.y * c.z;
  129. //}
  130. template<typename T, qualifier Q>
  131. GLM_FUNC_QUALIFIER tquat<T, Q>::tquat(vec<3, T, Q> const& u, vec<3, T, Q> const& v)
  132. {
  133. T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v));
  134. T real_part = norm_u_norm_v + dot(u, v);
  135. vec<3, T, Q> t;
  136. if(real_part < static_cast<T>(1.e-6f) * norm_u_norm_v)
  137. {
  138. // If u and v are exactly opposite, rotate 180 degrees
  139. // around an arbitrary orthogonal axis. Axis normalisation
  140. // can happen later, when we normalise the quaternion.
  141. real_part = static_cast<T>(0);
  142. 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);
  143. }
  144. else
  145. {
  146. // Otherwise, build quaternion the standard way.
  147. t = cross(u, v);
  148. }
  149. *this = normalize(tquat<T, Q>(real_part, t.x, t.y, t.z));
  150. }
  151. template<typename T, qualifier Q>
  152. GLM_FUNC_QUALIFIER tquat<T, Q>::tquat(vec<3, T, Q> const& eulerAngle)
  153. {
  154. vec<3, T, Q> c = glm::cos(eulerAngle * T(0.5));
  155. vec<3, T, Q> s = glm::sin(eulerAngle * T(0.5));
  156. this->w = c.x * c.y * c.z + s.x * s.y * s.z;
  157. this->x = s.x * c.y * c.z - c.x * s.y * s.z;
  158. this->y = c.x * s.y * c.z + s.x * c.y * s.z;
  159. this->z = c.x * c.y * s.z - s.x * s.y * c.z;
  160. }
  161. template<typename T, qualifier Q>
  162. GLM_FUNC_QUALIFIER tquat<T, Q>::tquat(mat<3, 3, T, Q> const& m)
  163. {
  164. *this = quat_cast(m);
  165. }
  166. template<typename T, qualifier Q>
  167. GLM_FUNC_QUALIFIER tquat<T, Q>::tquat(mat<4, 4, T, Q> const& m)
  168. {
  169. *this = quat_cast(m);
  170. }
  171. # if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS
  172. template<typename T, qualifier Q>
  173. GLM_FUNC_QUALIFIER tquat<T, Q>::operator mat<3, 3, T, Q>()
  174. {
  175. return mat3_cast(*this);
  176. }
  177. template<typename T, qualifier Q>
  178. GLM_FUNC_QUALIFIER tquat<T, Q>::operator mat<4, 4, T, Q>()
  179. {
  180. return mat4_cast(*this);
  181. }
  182. # endif//GLM_HAS_EXPLICIT_CONVERSION_OPERATORS
  183. template<typename T, qualifier Q>
  184. GLM_FUNC_QUALIFIER tquat<T, Q> conjugate(tquat<T, Q> const& q)
  185. {
  186. return tquat<T, Q>(q.w, -q.x, -q.y, -q.z);
  187. }
  188. template<typename T, qualifier Q>
  189. GLM_FUNC_QUALIFIER tquat<T, Q> inverse(tquat<T, Q> const& q)
  190. {
  191. return conjugate(q) / dot(q, q);
  192. }
  193. // -- Unary arithmetic operators --
  194. # if !GLM_HAS_DEFAULTED_FUNCTIONS
  195. template<typename T, qualifier Q>
  196. GLM_FUNC_QUALIFIER tquat<T, Q> & tquat<T, Q>::operator=(tquat<T, Q> const& q)
  197. {
  198. this->w = q.w;
  199. this->x = q.x;
  200. this->y = q.y;
  201. this->z = q.z;
  202. return *this;
  203. }
  204. # endif//!GLM_HAS_DEFAULTED_FUNCTIONS
  205. template<typename T, qualifier Q>
  206. template<typename U>
  207. GLM_FUNC_QUALIFIER tquat<T, Q> & tquat<T, Q>::operator=(tquat<U, Q> const& q)
  208. {
  209. this->w = static_cast<T>(q.w);
  210. this->x = static_cast<T>(q.x);
  211. this->y = static_cast<T>(q.y);
  212. this->z = static_cast<T>(q.z);
  213. return *this;
  214. }
  215. template<typename T, qualifier Q>
  216. template<typename U>
  217. GLM_FUNC_QUALIFIER tquat<T, Q> & tquat<T, Q>::operator+=(tquat<U, Q> const& q)
  218. {
  219. return (*this = detail::compute_quat_add<T, Q, detail::is_aligned<Q>::value>::call(*this, tquat<T, Q>(q)));
  220. }
  221. template<typename T, qualifier Q>
  222. template<typename U>
  223. GLM_FUNC_QUALIFIER tquat<T, Q> & tquat<T, Q>::operator-=(tquat<U, Q> const& q)
  224. {
  225. return (*this = detail::compute_quat_sub<T, Q, detail::is_aligned<Q>::value>::call(*this, tquat<T, Q>(q)));
  226. }
  227. template<typename T, qualifier Q>
  228. template<typename U>
  229. GLM_FUNC_QUALIFIER tquat<T, Q> & tquat<T, Q>::operator*=(tquat<U, Q> const& r)
  230. {
  231. tquat<T, Q> const p(*this);
  232. tquat<T, Q> const q(r);
  233. this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z;
  234. this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y;
  235. this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z;
  236. this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x;
  237. return *this;
  238. }
  239. template<typename T, qualifier Q>
  240. template<typename U>
  241. GLM_FUNC_QUALIFIER tquat<T, Q> & tquat<T, Q>::operator*=(U s)
  242. {
  243. return (*this = detail::compute_quat_mul_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s)));
  244. }
  245. template<typename T, qualifier Q>
  246. template<typename U>
  247. GLM_FUNC_QUALIFIER tquat<T, Q> & tquat<T, Q>::operator/=(U s)
  248. {
  249. return (*this = detail::compute_quat_div_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s)));
  250. }
  251. // -- Unary bit operators --
  252. template<typename T, qualifier Q>
  253. GLM_FUNC_QUALIFIER tquat<T, Q> operator+(tquat<T, Q> const& q)
  254. {
  255. return q;
  256. }
  257. template<typename T, qualifier Q>
  258. GLM_FUNC_QUALIFIER tquat<T, Q> operator-(tquat<T, Q> const& q)
  259. {
  260. return tquat<T, Q>(-q.w, -q.x, -q.y, -q.z);
  261. }
  262. // -- Binary operators --
  263. template<typename T, qualifier Q>
  264. GLM_FUNC_QUALIFIER tquat<T, Q> operator+(tquat<T, Q> const& q, tquat<T, Q> const& p)
  265. {
  266. return tquat<T, Q>(q) += p;
  267. }
  268. template<typename T, qualifier Q>
  269. GLM_FUNC_QUALIFIER tquat<T, Q> operator-(tquat<T, Q> const& q, tquat<T, Q> const& p)
  270. {
  271. return tquat<T, Q>(q) -= p;
  272. }
  273. template<typename T, qualifier Q>
  274. GLM_FUNC_QUALIFIER tquat<T, Q> operator*(tquat<T, Q> const& q, tquat<T, Q> const& p)
  275. {
  276. return tquat<T, Q>(q) *= p;
  277. }
  278. template<typename T, qualifier Q>
  279. GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(tquat<T, Q> const& q, vec<3, T, Q> const& v)
  280. {
  281. vec<3, T, Q> const QuatVector(q.x, q.y, q.z);
  282. vec<3, T, Q> const uv(glm::cross(QuatVector, v));
  283. vec<3, T, Q> const uuv(glm::cross(QuatVector, uv));
  284. return v + ((uv * q.w) + uuv) * static_cast<T>(2);
  285. }
  286. template<typename T, qualifier Q>
  287. GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(vec<3, T, Q> const& v, tquat<T, Q> const& q)
  288. {
  289. return glm::inverse(q) * v;
  290. }
  291. template<typename T, qualifier Q>
  292. GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(tquat<T, Q> const& q, vec<4, T, Q> const& v)
  293. {
  294. return detail::compute_quat_mul_vec4<T, Q, detail::is_aligned<Q>::value>::call(q, v);
  295. }
  296. template<typename T, qualifier Q>
  297. GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(vec<4, T, Q> const& v, tquat<T, Q> const& q)
  298. {
  299. return glm::inverse(q) * v;
  300. }
  301. template<typename T, qualifier Q>
  302. GLM_FUNC_QUALIFIER tquat<T, Q> operator*(tquat<T, Q> const& q, T const& s)
  303. {
  304. return tquat<T, Q>(
  305. q.w * s, q.x * s, q.y * s, q.z * s);
  306. }
  307. template<typename T, qualifier Q>
  308. GLM_FUNC_QUALIFIER tquat<T, Q> operator*(T const& s, tquat<T, Q> const& q)
  309. {
  310. return q * s;
  311. }
  312. template<typename T, qualifier Q>
  313. GLM_FUNC_QUALIFIER tquat<T, Q> operator/(tquat<T, Q> const& q, T const& s)
  314. {
  315. return tquat<T, Q>(
  316. q.w / s, q.x / s, q.y / s, q.z / s);
  317. }
  318. // -- Boolean operators --
  319. template<typename T, qualifier Q>
  320. GLM_FUNC_QUALIFIER bool operator==(tquat<T, Q> const& q1, tquat<T, Q> const& q2)
  321. {
  322. return all(epsilonEqual(q1, q2, epsilon<T>()));
  323. }
  324. template<typename T, qualifier Q>
  325. GLM_FUNC_QUALIFIER bool operator!=(tquat<T, Q> const& q1, tquat<T, Q> const& q2)
  326. {
  327. return any(epsilonNotEqual(q1, q2, epsilon<T>()));
  328. }
  329. // -- Operations --
  330. template<typename T, qualifier Q>
  331. GLM_FUNC_QUALIFIER T dot(tquat<T, Q> const& x, tquat<T, Q> const& y)
  332. {
  333. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs");
  334. return detail::compute_dot<tquat<T, Q>, T, detail::is_aligned<Q>::value>::call(x, y);
  335. }
  336. template<typename T, qualifier Q>
  337. GLM_FUNC_QUALIFIER T length(tquat<T, Q> const& q)
  338. {
  339. return glm::sqrt(dot(q, q));
  340. }
  341. template<typename T, qualifier Q>
  342. GLM_FUNC_QUALIFIER tquat<T, Q> normalize(tquat<T, Q> const& q)
  343. {
  344. T len = length(q);
  345. if(len <= T(0)) // Problem
  346. return tquat<T, Q>(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
  347. T oneOverLen = T(1) / len;
  348. return tquat<T, Q>(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen);
  349. }
  350. template<typename T, qualifier Q>
  351. GLM_FUNC_QUALIFIER tquat<T, Q> cross(tquat<T, Q> const& q1, tquat<T, Q> const& q2)
  352. {
  353. return tquat<T, Q>(
  354. q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z,
  355. q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y,
  356. q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z,
  357. q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x);
  358. }
  359. /*
  360. // (x * sin(1 - a) * angle / sin(angle)) + (y * sin(a) * angle / sin(angle))
  361. template<typename T, qualifier Q>
  362. GLM_FUNC_QUALIFIER tquat<T, Q> mix(tquat<T, Q> const& x, tquat<T, Q> const& y, T const& a)
  363. {
  364. if(a <= T(0)) return x;
  365. if(a >= T(1)) return y;
  366. float fCos = dot(x, y);
  367. tquat<T, Q> y2(y); //BUG!!! tquat<T, Q> y2;
  368. if(fCos < T(0))
  369. {
  370. y2 = -y;
  371. fCos = -fCos;
  372. }
  373. //if(fCos > 1.0f) // problem
  374. float k0, k1;
  375. if(fCos > T(0.9999))
  376. {
  377. k0 = T(1) - a;
  378. k1 = T(0) + a; //BUG!!! 1.0f + a;
  379. }
  380. else
  381. {
  382. T fSin = sqrt(T(1) - fCos * fCos);
  383. T fAngle = atan(fSin, fCos);
  384. T fOneOverSin = static_cast<T>(1) / fSin;
  385. k0 = sin((T(1) - a) * fAngle) * fOneOverSin;
  386. k1 = sin((T(0) + a) * fAngle) * fOneOverSin;
  387. }
  388. return tquat<T, Q>(
  389. k0 * x.w + k1 * y2.w,
  390. k0 * x.x + k1 * y2.x,
  391. k0 * x.y + k1 * y2.y,
  392. k0 * x.z + k1 * y2.z);
  393. }
  394. template<typename T, qualifier Q>
  395. GLM_FUNC_QUALIFIER tquat<T, Q> mix2
  396. (
  397. tquat<T, Q> const& x,
  398. tquat<T, Q> const& y,
  399. T const& a
  400. )
  401. {
  402. bool flip = false;
  403. if(a <= static_cast<T>(0)) return x;
  404. if(a >= static_cast<T>(1)) return y;
  405. T cos_t = dot(x, y);
  406. if(cos_t < T(0))
  407. {
  408. cos_t = -cos_t;
  409. flip = true;
  410. }
  411. T alpha(0), beta(0);
  412. if(T(1) - cos_t < 1e-7)
  413. beta = static_cast<T>(1) - alpha;
  414. else
  415. {
  416. T theta = acos(cos_t);
  417. T sin_t = sin(theta);
  418. beta = sin(theta * (T(1) - alpha)) / sin_t;
  419. alpha = sin(alpha * theta) / sin_t;
  420. }
  421. if(flip)
  422. alpha = -alpha;
  423. return normalize(beta * x + alpha * y);
  424. }
  425. */
  426. template<typename T, qualifier Q>
  427. GLM_FUNC_QUALIFIER tquat<T, Q> mix(tquat<T, Q> const& x, tquat<T, Q> const& y, T a)
  428. {
  429. T cosTheta = dot(x, y);
  430. // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator
  431. if(cosTheta > T(1) - epsilon<T>())
  432. {
  433. // Linear interpolation
  434. return tquat<T, Q>(
  435. mix(x.w, y.w, a),
  436. mix(x.x, y.x, a),
  437. mix(x.y, y.y, a),
  438. mix(x.z, y.z, a));
  439. }
  440. else
  441. {
  442. // Essential Mathematics, page 467
  443. T angle = acos(cosTheta);
  444. return (sin((T(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle);
  445. }
  446. }
  447. template<typename T, qualifier Q>
  448. GLM_FUNC_QUALIFIER tquat<T, Q> lerp(tquat<T, Q> const& x, tquat<T, Q> const& y, T a)
  449. {
  450. // Lerp is only defined in [0, 1]
  451. assert(a >= static_cast<T>(0));
  452. assert(a <= static_cast<T>(1));
  453. return x * (T(1) - a) + (y * a);
  454. }
  455. template<typename T, qualifier Q>
  456. GLM_FUNC_QUALIFIER tquat<T, Q> slerp(tquat<T, Q> const& x, tquat<T, Q> const& y, T a)
  457. {
  458. tquat<T, Q> z = y;
  459. T cosTheta = dot(x, y);
  460. // If cosTheta < 0, the interpolation will take the long way around the sphere.
  461. // To fix this, one quat must be negated.
  462. if (cosTheta < T(0))
  463. {
  464. z = -y;
  465. cosTheta = -cosTheta;
  466. }
  467. // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator
  468. if(cosTheta > T(1) - epsilon<T>())
  469. {
  470. // Linear interpolation
  471. return tquat<T, Q>(
  472. mix(x.w, z.w, a),
  473. mix(x.x, z.x, a),
  474. mix(x.y, z.y, a),
  475. mix(x.z, z.z, a));
  476. }
  477. else
  478. {
  479. // Essential Mathematics, page 467
  480. T angle = acos(cosTheta);
  481. return (sin((T(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle);
  482. }
  483. }
  484. template<typename T, qualifier Q>
  485. GLM_FUNC_QUALIFIER tquat<T, Q> rotate(tquat<T, Q> const& q, T const& angle, vec<3, T, Q> const& v)
  486. {
  487. vec<3, T, Q> Tmp = v;
  488. // Axis of rotation must be normalised
  489. T len = glm::length(Tmp);
  490. if(abs(len - T(1)) > T(0.001))
  491. {
  492. T oneOverLen = static_cast<T>(1) / len;
  493. Tmp.x *= oneOverLen;
  494. Tmp.y *= oneOverLen;
  495. Tmp.z *= oneOverLen;
  496. }
  497. T const AngleRad(angle);
  498. T const Sin = sin(AngleRad * T(0.5));
  499. return q * tquat<T, Q>(cos(AngleRad * T(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin);
  500. //return gtc::quaternion::cross(q, tquat<T, Q>(cos(AngleRad * T(0.5)), Tmp.x * fSin, Tmp.y * fSin, Tmp.z * fSin));
  501. }
  502. template<typename T, qualifier Q>
  503. GLM_FUNC_QUALIFIER vec<3, T, Q> eulerAngles(tquat<T, Q> const& x)
  504. {
  505. return vec<3, T, Q>(pitch(x), yaw(x), roll(x));
  506. }
  507. template<typename T, qualifier Q>
  508. GLM_FUNC_QUALIFIER T roll(tquat<T, Q> const& q)
  509. {
  510. return static_cast<T>(atan(static_cast<T>(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z));
  511. }
  512. template<typename T, qualifier Q>
  513. GLM_FUNC_QUALIFIER T pitch(tquat<T, Q> const& q)
  514. {
  515. //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));
  516. const T y = static_cast<T>(2) * (q.y * q.z + q.w * q.x);
  517. const T x = q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z;
  518. if(detail::compute_equal<T>::call(y, static_cast<T>(0)) && detail::compute_equal<T>::call(x, static_cast<T>(0))) //avoid atan2(0,0) - handle singularity - Matiis
  519. return static_cast<T>(static_cast<T>(2) * atan(q.x,q.w));
  520. return static_cast<T>(atan(y,x));
  521. }
  522. template<typename T, qualifier Q>
  523. GLM_FUNC_QUALIFIER T yaw(tquat<T, Q> const& q)
  524. {
  525. return asin(clamp(static_cast<T>(-2) * (q.x * q.z - q.w * q.y), static_cast<T>(-1), static_cast<T>(1)));
  526. }
  527. template<typename T, qualifier Q>
  528. GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat3_cast(tquat<T, Q> const& q)
  529. {
  530. mat<3, 3, T, Q> Result(T(1));
  531. T qxx(q.x * q.x);
  532. T qyy(q.y * q.y);
  533. T qzz(q.z * q.z);
  534. T qxz(q.x * q.z);
  535. T qxy(q.x * q.y);
  536. T qyz(q.y * q.z);
  537. T qwx(q.w * q.x);
  538. T qwy(q.w * q.y);
  539. T qwz(q.w * q.z);
  540. Result[0][0] = T(1) - T(2) * (qyy + qzz);
  541. Result[0][1] = T(2) * (qxy + qwz);
  542. Result[0][2] = T(2) * (qxz - qwy);
  543. Result[1][0] = T(2) * (qxy - qwz);
  544. Result[1][1] = T(1) - T(2) * (qxx + qzz);
  545. Result[1][2] = T(2) * (qyz + qwx);
  546. Result[2][0] = T(2) * (qxz + qwy);
  547. Result[2][1] = T(2) * (qyz - qwx);
  548. Result[2][2] = T(1) - T(2) * (qxx + qyy);
  549. return Result;
  550. }
  551. template<typename T, qualifier Q>
  552. GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat4_cast(tquat<T, Q> const& q)
  553. {
  554. return mat<4, 4, T, Q>(mat3_cast(q));
  555. }
  556. template<typename T, qualifier Q>
  557. GLM_FUNC_QUALIFIER tquat<T, Q> quat_cast(mat<3, 3, T, Q> const& m)
  558. {
  559. T fourXSquaredMinus1 = m[0][0] - m[1][1] - m[2][2];
  560. T fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2];
  561. T fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1];
  562. T fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2];
  563. int biggestIndex = 0;
  564. T fourBiggestSquaredMinus1 = fourWSquaredMinus1;
  565. if(fourXSquaredMinus1 > fourBiggestSquaredMinus1)
  566. {
  567. fourBiggestSquaredMinus1 = fourXSquaredMinus1;
  568. biggestIndex = 1;
  569. }
  570. if(fourYSquaredMinus1 > fourBiggestSquaredMinus1)
  571. {
  572. fourBiggestSquaredMinus1 = fourYSquaredMinus1;
  573. biggestIndex = 2;
  574. }
  575. if(fourZSquaredMinus1 > fourBiggestSquaredMinus1)
  576. {
  577. fourBiggestSquaredMinus1 = fourZSquaredMinus1;
  578. biggestIndex = 3;
  579. }
  580. T biggestVal = sqrt(fourBiggestSquaredMinus1 + static_cast<T>(1)) * static_cast<T>(0.5);
  581. T mult = static_cast<T>(0.25) / biggestVal;
  582. switch(biggestIndex)
  583. {
  584. case 0:
  585. return tquat<T, Q>(biggestVal, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult);
  586. case 1:
  587. return tquat<T, Q>((m[1][2] - m[2][1]) * mult, biggestVal, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult);
  588. case 2:
  589. return tquat<T, Q>((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggestVal, (m[1][2] + m[2][1]) * mult);
  590. case 3:
  591. return tquat<T, Q>((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggestVal);
  592. default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity.
  593. assert(false);
  594. return tquat<T, Q>(1, 0, 0, 0);
  595. }
  596. }
  597. template<typename T, qualifier Q>
  598. GLM_FUNC_QUALIFIER tquat<T, Q> quat_cast(mat<4, 4, T, Q> const& m4)
  599. {
  600. return quat_cast(mat<3, 3, T, Q>(m4));
  601. }
  602. template<typename T, qualifier Q>
  603. GLM_FUNC_QUALIFIER T angle(tquat<T, Q> const& x)
  604. {
  605. return acos(x.w) * static_cast<T>(2);
  606. }
  607. template<typename T, qualifier Q>
  608. GLM_FUNC_QUALIFIER vec<3, T, Q> axis(tquat<T, Q> const& x)
  609. {
  610. T tmp1 = static_cast<T>(1) - x.w * x.w;
  611. if(tmp1 <= static_cast<T>(0))
  612. return vec<3, T, Q>(0, 0, 1);
  613. T tmp2 = static_cast<T>(1) / sqrt(tmp1);
  614. return vec<3, T, Q>(x.x * tmp2, x.y * tmp2, x.z * tmp2);
  615. }
  616. template<typename T, qualifier Q>
  617. GLM_FUNC_QUALIFIER tquat<T, Q> angleAxis(T const& angle, vec<3, T, Q> const& v)
  618. {
  619. tquat<T, Q> Result;
  620. T const a(angle);
  621. T const s = glm::sin(a * static_cast<T>(0.5));
  622. Result.w = glm::cos(a * static_cast<T>(0.5));
  623. Result.x = v.x * s;
  624. Result.y = v.y * s;
  625. Result.z = v.z * s;
  626. return Result;
  627. }
  628. template<typename T, qualifier Q>
  629. GLM_FUNC_QUALIFIER vec<4, bool, Q> lessThan(tquat<T, Q> const& x, tquat<T, Q> const& y)
  630. {
  631. vec<4, bool, Q> Result;
  632. for(length_t i = 0; i < x.length(); ++i)
  633. Result[i] = x[i] < y[i];
  634. return Result;
  635. }
  636. template<typename T, qualifier Q>
  637. GLM_FUNC_QUALIFIER vec<4, bool, Q> lessThanEqual(tquat<T, Q> const& x, tquat<T, Q> const& y)
  638. {
  639. vec<4, bool, Q> Result;
  640. for(length_t i = 0; i < x.length(); ++i)
  641. Result[i] = x[i] <= y[i];
  642. return Result;
  643. }
  644. template<typename T, qualifier Q>
  645. GLM_FUNC_QUALIFIER vec<4, bool, Q> greaterThan(tquat<T, Q> const& x, tquat<T, Q> const& y)
  646. {
  647. vec<4, bool, Q> Result;
  648. for(length_t i = 0; i < x.length(); ++i)
  649. Result[i] = x[i] > y[i];
  650. return Result;
  651. }
  652. template<typename T, qualifier Q>
  653. GLM_FUNC_QUALIFIER vec<4, bool, Q> greaterThanEqual(tquat<T, Q> const& x, tquat<T, Q> const& y)
  654. {
  655. vec<4, bool, Q> Result;
  656. for(length_t i = 0; i < x.length(); ++i)
  657. Result[i] = x[i] >= y[i];
  658. return Result;
  659. }
  660. template<typename T, qualifier Q>
  661. GLM_FUNC_QUALIFIER vec<4, bool, Q> equal(tquat<T, Q> const& x, tquat<T, Q> const& y)
  662. {
  663. vec<4, bool, Q> Result;
  664. for(length_t i = 0; i < x.length(); ++i)
  665. Result[i] = detail::compute_equal<T>::call(x[i], y[i]);
  666. return Result;
  667. }
  668. template<typename T, qualifier Q>
  669. GLM_FUNC_QUALIFIER vec<4, bool, Q> notEqual(tquat<T, Q> const& x, tquat<T, Q> const& y)
  670. {
  671. vec<4, bool, Q> Result;
  672. for(length_t i = 0; i < x.length(); ++i)
  673. Result[i] = !detail::compute_equal<T>::call(x[i], y[i]);
  674. return Result;
  675. }
  676. template<typename T, qualifier Q>
  677. GLM_FUNC_QUALIFIER vec<4, bool, Q> isnan(tquat<T, Q> const& q)
  678. {
  679. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs");
  680. return vec<4, bool, Q>(isnan(q.x), isnan(q.y), isnan(q.z), isnan(q.w));
  681. }
  682. template<typename T, qualifier Q>
  683. GLM_FUNC_QUALIFIER vec<4, bool, Q> isinf(tquat<T, Q> const& q)
  684. {
  685. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isinf' only accept floating-point inputs");
  686. return vec<4, bool, Q>(isinf(q.x), isinf(q.y), isinf(q.z), isinf(q.w));
  687. }
  688. }//namespace glm
  689. #if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_ALIGNED_TYPE
  690. # include "quaternion_simd.inl"
  691. #endif