quat_operations.hpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486
  1. #ifndef BOOST_QVM_QUAT_OPERATIONS
  2. #define BOOST_QVM_QUAT_OPERATIONS
  3. /// Copyright (c) 2008-2021 Emil Dotchevski and Reverge Studios, Inc.
  4. /// Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. /// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/qvm/detail/quat_assign.hpp>
  7. #include <boost/qvm/deduce_quat.hpp>
  8. #include <boost/qvm/mat_traits.hpp>
  9. #include <boost/qvm/scalar_traits.hpp>
  10. #include <boost/qvm/math.hpp>
  11. #include <boost/qvm/assert.hpp>
  12. #include <boost/qvm/error.hpp>
  13. #include <boost/qvm/throw_exception.hpp>
  14. #include <string>
  15. namespace boost { namespace qvm {
  16. namespace
  17. qvm_detail
  18. {
  19. BOOST_QVM_INLINE_CRITICAL
  20. void const *
  21. get_valid_ptr_quat_operations()
  22. {
  23. static int const obj=0;
  24. return &obj;
  25. }
  26. }
  27. ////////////////////////////////////////////////
  28. namespace
  29. msvc_parse_bug_workaround
  30. {
  31. template <class A,class B>
  32. struct
  33. quats
  34. {
  35. static bool const value=is_quat<A>::value && is_quat<B>::value;
  36. };
  37. }
  38. namespace
  39. qvm_to_string_detail
  40. {
  41. template <class T>
  42. std::string to_string( T const & x );
  43. }
  44. template <class A>
  45. inline
  46. typename enable_if_c<
  47. is_quat<A>::value,
  48. std::string>::type
  49. to_string( A const & a )
  50. {
  51. using namespace qvm_to_string_detail;
  52. return '('+
  53. to_string(quat_traits<A>::template read_element<0>(a))+','+
  54. to_string(quat_traits<A>::template read_element<1>(a))+','+
  55. to_string(quat_traits<A>::template read_element<2>(a))+','+
  56. to_string(quat_traits<A>::template read_element<3>(a))+')';
  57. }
  58. ////////////////////////////////////////////////
  59. template <class A,class B,class Cmp>
  60. BOOST_QVM_INLINE_OPERATIONS
  61. typename enable_if_c<
  62. is_quat<A>::value && is_quat<B>::value,
  63. bool>::type
  64. cmp( A const & a, B const & b, Cmp f )
  65. {
  66. typedef typename quat_traits<A>::scalar_type T;
  67. typedef typename quat_traits<B>::scalar_type U;
  68. T q1[4] =
  69. {
  70. quat_traits<A>::template read_element<0>(a),
  71. quat_traits<A>::template read_element<1>(a),
  72. quat_traits<A>::template read_element<2>(a),
  73. quat_traits<A>::template read_element<3>(a)
  74. };
  75. U q2[4] =
  76. {
  77. quat_traits<B>::template read_element<0>(b),
  78. quat_traits<B>::template read_element<1>(b),
  79. quat_traits<B>::template read_element<2>(b),
  80. quat_traits<B>::template read_element<3>(b)
  81. };
  82. int i;
  83. for( i=0; i!=4; ++i )
  84. if( !f(q1[i],q2[i]) )
  85. break;
  86. if( i==4 )
  87. return true;
  88. for( i=0; i!=4; ++i )
  89. if( !f(q1[i],-q2[i]) )
  90. return false;
  91. return true;
  92. }
  93. ////////////////////////////////////////////////
  94. template <class R,class A>
  95. BOOST_QVM_INLINE_TRIVIAL
  96. typename enable_if_c<
  97. is_quat<R>::value && is_quat<A>::value,
  98. R>::type
  99. convert_to( A const & a )
  100. {
  101. R r;
  102. quat_traits<R>::template write_element<0>(r) = quat_traits<A>::template read_element<0>(a);
  103. quat_traits<R>::template write_element<1>(r) = quat_traits<A>::template read_element<1>(a);
  104. quat_traits<R>::template write_element<2>(r) = quat_traits<A>::template read_element<2>(a);
  105. quat_traits<R>::template write_element<3>(r) = quat_traits<A>::template read_element<3>(a);
  106. return r;
  107. }
  108. template <class R,class A>
  109. BOOST_QVM_INLINE_OPERATIONS
  110. typename enable_if_c<
  111. is_quat<R>::value && is_mat<A>::value &&
  112. mat_traits<A>::rows==3 && mat_traits<A>::cols==3,
  113. R>::type
  114. convert_to( A const & a )
  115. {
  116. typedef typename mat_traits<A>::scalar_type T;
  117. T const mat[3][3] =
  118. {
  119. { mat_traits<A>::template read_element<0,0>(a), mat_traits<A>::template read_element<0,1>(a), mat_traits<A>::template read_element<0,2>(a) },
  120. { mat_traits<A>::template read_element<1,0>(a), mat_traits<A>::template read_element<1,1>(a), mat_traits<A>::template read_element<1,2>(a) },
  121. { mat_traits<A>::template read_element<2,0>(a), mat_traits<A>::template read_element<2,1>(a), mat_traits<A>::template read_element<2,2>(a) }
  122. };
  123. R r;
  124. if( mat[0][0]+mat[1][1]+mat[2][2] > scalar_traits<T>::value(0) )
  125. {
  126. T t = mat[0][0] + mat[1][1] + mat[2][2] + scalar_traits<T>::value(1);
  127. T s = (scalar_traits<T>::value(1)/sqrt<T>(t))/2;
  128. quat_traits<R>::template write_element<0>(r)=s*t;
  129. quat_traits<R>::template write_element<1>(r)=(mat[2][1]-mat[1][2])*s;
  130. quat_traits<R>::template write_element<2>(r)=(mat[0][2]-mat[2][0])*s;
  131. quat_traits<R>::template write_element<3>(r)=(mat[1][0]-mat[0][1])*s;
  132. }
  133. else if( mat[0][0]>mat[1][1] && mat[0][0]>mat[2][2] )
  134. {
  135. T t = mat[0][0] - mat[1][1] - mat[2][2] + scalar_traits<T>::value(1);
  136. T s = (scalar_traits<T>::value(1)/sqrt<T>(t))/2;
  137. quat_traits<R>::template write_element<0>(r)=(mat[2][1]-mat[1][2])*s;
  138. quat_traits<R>::template write_element<1>(r)=s*t;
  139. quat_traits<R>::template write_element<2>(r)=(mat[1][0]+mat[0][1])*s;
  140. quat_traits<R>::template write_element<3>(r)=(mat[0][2]+mat[2][0])*s;
  141. }
  142. else if( mat[1][1]>mat[2][2] )
  143. {
  144. T t = - mat[0][0] + mat[1][1] - mat[2][2] + scalar_traits<T>::value(1);
  145. T s = (scalar_traits<T>::value(1)/sqrt<T>(t))/2;
  146. quat_traits<R>::template write_element<0>(r)=(mat[0][2]-mat[2][0])*s;
  147. quat_traits<R>::template write_element<1>(r)=(mat[1][0]+mat[0][1])*s;
  148. quat_traits<R>::template write_element<2>(r)=s*t;
  149. quat_traits<R>::template write_element<3>(r)=(mat[2][1]+mat[1][2])*s;
  150. }
  151. else
  152. {
  153. T t = - mat[0][0] - mat[1][1] + mat[2][2] + scalar_traits<T>::value(1);
  154. T s = (scalar_traits<T>::value(1)/sqrt<T>(t))/2;
  155. quat_traits<R>::template write_element<0>(r)=(mat[1][0]-mat[0][1])*s;
  156. quat_traits<R>::template write_element<1>(r)=(mat[0][2]+mat[2][0])*s;
  157. quat_traits<R>::template write_element<2>(r)=(mat[2][1]+mat[1][2])*s;
  158. quat_traits<R>::template write_element<3>(r)=s*t;
  159. }
  160. return r;
  161. }
  162. ////////////////////////////////////////////////
  163. template <class A>
  164. BOOST_QVM_INLINE_OPERATIONS
  165. typename lazy_enable_if_c<
  166. is_quat<A>::value,
  167. deduce_quat<A> >::type
  168. conjugate( A const & a )
  169. {
  170. typedef typename deduce_quat<A>::type R;
  171. R r;
  172. quat_traits<R>::template write_element<0>(r)=quat_traits<A>::template read_element<0>(a);
  173. quat_traits<R>::template write_element<1>(r)=-quat_traits<A>::template read_element<1>(a);
  174. quat_traits<R>::template write_element<2>(r)=-quat_traits<A>::template read_element<2>(a);
  175. quat_traits<R>::template write_element<3>(r)=-quat_traits<A>::template read_element<3>(a);
  176. return r;
  177. }
  178. ////////////////////////////////////////////////
  179. namespace
  180. qvm_detail
  181. {
  182. template <class T>
  183. class
  184. identity_quat_
  185. {
  186. identity_quat_( identity_quat_ const & );
  187. identity_quat_ & operator=( identity_quat_ const & );
  188. ~identity_quat_();
  189. public:
  190. template <class R>
  191. BOOST_QVM_INLINE_TRIVIAL
  192. operator R() const
  193. {
  194. R r;
  195. assign(r,*this);
  196. return r;
  197. }
  198. };
  199. }
  200. template <class T>
  201. struct
  202. quat_traits< qvm_detail::identity_quat_<T> >
  203. {
  204. typedef qvm_detail::identity_quat_<T> this_quaternion;
  205. typedef T scalar_type;
  206. template <int I>
  207. static
  208. BOOST_QVM_INLINE_CRITICAL
  209. scalar_type
  210. read_element( this_quaternion const & x )
  211. {
  212. BOOST_QVM_STATIC_ASSERT(I>=0);
  213. BOOST_QVM_STATIC_ASSERT(I<4);
  214. return scalar_traits<T>::value(I==0);
  215. }
  216. static
  217. BOOST_QVM_INLINE_CRITICAL
  218. scalar_type
  219. read_element_idx( int i, this_quaternion const & x )
  220. {
  221. BOOST_QVM_ASSERT(i>=0);
  222. BOOST_QVM_ASSERT(i<4);
  223. return scalar_traits<T>::value(i==0);
  224. }
  225. };
  226. template <class T>
  227. struct
  228. deduce_quat< qvm_detail::identity_quat_<T> >
  229. {
  230. typedef quat<T> type;
  231. };
  232. template <class T>
  233. struct
  234. deduce_quat2< qvm_detail::identity_quat_<T>, qvm_detail::identity_quat_<T> >
  235. {
  236. typedef quat<T> type;
  237. };
  238. template <class T>
  239. BOOST_QVM_INLINE_TRIVIAL
  240. qvm_detail::identity_quat_<T> const &
  241. identity_quat()
  242. {
  243. return *(qvm_detail::identity_quat_<T> const *)qvm_detail::get_valid_ptr_quat_operations();
  244. }
  245. template <class A>
  246. BOOST_QVM_INLINE_OPERATIONS
  247. typename enable_if_c<
  248. is_quat<A>::value,
  249. void>::type
  250. set_identity( A & a )
  251. {
  252. typedef typename quat_traits<A>::scalar_type T;
  253. T const zero=scalar_traits<T>::value(0);
  254. T const one=scalar_traits<T>::value(1);
  255. quat_traits<A>::template write_element<0>(a) = one;
  256. quat_traits<A>::template write_element<1>(a) = zero;
  257. quat_traits<A>::template write_element<2>(a) = zero;
  258. quat_traits<A>::template write_element<3>(a) = zero;
  259. }
  260. ////////////////////////////////////////////////
  261. namespace
  262. qvm_detail
  263. {
  264. template <class OriginalType,class Scalar>
  265. class
  266. quaternion_scalar_cast_
  267. {
  268. quaternion_scalar_cast_( quaternion_scalar_cast_ const & );
  269. quaternion_scalar_cast_ & operator=( quaternion_scalar_cast_ const & );
  270. ~quaternion_scalar_cast_();
  271. public:
  272. template <class T>
  273. BOOST_QVM_INLINE_TRIVIAL
  274. quaternion_scalar_cast_ &
  275. operator=( T const & x )
  276. {
  277. assign(*this,x);
  278. return *this;
  279. }
  280. template <class R>
  281. BOOST_QVM_INLINE_TRIVIAL
  282. operator R() const
  283. {
  284. R r;
  285. assign(r,*this);
  286. return r;
  287. }
  288. };
  289. template <bool> struct scalar_cast_quaternion_filter { };
  290. template <> struct scalar_cast_quaternion_filter<true> { typedef int type; };
  291. }
  292. template <class OriginalType,class Scalar>
  293. struct
  294. quat_traits< qvm_detail::quaternion_scalar_cast_<OriginalType,Scalar> >
  295. {
  296. typedef Scalar scalar_type;
  297. typedef qvm_detail::quaternion_scalar_cast_<OriginalType,Scalar> this_quaternion;
  298. template <int I>
  299. static
  300. BOOST_QVM_INLINE_CRITICAL
  301. scalar_type
  302. read_element( this_quaternion const & x )
  303. {
  304. BOOST_QVM_STATIC_ASSERT(I>=0);
  305. BOOST_QVM_STATIC_ASSERT(I<4);
  306. return scalar_type(quat_traits<OriginalType>::template read_element<I>(reinterpret_cast<OriginalType const &>(x)));
  307. }
  308. static
  309. BOOST_QVM_INLINE_CRITICAL
  310. scalar_type
  311. read_element_idx( int i, this_quaternion const & x )
  312. {
  313. BOOST_QVM_ASSERT(i>=0);
  314. BOOST_QVM_ASSERT(i<4);
  315. return scalar_type(quat_traits<OriginalType>::read_element_idx(i,reinterpret_cast<OriginalType const &>(x)));
  316. }
  317. };
  318. template <class Scalar,class T>
  319. BOOST_QVM_INLINE_TRIVIAL
  320. qvm_detail::quaternion_scalar_cast_<T,Scalar> const &
  321. scalar_cast( T const & x, typename qvm_detail::scalar_cast_quaternion_filter<is_quat<T>::value>::type=0 )
  322. {
  323. return reinterpret_cast<qvm_detail::quaternion_scalar_cast_<T,Scalar> const &>(x);
  324. }
  325. ////////////////////////////////////////////////
  326. template <class A,class B>
  327. BOOST_QVM_INLINE_OPERATIONS
  328. typename enable_if_c<
  329. is_quat<A>::value && is_scalar<B>::value,
  330. A &>::type
  331. operator/=( A & a, B b )
  332. {
  333. quat_traits<A>::template write_element<0>(a)/=b;
  334. quat_traits<A>::template write_element<1>(a)/=b;
  335. quat_traits<A>::template write_element<2>(a)/=b;
  336. quat_traits<A>::template write_element<3>(a)/=b;
  337. return a;
  338. }
  339. template <class A,class B>
  340. BOOST_QVM_INLINE_OPERATIONS
  341. typename lazy_enable_if_c<
  342. is_quat<A>::value && is_scalar<B>::value,
  343. deduce_quat2<A,B> >::type
  344. operator/( A const & a, B b )
  345. {
  346. typedef typename deduce_quat2<A,B>::type R;
  347. R r;
  348. quat_traits<R>::template write_element<0>(r) = quat_traits<A>::template read_element<0>(a)/b;
  349. quat_traits<R>::template write_element<1>(r) = quat_traits<A>::template read_element<1>(a)/b;
  350. quat_traits<R>::template write_element<2>(r) = quat_traits<A>::template read_element<2>(a)/b;
  351. quat_traits<R>::template write_element<3>(r) = quat_traits<A>::template read_element<3>(a)/b;
  352. return r;
  353. }
  354. template <class A,class B>
  355. BOOST_QVM_INLINE_OPERATIONS
  356. typename lazy_enable_if_c<
  357. is_quat<A>::value && is_quat<B>::value,
  358. deduce_scalar<typename quat_traits<A>::scalar_type,typename quat_traits<B>::scalar_type> >::type
  359. dot( A const & a, B const & b )
  360. {
  361. typedef typename quat_traits<A>::scalar_type Ta;
  362. typedef typename quat_traits<B>::scalar_type Tb;
  363. typedef typename deduce_scalar<Ta,Tb>::type Tr;
  364. Ta const a0=quat_traits<A>::template read_element<0>(a);
  365. Ta const a1=quat_traits<A>::template read_element<1>(a);
  366. Ta const a2=quat_traits<A>::template read_element<2>(a);
  367. Ta const a3=quat_traits<A>::template read_element<3>(a);
  368. Tb const b0=quat_traits<B>::template read_element<0>(b);
  369. Tb const b1=quat_traits<B>::template read_element<1>(b);
  370. Tb const b2=quat_traits<B>::template read_element<2>(b);
  371. Tb const b3=quat_traits<B>::template read_element<3>(b);
  372. Tr const dp=a0*b0+a1*b1+a2*b2+a3*b3;
  373. return dp;
  374. }
  375. template <class A,class B>
  376. BOOST_QVM_INLINE_OPERATIONS
  377. typename enable_if_c<
  378. is_quat<A>::value && is_quat<B>::value,
  379. bool>::type
  380. operator==( A const & a, B const & b )
  381. {
  382. return
  383. quat_traits<A>::template read_element<0>(a)==quat_traits<B>::template read_element<0>(b) &&
  384. quat_traits<A>::template read_element<1>(a)==quat_traits<B>::template read_element<1>(b) &&
  385. quat_traits<A>::template read_element<2>(a)==quat_traits<B>::template read_element<2>(b) &&
  386. quat_traits<A>::template read_element<3>(a)==quat_traits<B>::template read_element<3>(b);
  387. }
  388. template <class A>
  389. BOOST_QVM_INLINE_OPERATIONS
  390. typename lazy_enable_if_c<
  391. is_quat<A>::value,
  392. deduce_quat<A> >::type
  393. inverse( A const & a )
  394. {
  395. typedef typename deduce_quat<A>::type R;
  396. typedef typename quat_traits<A>::scalar_type TA;
  397. TA aa = quat_traits<A>::template read_element<0>(a);
  398. TA ab = quat_traits<A>::template read_element<1>(a);
  399. TA ac = quat_traits<A>::template read_element<2>(a);
  400. TA ad = quat_traits<A>::template read_element<3>(a);
  401. TA m2 = ab*ab + ac*ac + ad*ad + aa*aa;
  402. if( m2==scalar_traits<TA>::value(0) )
  403. BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
  404. TA rm=scalar_traits<TA>::value(1)/m2;
  405. R r;
  406. quat_traits<R>::template write_element<0>(r) = aa*rm;
  407. quat_traits<R>::template write_element<1>(r) = -ab*rm;
  408. quat_traits<R>::template write_element<2>(r) = -ac*rm;
  409. quat_traits<R>::template write_element<3>(r) = -ad*rm;
  410. return r;
  411. }
  412. template <class A>
  413. BOOST_QVM_INLINE_OPERATIONS
  414. typename enable_if_c<
  415. is_quat<A>::value,
  416. typename quat_traits<A>::scalar_type>::type
  417. mag_sqr( A const & a )
  418. {
  419. typedef typename quat_traits<A>::scalar_type T;
  420. T x=quat_traits<A>::template read_element<0>(a);
  421. T y=quat_traits<A>::template read_element<1>(a);
  422. T z=quat_traits<A>::template read_element<2>(a);
  423. T w=quat_traits<A>::template read_element<3>(a);
  424. return x*x+y*y+z*z+w*w;
  425. }
  426. template <class A>
  427. BOOST_QVM_INLINE_OPERATIONS
  428. typename enable_if_c<
  429. is_quat<A>::value,
  430. typename quat_traits<A>::scalar_type>::type
  431. mag( A const & a )
  432. {
  433. typedef typename quat_traits<A>::scalar_type T;
  434. T x=quat_traits<A>::template read_element<0>(a);
  435. T y=quat_traits<A>::template read_element<1>(a);
  436. T z=quat_traits<A>::template read_element<2>(a);
  437. T w=quat_traits<A>::template read_element<3>(a);
  438. return sqrt<T>(x*x+y*y+z*z+w*w);
  439. }
  440. template <class A,class B>
  441. BOOST_QVM_INLINE_OPERATIONS
  442. typename enable_if<
  443. msvc_parse_bug_workaround::quats<A,B>,
  444. A &>::type
  445. operator-=( A & a, B const & b )
  446. {
  447. quat_traits<A>::template write_element<0>(a)-=quat_traits<B>::template read_element<0>(b);
  448. quat_traits<A>::template write_element<1>(a)-=quat_traits<B>::template read_element<1>(b);
  449. quat_traits<A>::template write_element<2>(a)-=quat_traits<B>::template read_element<2>(b);
  450. quat_traits<A>::template write_element<3>(a)-=quat_traits<B>::template read_element<3>(b);
  451. return a;
  452. }
  453. template <class A,class B>
  454. BOOST_QVM_INLINE_OPERATIONS
  455. typename lazy_enable_if_c<
  456. is_quat<A>::value && is_quat<B>::value,
  457. deduce_quat2<A,B> >::type
  458. operator-( A const & a, B const & b )
  459. {
  460. typedef typename deduce_quat2<A,B>::type R;
  461. R r;
  462. quat_traits<R>::template write_element<0>(r)=quat_traits<A>::template read_element<0>(a)-quat_traits<B>::template read_element<0>(b);
  463. quat_traits<R>::template write_element<1>(r)=quat_traits<A>::template read_element<1>(a)-quat_traits<B>::template read_element<1>(b);
  464. quat_traits<R>::template write_element<2>(r)=quat_traits<A>::template read_element<2>(a)-quat_traits<B>::template read_element<2>(b);
  465. quat_traits<R>::template write_element<3>(r)=quat_traits<A>::template read_element<3>(a)-quat_traits<B>::template read_element<3>(b);
  466. return r;
  467. }
  468. template <class A>
  469. BOOST_QVM_INLINE_OPERATIONS
  470. typename lazy_enable_if_c<
  471. is_quat<A>::value,
  472. deduce_quat<A> >::type
  473. operator-( A const & a )
  474. {
  475. typedef typename deduce_quat<A>::type R;
  476. R r;
  477. quat_traits<R>::template write_element<0>(r)=-quat_traits<A>::template read_element<0>(a);
  478. quat_traits<R>::template write_element<1>(r)=-quat_traits<A>::template read_element<1>(a);
  479. quat_traits<R>::template write_element<2>(r)=-quat_traits<A>::template read_element<2>(a);
  480. quat_traits<R>::template write_element<3>(r)=-quat_traits<A>::template read_element<3>(a);
  481. return r;
  482. }
  483. template <class A,class B>
  484. BOOST_QVM_INLINE_OPERATIONS
  485. typename enable_if<
  486. msvc_parse_bug_workaround::quats<A,B>,
  487. A &>::type
  488. operator*=( A & a, B const & b )
  489. {
  490. typedef typename quat_traits<A>::scalar_type TA;
  491. typedef typename quat_traits<B>::scalar_type TB;
  492. TA const aa=quat_traits<A>::template read_element<0>(a);
  493. TA const ab=quat_traits<A>::template read_element<1>(a);
  494. TA const ac=quat_traits<A>::template read_element<2>(a);
  495. TA const ad=quat_traits<A>::template read_element<3>(a);
  496. TB const ba=quat_traits<B>::template read_element<0>(b);
  497. TB const bb=quat_traits<B>::template read_element<1>(b);
  498. TB const bc=quat_traits<B>::template read_element<2>(b);
  499. TB const bd=quat_traits<B>::template read_element<3>(b);
  500. quat_traits<A>::template write_element<0>(a) = aa*ba - ab*bb - ac*bc - ad*bd;
  501. quat_traits<A>::template write_element<1>(a) = aa*bb + ab*ba + ac*bd - ad*bc;
  502. quat_traits<A>::template write_element<2>(a) = aa*bc + ac*ba + ad*bb - ab*bd;
  503. quat_traits<A>::template write_element<3>(a) = aa*bd + ad*ba + ab*bc - ac*bb;
  504. return a;
  505. }
  506. template <class A,class B>
  507. BOOST_QVM_INLINE_OPERATIONS
  508. typename enable_if_c<
  509. is_quat<A>::value && is_scalar<B>::value,
  510. A &>::type
  511. operator*=( A & a, B b )
  512. {
  513. quat_traits<A>::template write_element<0>(a)*=b;
  514. quat_traits<A>::template write_element<1>(a)*=b;
  515. quat_traits<A>::template write_element<2>(a)*=b;
  516. quat_traits<A>::template write_element<3>(a)*=b;
  517. return a;
  518. }
  519. template <class A,class B>
  520. BOOST_QVM_INLINE_OPERATIONS
  521. typename lazy_enable_if_c<
  522. is_quat<A>::value && is_quat<B>::value,
  523. deduce_quat2<A,B> >::type
  524. operator*( A const & a, B const & b )
  525. {
  526. typedef typename deduce_quat2<A,B>::type R;
  527. typedef typename quat_traits<A>::scalar_type TA;
  528. typedef typename quat_traits<B>::scalar_type TB;
  529. TA const aa=quat_traits<A>::template read_element<0>(a);
  530. TA const ab=quat_traits<A>::template read_element<1>(a);
  531. TA const ac=quat_traits<A>::template read_element<2>(a);
  532. TA const ad=quat_traits<A>::template read_element<3>(a);
  533. TB const ba=quat_traits<B>::template read_element<0>(b);
  534. TB const bb=quat_traits<B>::template read_element<1>(b);
  535. TB const bc=quat_traits<B>::template read_element<2>(b);
  536. TB const bd=quat_traits<B>::template read_element<3>(b);
  537. R r;
  538. quat_traits<R>::template write_element<0>(r) = aa*ba - ab*bb - ac*bc - ad*bd;
  539. quat_traits<R>::template write_element<1>(r) = aa*bb + ab*ba + ac*bd - ad*bc;
  540. quat_traits<R>::template write_element<2>(r) = aa*bc + ac*ba + ad*bb - ab*bd;
  541. quat_traits<R>::template write_element<3>(r) = aa*bd + ad*ba + ab*bc - ac*bb;
  542. return r;
  543. }
  544. template <class A,class B>
  545. BOOST_QVM_INLINE_OPERATIONS
  546. typename lazy_enable_if_c2<
  547. is_quat<A>::value && is_scalar<B>::value,
  548. deduce_quat2<A,B> >::type
  549. operator*( A const & a, B b )
  550. {
  551. typedef typename deduce_quat2<A,B>::type R;
  552. R r;
  553. quat_traits<R>::template write_element<0>(r)=quat_traits<A>::template read_element<0>(a)*b;
  554. quat_traits<R>::template write_element<1>(r)=quat_traits<A>::template read_element<1>(a)*b;
  555. quat_traits<R>::template write_element<2>(r)=quat_traits<A>::template read_element<2>(a)*b;
  556. quat_traits<R>::template write_element<3>(r)=quat_traits<A>::template read_element<3>(a)*b;
  557. return r;
  558. }
  559. template <class A,class B>
  560. BOOST_QVM_INLINE_OPERATIONS
  561. typename enable_if_c<
  562. is_quat<A>::value && is_quat<B>::value,
  563. bool>::type
  564. operator!=( A const & a, B const & b )
  565. {
  566. return
  567. quat_traits<A>::template read_element<0>(a)!=quat_traits<B>::template read_element<0>(b) ||
  568. quat_traits<A>::template read_element<1>(a)!=quat_traits<B>::template read_element<1>(b) ||
  569. quat_traits<A>::template read_element<2>(a)!=quat_traits<B>::template read_element<2>(b) ||
  570. quat_traits<A>::template read_element<3>(a)!=quat_traits<B>::template read_element<3>(b);
  571. }
  572. template <class A>
  573. BOOST_QVM_INLINE_OPERATIONS
  574. typename lazy_enable_if_c<
  575. is_quat<A>::value,
  576. deduce_quat<A> >::type
  577. normalized( A const & a )
  578. {
  579. typedef typename quat_traits<A>::scalar_type T;
  580. T const a0=quat_traits<A>::template read_element<0>(a);
  581. T const a1=quat_traits<A>::template read_element<1>(a);
  582. T const a2=quat_traits<A>::template read_element<2>(a);
  583. T const a3=quat_traits<A>::template read_element<3>(a);
  584. T const m2=a0*a0+a1*a1+a2*a2+a3*a3;
  585. if( m2==scalar_traits<typename quat_traits<A>::scalar_type>::value(0) )
  586. BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
  587. T const rm=scalar_traits<T>::value(1)/sqrt<T>(m2);
  588. typedef typename deduce_quat<A>::type R;
  589. R r;
  590. quat_traits<R>::template write_element<0>(r)=a0*rm;
  591. quat_traits<R>::template write_element<1>(r)=a1*rm;
  592. quat_traits<R>::template write_element<2>(r)=a2*rm;
  593. quat_traits<R>::template write_element<3>(r)=a3*rm;
  594. return r;
  595. }
  596. template <class A>
  597. BOOST_QVM_INLINE_OPERATIONS
  598. typename enable_if_c<
  599. is_quat<A>::value,
  600. void>::type
  601. normalize( A & a )
  602. {
  603. typedef typename quat_traits<A>::scalar_type T;
  604. T const a0=quat_traits<A>::template read_element<0>(a);
  605. T const a1=quat_traits<A>::template read_element<1>(a);
  606. T const a2=quat_traits<A>::template read_element<2>(a);
  607. T const a3=quat_traits<A>::template read_element<3>(a);
  608. T const m2=a0*a0+a1*a1+a2*a2+a3*a3;
  609. if( m2==scalar_traits<typename quat_traits<A>::scalar_type>::value(0) )
  610. BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
  611. T const rm=scalar_traits<T>::value(1)/sqrt<T>(m2);
  612. quat_traits<A>::template write_element<0>(a)*=rm;
  613. quat_traits<A>::template write_element<1>(a)*=rm;
  614. quat_traits<A>::template write_element<2>(a)*=rm;
  615. quat_traits<A>::template write_element<3>(a)*=rm;
  616. }
  617. template <class A,class B>
  618. BOOST_QVM_INLINE_OPERATIONS
  619. typename enable_if<
  620. msvc_parse_bug_workaround::quats<A,B>,
  621. A &>::type
  622. operator+=( A & a, B const & b )
  623. {
  624. quat_traits<A>::template write_element<0>(a)+=quat_traits<B>::template read_element<0>(b);
  625. quat_traits<A>::template write_element<1>(a)+=quat_traits<B>::template read_element<1>(b);
  626. quat_traits<A>::template write_element<2>(a)+=quat_traits<B>::template read_element<2>(b);
  627. quat_traits<A>::template write_element<3>(a)+=quat_traits<B>::template read_element<3>(b);
  628. return a;
  629. }
  630. template <class A,class B>
  631. BOOST_QVM_INLINE_OPERATIONS
  632. typename lazy_enable_if_c<
  633. is_quat<A>::value && is_quat<B>::value,
  634. deduce_quat2<A,B> >::type
  635. operator+( A const & a, B const & b )
  636. {
  637. typedef typename deduce_quat2<A,B>::type R;
  638. R r;
  639. quat_traits<R>::template write_element<0>(r)=quat_traits<A>::template read_element<0>(a)+quat_traits<B>::template read_element<0>(b);
  640. quat_traits<R>::template write_element<1>(r)=quat_traits<A>::template read_element<1>(a)+quat_traits<B>::template read_element<1>(b);
  641. quat_traits<R>::template write_element<2>(r)=quat_traits<A>::template read_element<2>(a)+quat_traits<B>::template read_element<2>(b);
  642. quat_traits<R>::template write_element<3>(r)=quat_traits<A>::template read_element<3>(a)+quat_traits<B>::template read_element<3>(b);
  643. return r;
  644. }
  645. template <class A,class B,class C>
  646. BOOST_QVM_INLINE_OPERATIONS
  647. typename lazy_enable_if_c<
  648. is_quat<A>::value && is_quat<B>::value && is_scalar<C>::value,
  649. deduce_quat2<A,B> >::type
  650. slerp( A const & a, B const & b, C t )
  651. {
  652. typedef typename deduce_quat2<A,B>::type R;
  653. typedef typename quat_traits<R>::scalar_type TR;
  654. TR const one = scalar_traits<TR>::value(1);
  655. TR dp = dot(a,b);
  656. TR sc=one;
  657. if( dp < one )
  658. {
  659. TR const theta = acos<TR>(dp);
  660. TR const invsintheta = one/sin<TR>(theta);
  661. TR const scale = sin<TR>(theta*(one-t)) * invsintheta;
  662. TR const invscale = sin<TR>(theta*t) * invsintheta * sc;
  663. return a*scale + b*invscale;
  664. }
  665. else
  666. return normalized(a+(b-a)*t);
  667. }
  668. ////////////////////////////////////////////////
  669. namespace
  670. qvm_detail
  671. {
  672. template <class T>
  673. class
  674. qref_
  675. {
  676. qref_( qref_ const & );
  677. qref_ & operator=( qref_ const & );
  678. ~qref_();
  679. public:
  680. template <class R>
  681. BOOST_QVM_INLINE_TRIVIAL
  682. qref_ &
  683. operator=( R const & x )
  684. {
  685. assign(*this,x);
  686. return *this;
  687. }
  688. template <class R>
  689. BOOST_QVM_INLINE_TRIVIAL
  690. operator R() const
  691. {
  692. R r;
  693. assign(r,*this);
  694. return r;
  695. }
  696. };
  697. }
  698. template <class Q>
  699. struct quat_traits;
  700. template <class Q>
  701. struct
  702. quat_traits< qvm_detail::qref_<Q> >
  703. {
  704. typedef typename quat_traits<Q>::scalar_type scalar_type;
  705. typedef qvm_detail::qref_<Q> this_quaternion;
  706. template <int I>
  707. static
  708. BOOST_QVM_INLINE_CRITICAL
  709. scalar_type
  710. read_element( this_quaternion const & x )
  711. {
  712. BOOST_QVM_STATIC_ASSERT(I>=0);
  713. BOOST_QVM_STATIC_ASSERT(I<4);
  714. return quat_traits<Q>::template read_element<I>(reinterpret_cast<Q const &>(x));
  715. }
  716. template <int I>
  717. static
  718. BOOST_QVM_INLINE_CRITICAL
  719. scalar_type &
  720. write_element( this_quaternion & x )
  721. {
  722. BOOST_QVM_STATIC_ASSERT(I>=0);
  723. BOOST_QVM_STATIC_ASSERT(I<4);
  724. return quat_traits<Q>::template write_element<I>(reinterpret_cast<Q &>(x));
  725. }
  726. };
  727. template <class Q>
  728. struct
  729. deduce_quat< qvm_detail::qref_<Q> >
  730. {
  731. typedef quat<typename quat_traits<Q>::scalar_type> type;
  732. };
  733. template <class Q>
  734. BOOST_QVM_INLINE_TRIVIAL
  735. typename enable_if_c<
  736. is_quat<Q>::value,
  737. qvm_detail::qref_<Q> const &>::type
  738. qref( Q const & a )
  739. {
  740. return reinterpret_cast<qvm_detail::qref_<Q> const &>(a);
  741. }
  742. template <class Q>
  743. BOOST_QVM_INLINE_TRIVIAL
  744. typename enable_if_c<
  745. is_quat<Q>::value,
  746. qvm_detail::qref_<Q> &>::type
  747. qref( Q & a )
  748. {
  749. return reinterpret_cast<qvm_detail::qref_<Q> &>(a);
  750. }
  751. ////////////////////////////////////////////////
  752. namespace
  753. qvm_detail
  754. {
  755. template <class T>
  756. class
  757. zero_q_
  758. {
  759. zero_q_( zero_q_ const & );
  760. zero_q_ & operator=( zero_q_ const & );
  761. ~zero_q_();
  762. public:
  763. template <class R>
  764. BOOST_QVM_INLINE_TRIVIAL
  765. operator R() const
  766. {
  767. R r;
  768. assign(r,*this);
  769. return r;
  770. }
  771. };
  772. }
  773. template <class T>
  774. struct
  775. quat_traits< qvm_detail::zero_q_<T> >
  776. {
  777. typedef qvm_detail::zero_q_<T> this_quaternion;
  778. typedef T scalar_type;
  779. template <int I>
  780. static
  781. BOOST_QVM_INLINE_CRITICAL
  782. scalar_type
  783. read_element( this_quaternion const & x )
  784. {
  785. BOOST_QVM_STATIC_ASSERT(I>=0);
  786. BOOST_QVM_STATIC_ASSERT(I<4);
  787. return scalar_traits<scalar_type>::value(0);
  788. }
  789. static
  790. BOOST_QVM_INLINE_CRITICAL
  791. scalar_type
  792. read_element_idx( int i, this_quaternion const & x )
  793. {
  794. BOOST_QVM_ASSERT(i>=0);
  795. BOOST_QVM_ASSERT(i<4);
  796. return scalar_traits<scalar_type>::value(0);
  797. }
  798. };
  799. template <class T>
  800. BOOST_QVM_INLINE_TRIVIAL
  801. qvm_detail::zero_q_<T> const &
  802. zero_quat()
  803. {
  804. return *(qvm_detail::zero_q_<T> const *)qvm_detail::get_valid_ptr_quat_operations();
  805. }
  806. template <class A>
  807. BOOST_QVM_INLINE_OPERATIONS
  808. typename enable_if_c<
  809. is_quat<A>::value,
  810. void>::type
  811. set_zero( A & a )
  812. {
  813. typedef typename quat_traits<A>::scalar_type T;
  814. T const zero=scalar_traits<T>::value(0);
  815. quat_traits<A>::template write_element<0>(a) = zero;
  816. quat_traits<A>::template write_element<1>(a) = zero;
  817. quat_traits<A>::template write_element<2>(a) = zero;
  818. quat_traits<A>::template write_element<3>(a) = zero;
  819. }
  820. ////////////////////////////////////////////////
  821. namespace
  822. qvm_detail
  823. {
  824. template <class V>
  825. struct
  826. rot_quat_
  827. {
  828. typedef typename vec_traits<V>::scalar_type scalar_type;
  829. scalar_type a[4];
  830. template <class Angle>
  831. BOOST_QVM_INLINE
  832. rot_quat_( V const & axis, Angle angle )
  833. {
  834. scalar_type const x=vec_traits<V>::template read_element<0>(axis);
  835. scalar_type const y=vec_traits<V>::template read_element<1>(axis);
  836. scalar_type const z=vec_traits<V>::template read_element<2>(axis);
  837. scalar_type const m2=x*x+y*y+z*z;
  838. if( m2==scalar_traits<scalar_type>::value(0) )
  839. BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
  840. scalar_type const rm=scalar_traits<scalar_type>::value(1)/sqrt<scalar_type>(m2);
  841. angle/=2;
  842. scalar_type const s=sin<Angle>(angle);
  843. a[0] = cos<Angle>(angle);
  844. a[1] = rm*x*s;
  845. a[2] = rm*y*s;
  846. a[3] = rm*z*s;
  847. }
  848. template <class R>
  849. BOOST_QVM_INLINE_TRIVIAL
  850. operator R() const
  851. {
  852. R r;
  853. assign(r,*this);
  854. return r;
  855. }
  856. };
  857. }
  858. template <class V>
  859. struct
  860. quat_traits< qvm_detail::rot_quat_<V> >
  861. {
  862. typedef qvm_detail::rot_quat_<V> this_quaternion;
  863. typedef typename this_quaternion::scalar_type scalar_type;
  864. template <int I>
  865. static
  866. BOOST_QVM_INLINE_CRITICAL
  867. scalar_type
  868. read_element( this_quaternion const & x )
  869. {
  870. BOOST_QVM_STATIC_ASSERT(I>=0);
  871. BOOST_QVM_STATIC_ASSERT(I<4);
  872. return x.a[I];
  873. }
  874. };
  875. template <class V>
  876. struct
  877. deduce_quat< qvm_detail::rot_quat_<V> >
  878. {
  879. typedef quat<typename vec_traits<V>::scalar_type> type;
  880. };
  881. template <class A,class Angle>
  882. BOOST_QVM_INLINE
  883. typename enable_if_c<
  884. is_vec<A>::value && vec_traits<A>::dim==3,
  885. qvm_detail::rot_quat_<A> >::type
  886. rot_quat( A const & axis, Angle angle )
  887. {
  888. return qvm_detail::rot_quat_<A>(axis,angle);
  889. }
  890. template <class A,class B,class Angle>
  891. BOOST_QVM_INLINE_OPERATIONS
  892. typename enable_if_c<
  893. is_quat<A>::value &&
  894. is_vec<B>::value && vec_traits<B>::dim==3,
  895. void>::type
  896. set_rot( A & a, B const & axis, Angle angle )
  897. {
  898. assign(a,rot_quat(axis,angle));
  899. }
  900. template <class A,class B,class Angle>
  901. BOOST_QVM_INLINE_OPERATIONS
  902. typename enable_if_c<
  903. is_quat<A>::value &&
  904. is_vec<B>::value && vec_traits<B>::dim==3,
  905. void>::type
  906. rotate( A & a, B const & axis, Angle angle )
  907. {
  908. a *= rot_quat(axis,angle);
  909. }
  910. ////////////////////////////////////////////////
  911. namespace
  912. qvm_detail
  913. {
  914. template <class T>
  915. struct
  916. rotx_quat_
  917. {
  918. BOOST_QVM_INLINE_TRIVIAL
  919. rotx_quat_()
  920. {
  921. }
  922. template <class R>
  923. BOOST_QVM_INLINE_TRIVIAL
  924. operator R() const
  925. {
  926. R r;
  927. assign(r,*this);
  928. return r;
  929. }
  930. private:
  931. rotx_quat_( rotx_quat_ const & );
  932. rotx_quat_ & operator=( rotx_quat_ const & );
  933. ~rotx_quat_();
  934. };
  935. template <int I>
  936. struct
  937. rotx_q_get
  938. {
  939. template <class T>
  940. static
  941. BOOST_QVM_INLINE_CRITICAL
  942. T
  943. get( T const & )
  944. {
  945. return scalar_traits<T>::value(0);
  946. }
  947. };
  948. template <>
  949. struct
  950. rotx_q_get<1>
  951. {
  952. template <class T>
  953. static
  954. BOOST_QVM_INLINE_CRITICAL
  955. T
  956. get( T const & angle )
  957. {
  958. return sin<T>(angle/2);
  959. }
  960. };
  961. template <>
  962. struct
  963. rotx_q_get<0>
  964. {
  965. template <class T>
  966. static
  967. BOOST_QVM_INLINE_CRITICAL
  968. T
  969. get( T const & angle )
  970. {
  971. return cos<T>(angle/2);
  972. }
  973. };
  974. }
  975. template <class Angle>
  976. struct
  977. quat_traits< qvm_detail::rotx_quat_<Angle> >
  978. {
  979. typedef qvm_detail::rotx_quat_<Angle> this_quaternion;
  980. typedef Angle scalar_type;
  981. template <int I>
  982. static
  983. BOOST_QVM_INLINE_CRITICAL
  984. scalar_type
  985. read_element( this_quaternion const & x )
  986. {
  987. BOOST_QVM_STATIC_ASSERT(I>=0);
  988. BOOST_QVM_STATIC_ASSERT(I<4);
  989. return qvm_detail::rotx_q_get<I>::get(reinterpret_cast<Angle const &>(x));
  990. }
  991. };
  992. template <class Angle>
  993. struct
  994. deduce_quat< qvm_detail::rotx_quat_<Angle> >
  995. {
  996. typedef quat<Angle> type;
  997. };
  998. template <class Angle>
  999. struct
  1000. deduce_quat2< qvm_detail::rotx_quat_<Angle>, qvm_detail::rotx_quat_<Angle> >
  1001. {
  1002. typedef quat<Angle> type;
  1003. };
  1004. template <class Angle>
  1005. BOOST_QVM_INLINE_TRIVIAL
  1006. qvm_detail::rotx_quat_<Angle> const &
  1007. rotx_quat( Angle const & angle )
  1008. {
  1009. return reinterpret_cast<qvm_detail::rotx_quat_<Angle> const &>(angle);
  1010. }
  1011. template <class A,class Angle>
  1012. BOOST_QVM_INLINE_OPERATIONS
  1013. typename enable_if_c<
  1014. is_quat<A>::value,
  1015. void>::type
  1016. set_rotx( A & a, Angle angle )
  1017. {
  1018. assign(a,rotx_quat(angle));
  1019. }
  1020. template <class A,class Angle>
  1021. BOOST_QVM_INLINE_OPERATIONS
  1022. typename enable_if_c<
  1023. is_quat<A>::value,
  1024. void>::type
  1025. rotate_x( A & a, Angle angle )
  1026. {
  1027. a *= rotx_quat(angle);
  1028. }
  1029. ////////////////////////////////////////////////
  1030. namespace
  1031. qvm_detail
  1032. {
  1033. template <class T>
  1034. struct
  1035. roty_quat_
  1036. {
  1037. BOOST_QVM_INLINE_TRIVIAL
  1038. roty_quat_()
  1039. {
  1040. }
  1041. template <class R>
  1042. BOOST_QVM_INLINE_TRIVIAL
  1043. operator R() const
  1044. {
  1045. R r;
  1046. assign(r,*this);
  1047. return r;
  1048. }
  1049. private:
  1050. roty_quat_( roty_quat_ const & );
  1051. roty_quat_ & operator=( roty_quat_ const & );
  1052. ~roty_quat_();
  1053. };
  1054. template <int I>
  1055. struct
  1056. roty_q_get
  1057. {
  1058. template <class T>
  1059. static
  1060. BOOST_QVM_INLINE_CRITICAL
  1061. T
  1062. get( T const & )
  1063. {
  1064. return scalar_traits<T>::value(0);
  1065. }
  1066. };
  1067. template <>
  1068. struct
  1069. roty_q_get<2>
  1070. {
  1071. template <class T>
  1072. static
  1073. BOOST_QVM_INLINE_CRITICAL
  1074. T
  1075. get( T const & angle )
  1076. {
  1077. return sin<T>(angle/2);
  1078. }
  1079. };
  1080. template <>
  1081. struct
  1082. roty_q_get<0>
  1083. {
  1084. template <class T>
  1085. static
  1086. BOOST_QVM_INLINE_CRITICAL
  1087. T
  1088. get( T const & angle )
  1089. {
  1090. return cos<T>(angle/2);
  1091. }
  1092. };
  1093. }
  1094. template <class Angle>
  1095. struct
  1096. quat_traits< qvm_detail::roty_quat_<Angle> >
  1097. {
  1098. typedef qvm_detail::roty_quat_<Angle> this_quaternion;
  1099. typedef Angle scalar_type;
  1100. template <int I>
  1101. static
  1102. BOOST_QVM_INLINE_CRITICAL
  1103. scalar_type
  1104. read_element( this_quaternion const & x )
  1105. {
  1106. BOOST_QVM_STATIC_ASSERT(I>=0);
  1107. BOOST_QVM_STATIC_ASSERT(I<4);
  1108. return qvm_detail::roty_q_get<I>::get(reinterpret_cast<Angle const &>(x));
  1109. }
  1110. };
  1111. template <class Angle>
  1112. struct
  1113. deduce_quat< qvm_detail::roty_quat_<Angle> >
  1114. {
  1115. typedef quat<Angle> type;
  1116. };
  1117. template <class Angle>
  1118. struct
  1119. deduce_quat2< qvm_detail::roty_quat_<Angle>, qvm_detail::roty_quat_<Angle> >
  1120. {
  1121. typedef quat<Angle> type;
  1122. };
  1123. template <class Angle>
  1124. BOOST_QVM_INLINE_TRIVIAL
  1125. qvm_detail::roty_quat_<Angle> const &
  1126. roty_quat( Angle const & angle )
  1127. {
  1128. return reinterpret_cast<qvm_detail::roty_quat_<Angle> const &>(angle);
  1129. }
  1130. template <class A,class Angle>
  1131. BOOST_QVM_INLINE_OPERATIONS
  1132. typename enable_if_c<
  1133. is_quat<A>::value,
  1134. void>::type
  1135. set_roty( A & a, Angle angle )
  1136. {
  1137. assign(a,roty_quat(angle));
  1138. }
  1139. template <class A,class Angle>
  1140. BOOST_QVM_INLINE_OPERATIONS
  1141. typename enable_if_c<
  1142. is_quat<A>::value,
  1143. void>::type
  1144. rotate_y( A & a, Angle angle )
  1145. {
  1146. a *= roty_quat(angle);
  1147. }
  1148. ////////////////////////////////////////////////
  1149. namespace
  1150. qvm_detail
  1151. {
  1152. template <class T>
  1153. struct
  1154. rotz_quat_
  1155. {
  1156. BOOST_QVM_INLINE_TRIVIAL
  1157. rotz_quat_()
  1158. {
  1159. }
  1160. template <class R>
  1161. BOOST_QVM_INLINE_TRIVIAL
  1162. operator R() const
  1163. {
  1164. R r;
  1165. assign(r,*this);
  1166. return r;
  1167. }
  1168. private:
  1169. rotz_quat_( rotz_quat_ const & );
  1170. rotz_quat_ & operator=( rotz_quat_ const & );
  1171. ~rotz_quat_();
  1172. };
  1173. template <int I>
  1174. struct
  1175. rotz_q_get
  1176. {
  1177. template <class T>
  1178. static
  1179. BOOST_QVM_INLINE_CRITICAL
  1180. T
  1181. get( T const & )
  1182. {
  1183. return scalar_traits<T>::value(0);
  1184. }
  1185. };
  1186. template <>
  1187. struct
  1188. rotz_q_get<3>
  1189. {
  1190. template <class T>
  1191. static
  1192. BOOST_QVM_INLINE_CRITICAL
  1193. T
  1194. get( T const & angle )
  1195. {
  1196. return sin<T>(angle/2);
  1197. }
  1198. };
  1199. template <>
  1200. struct
  1201. rotz_q_get<0>
  1202. {
  1203. template <class T>
  1204. static
  1205. BOOST_QVM_INLINE_CRITICAL
  1206. T
  1207. get( T const & angle )
  1208. {
  1209. return cos<T>(angle/2);
  1210. }
  1211. };
  1212. }
  1213. template <class Angle>
  1214. struct
  1215. quat_traits< qvm_detail::rotz_quat_<Angle> >
  1216. {
  1217. typedef qvm_detail::rotz_quat_<Angle> this_quaternion;
  1218. typedef Angle scalar_type;
  1219. template <int I>
  1220. static
  1221. BOOST_QVM_INLINE_CRITICAL
  1222. scalar_type
  1223. read_element( this_quaternion const & x )
  1224. {
  1225. BOOST_QVM_STATIC_ASSERT(I>=0);
  1226. BOOST_QVM_STATIC_ASSERT(I<4);
  1227. return qvm_detail::rotz_q_get<I>::get(reinterpret_cast<Angle const &>(x));
  1228. }
  1229. };
  1230. template <class Angle>
  1231. struct
  1232. deduce_quat< qvm_detail::rotz_quat_<Angle> >
  1233. {
  1234. typedef quat<Angle> type;
  1235. };
  1236. template <class Angle>
  1237. struct
  1238. deduce_quat2< qvm_detail::rotz_quat_<Angle>, qvm_detail::rotz_quat_<Angle> >
  1239. {
  1240. typedef quat<Angle> type;
  1241. };
  1242. template <class Angle>
  1243. BOOST_QVM_INLINE_TRIVIAL
  1244. qvm_detail::rotz_quat_<Angle> const &
  1245. rotz_quat( Angle const & angle )
  1246. {
  1247. return reinterpret_cast<qvm_detail::rotz_quat_<Angle> const &>(angle);
  1248. }
  1249. template <class A,class Angle>
  1250. BOOST_QVM_INLINE_OPERATIONS
  1251. typename enable_if_c<
  1252. is_quat<A>::value,
  1253. void>::type
  1254. set_rotz( A & a, Angle angle )
  1255. {
  1256. assign(a,rotz_quat(angle));
  1257. }
  1258. template <class A,class Angle>
  1259. BOOST_QVM_INLINE_OPERATIONS
  1260. typename enable_if_c<
  1261. is_quat<A>::value,
  1262. void>::type
  1263. rotate_z( A & a, Angle angle )
  1264. {
  1265. a *= rotz_quat(angle);
  1266. }
  1267. template <class A,class B>
  1268. BOOST_QVM_INLINE_OPERATIONS
  1269. typename enable_if_c<
  1270. is_quat<A>::value && is_vec<B>::value && vec_traits<B>::dim==3,
  1271. typename quat_traits<A>::scalar_type>::type
  1272. axis_angle( A const & a, B & b )
  1273. {
  1274. typedef typename quat_traits<A>::scalar_type T;
  1275. T a0=quat_traits<A>::template read_element<0>(a);
  1276. T a1=quat_traits<A>::template read_element<1>(a);
  1277. T a2=quat_traits<A>::template read_element<2>(a);
  1278. T a3=quat_traits<A>::template read_element<3>(a);
  1279. if( a0>1 )
  1280. {
  1281. T const m2=a0*a0+a1*a1+a2*a2+a3*a3;
  1282. if( m2==scalar_traits<T>::value(0) )
  1283. BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());
  1284. T const s=sqrt<T>(m2);
  1285. a0/=s;
  1286. a1/=s;
  1287. a2/=s;
  1288. a3/=s;
  1289. }
  1290. if( T s=sqrt<T>(1-a0*a0) )
  1291. {
  1292. vec_traits<B>::template write_element<0>(b) = a1/s;
  1293. vec_traits<B>::template write_element<1>(b) = a2/s;
  1294. vec_traits<B>::template write_element<2>(b) = a3/s;
  1295. }
  1296. else
  1297. {
  1298. typedef typename vec_traits<B>::scalar_type U;
  1299. vec_traits<B>::template write_element<0>(b) = scalar_traits<U>::value(1);
  1300. vec_traits<B>::template write_element<1>(b) = vec_traits<B>::template write_element<2>(b) = scalar_traits<U>::value(0);
  1301. }
  1302. return scalar_traits<T>::value(2) * qvm::acos(a0);
  1303. }
  1304. ////////////////////////////////////////////////
  1305. namespace
  1306. sfinae
  1307. {
  1308. using ::boost::qvm::assign;
  1309. using ::boost::qvm::cmp;
  1310. using ::boost::qvm::convert_to;
  1311. using ::boost::qvm::conjugate;
  1312. using ::boost::qvm::set_identity;
  1313. using ::boost::qvm::set_zero;
  1314. using ::boost::qvm::scalar_cast;
  1315. using ::boost::qvm::operator/=;
  1316. using ::boost::qvm::operator/;
  1317. using ::boost::qvm::dot;
  1318. using ::boost::qvm::operator==;
  1319. using ::boost::qvm::inverse;
  1320. using ::boost::qvm::mag_sqr;
  1321. using ::boost::qvm::mag;
  1322. using ::boost::qvm::slerp;
  1323. using ::boost::qvm::operator-=;
  1324. using ::boost::qvm::operator-;
  1325. using ::boost::qvm::operator*=;
  1326. using ::boost::qvm::operator*;
  1327. using ::boost::qvm::operator!=;
  1328. using ::boost::qvm::normalized;
  1329. using ::boost::qvm::normalize;
  1330. using ::boost::qvm::operator+=;
  1331. using ::boost::qvm::operator+;
  1332. using ::boost::qvm::qref;
  1333. using ::boost::qvm::rot_quat;
  1334. using ::boost::qvm::set_rot;
  1335. using ::boost::qvm::rotate;
  1336. using ::boost::qvm::rotx_quat;
  1337. using ::boost::qvm::set_rotx;
  1338. using ::boost::qvm::rotate_x;
  1339. using ::boost::qvm::roty_quat;
  1340. using ::boost::qvm::set_roty;
  1341. using ::boost::qvm::rotate_y;
  1342. using ::boost::qvm::rotz_quat;
  1343. using ::boost::qvm::set_rotz;
  1344. using ::boost::qvm::rotate_z;
  1345. }
  1346. } }
  1347. #endif