quat_operations.hpp 52 KB

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