00001
00002
00003
00004
00005
00006
00007
00008
00020 #ifndef quaternion_h
00021 #define quaternion_h
00022
00023 #include <cml/mathlib/epsilon.h>
00024 #include <cml/quaternion/quaternion_expr.h>
00025 #include <cml/quaternion/quaternion_dot.h>
00026 #include <cml/util.h>
00027
00028
00029
00030
00031 struct quaternion_requires_fixed_size_array_type_error;
00032
00033 namespace cml {
00034
00040 template<
00041 typename Element,
00042 class ArrayType,
00043 class Order,
00044 class Cross
00045 >
00046 class quaternion
00047 {
00048
00049 CML_STATIC_REQUIRE_M(
00050 (same_type< ArrayType, fixed<> >::is_true
00051 || same_type< ArrayType, external<> >::is_true),
00052 quaternion_requires_fixed_size_array_type_error);
00053
00054 public:
00055
00056
00057 typedef ArrayType storage_type;
00058 typedef typename ArrayType::template rebind<4>::other generator_type;
00059
00060
00061
00062
00063 typedef vector<Element, generator_type> vector_type;
00064
00065
00066 typedef typename vector_type::temporary_type vector_temporary;
00067
00068
00069 typedef Order order_type;
00070
00071
00072 typedef Cross cross_type;
00073
00074
00075 typedef typename vector_type::value_type value_type;
00076 typedef typename vector_type::reference reference;
00077 typedef typename vector_type::const_reference const_reference;
00078
00079
00080
00081 typedef quaternion<Element,storage_type,order_type,cross_type>
00082 quaternion_type;
00083
00084
00085 typedef quaternion_type expr_type;
00086
00087
00088 typedef quaternion<
00089 Element, typename vector_temporary::storage_type,
00090 order_type, cross_type> temporary_type;
00091
00092
00093 typedef quaternion_type& expr_reference;
00094 typedef const quaternion_type& expr_const_reference;
00095
00096
00097 typedef typename vector_type::memory_tag memory_tag;
00098
00099
00100 typedef typename vector_type::size_tag size_tag;
00101
00102
00103 typedef typename vector_temporary::subvector_type imaginary_type;
00104
00105
00106 typedef cml::et::quaternion_result_tag result_tag;
00107
00108
00109 typedef cml::et::assignable_tag assignable_tag;
00110
00111
00112 public:
00113
00115 enum { array_size = 4 };
00116
00118 enum {
00119 W = order_type::W,
00120 X = order_type::X,
00121 Y = order_type::Y,
00122 Z = order_type::Z
00123 };
00124
00125
00126 public:
00127
00129 value_type real() const { return m_q[W]; }
00130
00132 imaginary_type imaginary() const {
00133
00134
00135
00136
00137
00138 return imaginary_type(m_q[X], m_q[Y], m_q[Z]);
00139 }
00140
00142 const vector_type& as_vector() const {
00143 return m_q;
00144 }
00145
00147 value_type norm() const {
00148 return length_squared();
00149 }
00150
00152 value_type length_squared() const {
00153 return cml::dot(*this,*this);
00154 }
00155
00157 value_type length() const {
00158 return std::sqrt(length_squared());
00159 }
00160
00165 quaternion_type& normalize() {
00166 return (*this /= length());
00167 }
00168
00170 quaternion_type& conjugate() {
00171 return (*this) = cml::conjugate(*this);
00172 }
00173
00175 quaternion_type& inverse() {
00176 return (*this) = cml::inverse(*this);
00177 }
00178
00180 quaternion_type& identity() {
00181 m_q[W] = value_type(1);
00182 m_q[X] = value_type(0);
00183 m_q[Y] = value_type(0);
00184 m_q[Z] = value_type(0);
00185 return *this;
00186 }
00187
00189 temporary_type log(
00190 value_type tolerance = epsilon<value_type>::placeholder()) const
00191 {
00192 value_type a = acos_safe(real());
00193 value_type s = std::sin(a);
00194
00195 if (s > tolerance) {
00196 return temporary_type(value_type(0), imaginary() * (a / s));
00197 } else {
00198 return temporary_type(value_type(0), imaginary());
00199 }
00200 }
00201
00206 temporary_type exp(
00207 value_type tolerance = epsilon<value_type>::placeholder()) const
00208 {
00209 imaginary_type v = imaginary();
00210 value_type a = cml::length(v);
00211
00212 if (a > tolerance) {
00213 return temporary_type(std::cos(a), v * (std::sin(a) / a));
00214 } else {
00215 return temporary_type(std::cos(a), v);
00216 }
00217 }
00218
00219
00221 const_reference operator[](size_t i) const { return m_q[i]; }
00222
00224 reference operator[](size_t i) { return m_q[i]; }
00225
00230 void random(value_type min, value_type max) {
00231 for (size_t i = 0; i < 4; ++i) {
00232 m_q[i] = random_real(min,max);
00233 }
00234 }
00235
00236 public:
00237
00243 quaternion() {}
00244
00246 quaternion(Element* const array) : m_q(array) {}
00247
00249 quaternion(const quaternion_type& q) : m_q(q.m_q) {}
00250
00252 template<typename E, class AT> quaternion(
00253 const quaternion<E,AT,order_type,cross_type>& q)
00254 : m_q(q.as_vector()) {}
00255
00257 template<typename XprT> quaternion(QUATXPR_ARG_TYPE e) {
00258 typedef typename XprT::order_type arg_order;
00259 m_q[W] = e[arg_order::W];
00260 m_q[X] = e[arg_order::X];
00261 m_q[Y] = e[arg_order::Y];
00262 m_q[Z] = e[arg_order::Z];
00263 }
00264
00265
00266
00272 quaternion(const vector_type& v) : m_q(v) {}
00273
00282 quaternion(const value_type v[4]) : m_q(v) {}
00283
00290 quaternion(
00291 const value_type& a, const value_type& b,
00292 const value_type& c, const value_type& d)
00293 {
00294
00295 assign(a, b, c, d, Order());
00296 }
00297
00304 quaternion(const value_type& s, const imaginary_type& v) {
00305 m_q[W] = s; m_q[X] = v[0]; m_q[Y] = v[1]; m_q[Z] = v[2];
00306 }
00307
00314 quaternion(const imaginary_type& v, const value_type& s) {
00315 m_q[W] = s; m_q[X] = v[0]; m_q[Y] = v[1]; m_q[Z] = v[2];
00316 }
00317
00324 quaternion(const value_type v[3], const value_type& s) {
00325 m_q[W] = s; m_q[X] = v[0]; m_q[Y] = v[1]; m_q[Z] = v[2];
00326 }
00327
00334 quaternion(const value_type& s, const value_type v[3]) {
00335 m_q[W] = s; m_q[X] = v[0]; m_q[Y] = v[1]; m_q[Z] = v[2];
00336 }
00337
00338
00339
00341 template<typename XprT>
00342 quaternion(VECXPR_ARG_TYPE e) : m_q(e) {}
00343
00348 template<typename XprT>
00349 quaternion(const value_type& s, VECXPR_ARG_TYPE e) {
00350 m_q[W] = s; m_q[X] = e[0]; m_q[Y] = e[1]; m_q[Z] = e[2];
00351 }
00352
00353
00354
00355
00356
00357
00358
00364 #define CML_QUAT_ASSIGN_FROM_QUAT(_op_) \
00365 template<typename E, class AT> const quaternion_type& \
00366 operator _op_ (const quaternion<E,AT,order_type,cross_type>& q) { \
00367 m_q[W] _op_ q[W]; \
00368 m_q[X] _op_ q[X]; \
00369 m_q[Y] _op_ q[Y]; \
00370 m_q[Z] _op_ q[Z]; \
00371 return *this; \
00372 }
00373
00378 #define CML_QUAT_ASSIGN_FROM_QUATXPR(_op_) \
00379 template<typename XprT> quaternion_type& \
00380 operator _op_ (QUATXPR_ARG_TYPE e) { \
00381 typedef typename XprT::order_type arg_order; \
00382 m_q[W] _op_ e[arg_order::W]; \
00383 m_q[X] _op_ e[arg_order::X]; \
00384 m_q[Y] _op_ e[arg_order::Y]; \
00385 m_q[Z] _op_ e[arg_order::Z]; \
00386 return *this; \
00387 }
00388
00393 #define CML_QUAT_ASSIGN_FROM_SCALAR(_op_,_op_name_) \
00394 quaternion_type& operator _op_ (const value_type& s) { \
00395 typedef _op_name_ <value_type,value_type> OpT; \
00396 OpT().apply(m_q[W],s); \
00397 OpT().apply(m_q[X],s); \
00398 OpT().apply(m_q[Y],s); \
00399 OpT().apply(m_q[Z],s); \
00400 return *this; \
00401 }
00402
00403 CML_QUAT_ASSIGN_FROM_QUAT(=)
00404 CML_QUAT_ASSIGN_FROM_QUAT(+=)
00405 CML_QUAT_ASSIGN_FROM_QUAT(-=)
00406
00407 CML_QUAT_ASSIGN_FROM_QUATXPR(=)
00408 CML_QUAT_ASSIGN_FROM_QUATXPR(+=)
00409 CML_QUAT_ASSIGN_FROM_QUATXPR(-=)
00410
00411 CML_QUAT_ASSIGN_FROM_SCALAR(*=, cml::et::OpMulAssign)
00412 CML_QUAT_ASSIGN_FROM_SCALAR(/=, cml::et::OpDivAssign)
00413
00414 #undef CML_QUAT_ASSIGN_FROM_QUAT
00415 #undef CML_QUAT_ASSIGN_FROM_QUATXPR
00416 #undef CML_QUAT_ASSIGN_FROM_SCALAR
00417
00429 quaternion_type& operator*=(const quaternion_type& q) {
00430 return (*this = *this * q);
00431 }
00432
00444 template<typename XprT> quaternion_type& operator*=(QUATXPR_ARG_TYPE e) {
00445 return (*this = *this * e);
00446 }
00447
00449 typename vector_type::pointer data() { return m_q.data(); }
00450
00452 const typename vector_type::pointer data() const { return m_q.data(); }
00453
00454
00455
00456
00457
00458 #if 0
00459
00474 quaternion_type& operator/=(const quaternion_type& q) {
00475 return (*this = *this * cml::inverse(q));
00476 }
00477
00493 template<typename XprT> quaternion_type& operator/=(QUATXPR_ARG_TYPE e) {
00494 return (*this = *this * cml::inverse(e));
00495 }
00496 #endif
00497
00498
00499 protected:
00500
00502 void assign(const value_type& a, const value_type& b,
00503 const value_type& c, const value_type& d, scalar_first)
00504 {
00505 m_q[W] = a; m_q[X] = b; m_q[Y] = c; m_q[Z] = d;
00506 }
00507
00509 void assign(const value_type& a, const value_type& b,
00510 const value_type& c, const value_type& d, vector_first)
00511 {
00512 m_q[X] = a; m_q[Y] = b; m_q[Z] = c; m_q[W] = d;
00513 }
00514
00515
00516 protected:
00517
00518 vector_type m_q;
00519 };
00520
00521 }
00522
00523 #endif
00524
00525
00526