quat_operations.hpp 52 KB

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