/demo/glm/gtx/dual_quaternion.inl

https://gitlab.com/gazdik/FTGL3 · C++ Header · 421 lines · 337 code · 43 blank · 41 comment · 14 complexity · 414c4bc33dde037cab792eccc4494ce0 MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. /// OpenGL Mathematics (glm.g-truc.net)
  3. ///
  4. /// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
  5. /// Permission is hereby granted, free of charge, to any person obtaining a copy
  6. /// of this software and associated documentation files (the "Software"), to deal
  7. /// in the Software without restriction, including without limitation the rights
  8. /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. /// copies of the Software, and to permit persons to whom the Software is
  10. /// furnished to do so, subject to the following conditions:
  11. ///
  12. /// The above copyright notice and this permission notice shall be included in
  13. /// all copies or substantial portions of the Software.
  14. ///
  15. /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. /// THE SOFTWARE.
  22. ///
  23. /// @ref gtx_dual_quaternion
  24. /// @file glm/gtx/dual_quaternion.inl
  25. /// @date 2013-02-10 / 2013-02-13
  26. /// @author Maksim Vorobiev (msomeone@gmail.com)
  27. ///////////////////////////////////////////////////////////////////////////////////
  28. #include "../geometric.hpp"
  29. #include <limits>
  30. namespace glm{
  31. namespace detail
  32. {
  33. template <typename T, precision P>
  34. GLM_FUNC_QUALIFIER GLM_CONSTEXPR int tdualquat<T, P>::length() const
  35. {
  36. return 8;
  37. }
  38. template <typename T, precision P>
  39. GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat() :
  40. real(tquat<T, P>()),
  41. dual(tquat<T, P>(T(0), T(0), T(0), T(0)))
  42. {}
  43. template <typename T, precision P>
  44. GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat
  45. (
  46. tquat<T, P> const & r
  47. ) :
  48. real(r),
  49. dual(tquat<T, P>(T(0), T(0), T(0), T(0)))
  50. {}
  51. template <typename T, precision P>
  52. GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat
  53. (
  54. tquat<T, P> const & r,
  55. tquat<T, P> const & d
  56. ) :
  57. real(r),
  58. dual(d)
  59. {}
  60. template <typename T, precision P>
  61. GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat
  62. (
  63. tquat<T, P> const & q,
  64. tvec3<T, P> const& p
  65. ) :
  66. real(q),
  67. dual(
  68. T(-0.5) * ( p.x*q.x + p.y*q.y + p.z*q.z),
  69. T(+0.5) * ( p.x*q.w + p.y*q.z - p.z*q.y),
  70. T(+0.5) * (-p.x*q.z + p.y*q.w + p.z*q.x),
  71. T(+0.5) * ( p.x*q.y - p.y*q.x + p.z*q.w))
  72. {}
  73. //////////////////////////////////////////////////////////////
  74. // tdualquat conversions
  75. template <typename T, precision P>
  76. GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat
  77. (
  78. tmat2x4<T, P> const & m
  79. )
  80. {
  81. *this = dualquat_cast(m);
  82. }
  83. template <typename T, precision P>
  84. GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat
  85. (
  86. tmat3x4<T, P> const & m
  87. )
  88. {
  89. *this = dualquat_cast(m);
  90. }
  91. //////////////////////////////////////////////////////////////
  92. // tdualquat<T, P> accesses
  93. template <typename T, precision P>
  94. GLM_FUNC_QUALIFIER typename tdualquat<T, P>::part_type & tdualquat<T, P>::operator [] (int i)
  95. {
  96. assert(i >= 0 && i < this->length());
  97. return (&real)[i];
  98. }
  99. template <typename T, precision P>
  100. GLM_FUNC_QUALIFIER typename tdualquat<T, P>::part_type const & tdualquat<T, P>::operator [] (int i) const
  101. {
  102. assert(i >= 0 && i < this->length());
  103. return (&real)[i];
  104. }
  105. //////////////////////////////////////////////////////////////
  106. // tdualquat<valType> operators
  107. template <typename T, precision P>
  108. GLM_FUNC_QUALIFIER tdualquat<T, P> & tdualquat<T, P>::operator *=
  109. (
  110. T const & s
  111. )
  112. {
  113. this->real *= s;
  114. this->dual *= s;
  115. return *this;
  116. }
  117. template <typename T, precision P>
  118. GLM_FUNC_QUALIFIER tdualquat<T, P> & tdualquat<T, P>::operator /=
  119. (
  120. T const & s
  121. )
  122. {
  123. this->real /= s;
  124. this->dual /= s;
  125. return *this;
  126. }
  127. //////////////////////////////////////////////////////////////
  128. // tquat<valType> external operators
  129. template <typename T, precision P>
  130. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> operator-
  131. (
  132. detail::tdualquat<T, P> const & q
  133. )
  134. {
  135. return detail::tdualquat<T, P>(-q.real,-q.dual);
  136. }
  137. template <typename T, precision P>
  138. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> operator+
  139. (
  140. detail::tdualquat<T, P> const & q,
  141. detail::tdualquat<T, P> const & p
  142. )
  143. {
  144. return detail::tdualquat<T, P>(q.real + p.real,q.dual + p.dual);
  145. }
  146. template <typename T, precision P>
  147. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> operator*
  148. (
  149. detail::tdualquat<T, P> const & p,
  150. detail::tdualquat<T, P> const & o
  151. )
  152. {
  153. return detail::tdualquat<T, P>(p.real * o.real,p.real * o.dual + p.dual * o.real);
  154. }
  155. // Transformation
  156. template <typename T, precision P>
  157. GLM_FUNC_QUALIFIER detail::tvec3<T, P> operator*
  158. (
  159. detail::tdualquat<T, P> const & q,
  160. detail::tvec3<T, P> const & v
  161. )
  162. {
  163. detail::tvec3<T, P> const real_v3(q.real.x,q.real.y,q.real.z);
  164. detail::tvec3<T, P> const dual_v3(q.dual.x,q.dual.y,q.dual.z);
  165. return (cross(real_v3, cross(real_v3,v) + v * q.real.w + dual_v3) + dual_v3 * q.real.w - real_v3 * q.dual.w) * T(2) + v;
  166. }
  167. template <typename T, precision P>
  168. GLM_FUNC_QUALIFIER detail::tvec3<T, P> operator*
  169. (
  170. detail::tvec3<T, P> const & v,
  171. detail::tdualquat<T, P> const & q
  172. )
  173. {
  174. return glm::inverse(q) * v;
  175. }
  176. template <typename T, precision P>
  177. GLM_FUNC_QUALIFIER detail::tvec4<T, P> operator*
  178. (
  179. detail::tdualquat<T, P> const & q,
  180. detail::tvec4<T, P> const & v
  181. )
  182. {
  183. return detail::tvec4<T, P>(q * detail::tvec3<T, P>(v), v.w);
  184. }
  185. template <typename T, precision P>
  186. GLM_FUNC_QUALIFIER detail::tvec4<T, P> operator*
  187. (
  188. detail::tvec4<T, P> const & v,
  189. detail::tdualquat<T, P> const & q
  190. )
  191. {
  192. return glm::inverse(q) * v;
  193. }
  194. template <typename T, precision P>
  195. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> operator*
  196. (
  197. detail::tdualquat<T, P> const & q,
  198. T const & s
  199. )
  200. {
  201. return detail::tdualquat<T, P>(q.real * s, q.dual * s);
  202. }
  203. template <typename T, precision P>
  204. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> operator*
  205. (
  206. T const & s,
  207. detail::tdualquat<T, P> const & q
  208. )
  209. {
  210. return q * s;
  211. }
  212. template <typename T, precision P>
  213. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> operator/
  214. (
  215. detail::tdualquat<T, P> const & q,
  216. T const & s
  217. )
  218. {
  219. return detail::tdualquat<T, P>(q.real / s, q.dual / s);
  220. }
  221. //////////////////////////////////////
  222. // Boolean operators
  223. template <typename T, precision P>
  224. GLM_FUNC_QUALIFIER bool operator==
  225. (
  226. detail::tdualquat<T, P> const & q1,
  227. detail::tdualquat<T, P> const & q2
  228. )
  229. {
  230. return (q1.real == q2.real) && (q1.dual == q2.dual);
  231. }
  232. template <typename T, precision P>
  233. GLM_FUNC_QUALIFIER bool operator!=
  234. (
  235. detail::tdualquat<T, P> const & q1,
  236. detail::tdualquat<T, P> const & q2
  237. )
  238. {
  239. return (q1.real != q2.dual) || (q1.real != q2.dual);
  240. }
  241. }//namespace detail
  242. ////////////////////////////////////////////////////////
  243. template <typename T, precision P>
  244. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> normalize
  245. (
  246. detail::tdualquat<T, P> const & q
  247. )
  248. {
  249. return q / length(q.real);
  250. }
  251. template <typename T, precision P>
  252. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> lerp
  253. (
  254. detail::tdualquat<T, P> const & x,
  255. detail::tdualquat<T, P> const & y,
  256. T const & a
  257. )
  258. {
  259. // Dual Quaternion Linear blend aka DLB:
  260. // Lerp is only defined in [0, 1]
  261. assert(a >= static_cast<T>(0));
  262. assert(a <= static_cast<T>(1));
  263. T const k = dot(x.real,y.real) < static_cast<T>(0) ? -a : a;
  264. T const one(1);
  265. return detail::tdualquat<T, P>(x * (one - a) + y * k);
  266. }
  267. template <typename T, precision P>
  268. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> inverse
  269. (
  270. detail::tdualquat<T, P> const & q
  271. )
  272. {
  273. const glm::detail::tquat<T, P> real = conjugate(q.real);
  274. const glm::detail::tquat<T, P> dual = conjugate(q.dual);
  275. return detail::tdualquat<T, P>(real, dual + (real * (-2.0f * dot(real,dual))));
  276. }
  277. template <typename T, precision P>
  278. GLM_FUNC_QUALIFIER detail::tmat2x4<T, P> mat2x4_cast
  279. (
  280. detail::tdualquat<T, P> const & x
  281. )
  282. {
  283. return detail::tmat2x4<T, P>( x[0].x, x[0].y, x[0].z, x[0].w, x[1].x, x[1].y, x[1].z, x[1].w );
  284. }
  285. template <typename T, precision P>
  286. GLM_FUNC_QUALIFIER detail::tmat3x4<T, P> mat3x4_cast
  287. (
  288. detail::tdualquat<T, P> const & x
  289. )
  290. {
  291. detail::tquat<T, P> r = x.real / length2(x.real);
  292. detail::tquat<T, P> const rr(r.w * x.real.w, r.x * x.real.x, r.y * x.real.y, r.z * x.real.z);
  293. r *= static_cast<T>(2);
  294. T const xy = r.x * x.real.y;
  295. T const xz = r.x * x.real.z;
  296. T const yz = r.y * x.real.z;
  297. T const wx = r.w * x.real.x;
  298. T const wy = r.w * x.real.y;
  299. T const wz = r.w * x.real.z;
  300. detail::tvec4<T, P> const a(
  301. rr.w + rr.x - rr.y - rr.z,
  302. xy - wz,
  303. xz + wy,
  304. -(x.dual.w * r.x - x.dual.x * r.w + x.dual.y * r.z - x.dual.z * r.y));
  305. detail::tvec4<T, P> const b(
  306. xy + wz,
  307. rr.w + rr.y - rr.x - rr.z,
  308. yz - wx,
  309. -(x.dual.w * r.y - x.dual.x * r.z - x.dual.y * r.w + x.dual.z * r.x));
  310. detail::tvec4<T, P> const c(
  311. xz - wy,
  312. yz + wx,
  313. rr.w + rr.z - rr.x - rr.y,
  314. -(x.dual.w * r.z + x.dual.x * r.y - x.dual.y * r.x - x.dual.z * r.w));
  315. return detail::tmat3x4<T, P>(a, b, c);
  316. }
  317. template <typename T, precision P>
  318. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> dualquat_cast
  319. (
  320. detail::tmat2x4<T, P> const & x
  321. )
  322. {
  323. return detail::tdualquat<T, P>(
  324. detail::tquat<T, P>( x[0].w, x[0].x, x[0].y, x[0].z ),
  325. detail::tquat<T, P>( x[1].w, x[1].x, x[1].y, x[1].z ));
  326. }
  327. template <typename T, precision P>
  328. GLM_FUNC_QUALIFIER detail::tdualquat<T, P> dualquat_cast
  329. (
  330. detail::tmat3x4<T, P> const & x
  331. )
  332. {
  333. detail::tquat<T, P> real;
  334. T const trace = x[0].x + x[1].y + x[2].z;
  335. if(trace > T(0))
  336. {
  337. T const r = sqrt(T(1) + trace);
  338. T const invr = static_cast<T>(0.5) / r;
  339. real.w = static_cast<T>(0.5) * r;
  340. real.x = (x[2].y - x[1].z) * invr;
  341. real.y = (x[0].z - x[2].x) * invr;
  342. real.z = (x[1].x - x[0].y) * invr;
  343. }
  344. else if(x[0].x > x[1].y && x[0].x > x[2].z)
  345. {
  346. T const r = sqrt(T(1) + x[0].x - x[1].y - x[2].z);
  347. T const invr = static_cast<T>(0.5) / r;
  348. real.x = static_cast<T>(0.5)*r;
  349. real.y = (x[1].x + x[0].y) * invr;
  350. real.z = (x[0].z + x[2].x) * invr;
  351. real.w = (x[2].y - x[1].z) * invr;
  352. }
  353. else if(x[1].y > x[2].z)
  354. {
  355. T const r = sqrt(T(1) + x[1].y - x[0].x - x[2].z);
  356. T const invr = static_cast<T>(0.5) / r;
  357. real.x = (x[1].x + x[0].y) * invr;
  358. real.y = static_cast<T>(0.5) * r;
  359. real.z = (x[2].y + x[1].z) * invr;
  360. real.w = (x[0].z - x[2].x) * invr;
  361. }
  362. else
  363. {
  364. T const r = sqrt(T(1) + x[2].z - x[0].x - x[1].y);
  365. T const invr = static_cast<T>(0.5) / r;
  366. real.x = (x[0].z + x[2].x) * invr;
  367. real.y = (x[2].y + x[1].z) * invr;
  368. real.z = static_cast<T>(0.5) * r;
  369. real.w = (x[1].x - x[0].y) * invr;
  370. }
  371. detail::tquat<T, P> dual;
  372. dual.x = T(0.5) * ( x[0].w * real.w + x[1].w * real.z - x[2].w * real.y);
  373. dual.y = T(0.5) * (-x[0].w * real.z + x[1].w * real.w + x[2].w * real.x);
  374. dual.z = T(0.5) * ( x[0].w * real.y - x[1].w * real.x + x[2].w * real.w);
  375. dual.w = -T(0.5) * ( x[0].w * real.x + x[1].w * real.y + x[2].w * real.z);
  376. return detail::tdualquat<T, P>(real, dual);
  377. }
  378. }//namespace glm