GEL
2
GEL is a library for Geometry and Linear Algebra
|
00001 #ifndef __CGLA_ARITHQUAT_H__ 00002 #define __CGLA_ARITHQUAT_H__ 00003 00004 #include "CGLA.h" 00005 #include "ArithVecFloat.h" 00006 #include "ArithSqMatFloat.h" 00007 #include <cmath> 00008 00009 namespace CGLA { 00010 00015 template<class T, class V, class Q> 00016 class ArithQuat 00017 { 00018 public: 00019 00021 V qv; 00022 00024 T qw; 00025 00027 #ifndef NDEBUG 00028 ArithQuat() : qw(CGLA_INIT_VALUE) {} 00029 #else 00030 ArithQuat() {} 00031 #endif 00032 00034 ArithQuat(const V& imaginary, T real = 1.0f) : qv(imaginary) , qw(real) {} 00035 00037 ArithQuat(T x, T y, T z, T _qw) : qv(x,y,z), qw(_qw) {} 00038 00039 00041 void set(const V& imaginary, T real=1.0f) 00042 { 00043 qv = imaginary; 00044 qw = real; 00045 } 00046 00047 void set(T x, T y, T z, T _qw) 00048 { 00049 qv.set(x,y,z); 00050 qw = _qw; 00051 } 00052 00053 /*void set(const Vec4f& v) 00054 { 00055 qv.set(v[0], v[1], v[2]); 00056 qw = v[3]; 00057 }*/ 00058 00060 void get(T& x, T& y, T& z, T& _qw) const 00061 { 00062 x = qv[0]; 00063 y = qv[1]; 00064 z = qv[2]; 00065 _qw = qw; 00066 } 00067 00069 V get_imaginary_part() const { return qv; } 00070 00072 T get_real_part() const { return qw; } 00073 00074 00075 00077 void get_rot(T& angle, V& v) 00078 { 00079 angle = 2*std::acos(qw); 00080 00081 if(angle < TINY) 00082 v = V(static_cast<T>(1.0), static_cast<T>(0.0), static_cast<T>(0.0)); 00083 else 00084 v = qv*(static_cast<T>(1.0)/std::sin(angle)); 00085 00086 if(angle > M_PI) 00087 v = -v; 00088 00089 v.normalize(); 00090 } 00091 00093 void make_rot(T angle, const V& v) 00094 { 00095 angle /= static_cast<T>(2.0); 00096 qv = CGLA::normalize(v)*std::sin(angle); 00097 qw = std::cos(angle); 00098 } 00099 00102 void make_rot(const V& s,const V& t) 00103 { 00104 T tmp = std::sqrt(2*(1 + dot(s, t))); 00105 qv = cross(s, t)*(1.0/tmp); 00106 qw = tmp/2.0; 00107 } 00108 00110 template <class VT, class MT, unsigned int ROWS> 00111 void make_rot(ArithSqMatFloat<VT,MT,ROWS>& m) 00112 { 00113 assert(ROWS==3 || ROWS==4); 00114 T trace = m[0][0] + m[1][1] + m[2][2] + static_cast<T>(1.0); 00115 00116 //If the trace of the matrix is greater than zero, then 00117 //perform an "instant" calculation. 00118 if ( trace > TINY ) 00119 { 00120 T S = sqrt(trace) * static_cast<T>(2.0); 00121 qv = V(m[2][1] - m[1][2], m[0][2] - m[2][0], m[1][0] - m[0][1] ); 00122 qv /= S; 00123 qw = static_cast<T>(0.25) * S; 00124 } 00125 else 00126 { 00127 //If the trace of the matrix is equal to zero (or negative...) then identify 00128 //which major diagonal element has the greatest value. 00129 //Depending on this, calculate the following: 00130 00131 if ( m[0][0] > m[1][1] && m[0][0] > m[2][2] ) { // Column 0: 00132 T S = sqrt( static_cast<T>(1.0) + m[0][0] - m[1][1] - m[2][2] ) * static_cast<T>(2.0); 00133 qv[0] = 0.25f * S; 00134 qv[1] = (m[1][0] + m[0][1] ) / S; 00135 qv[2] = (m[0][2] + m[2][0] ) / S; 00136 qw = (m[2][1] - m[1][3] ) / S; 00137 } else if ( m[1][1] > m[2][2] ) { // Column 1: 00138 T S = sqrt( 1.0 + m[1][1] - m[0][0] - m[2][2] ) * 2.0; 00139 qv[0] = (m[1][0] + m[0][1] ) / S; 00140 qv[1] = 0.25 * S; 00141 qv[2] = (m[2][1] + m[1][2] ) / S; 00142 qw = (m[0][2] - m[2][0] ) / S; 00143 } else { // Column 2: 00144 T S = sqrt( 1.0 + m[2][2] - m[0][0] - m[1][1] ) * 2.0; 00145 qv[0] = (m[0][2] + m[2][0] ) / S; 00146 qv[1] = (m[2][1] + m[1][2] ) / S; 00147 qv[2] = 0.25 * S; 00148 qw = (m[1][0] - m[0][1] ) / S; 00149 } 00150 } 00151 //The quaternion is then defined as: 00152 // Q = | X Y Z W | 00153 } 00154 00155 //---------------------------------------------------------------------- 00156 // Binary operators 00157 //---------------------------------------------------------------------- 00158 00159 bool operator==(const ArithQuat<T,V,Q>& q) const 00160 { 00161 return qw == q.qw && qv == q.qv; 00162 } 00163 00164 bool operator!=(const ArithQuat<T,V,Q>& q) const 00165 { 00166 return qw != q.qw || qv != q.qv; 00167 } 00168 00170 Q operator*(const ArithQuat<T,V,Q>& q) const 00171 { 00172 return Q(cross(qv, q.qv) + qv*q.qw + q.qv*qw, 00173 qw*q.qw - dot(qv, q.qv)); 00174 } 00175 00177 Q operator*(T scalar) const 00178 { 00179 return Q(qv*scalar, qw*scalar); 00180 } 00181 00183 Q operator+(const ArithQuat<T,V,Q>& q) const 00184 { 00185 return Q(qv + q.qv, qw + q.qw); 00186 } 00187 00188 //---------------------------------------------------------------------- 00189 // Unary operators 00190 //---------------------------------------------------------------------- 00191 00193 Q operator-() const { return Q(-qv, -qw); } 00194 00196 T norm() const { return dot(qv, qv) + qw*qw; } 00197 00199 Q conjugate() const { return Q(-qv, qw); } 00200 00202 Q inverse() const { return Q(conjugate()*(1/norm())); } 00203 00205 Q normalize() { return Q((*this)*(1/norm())); } 00206 00207 //---------------------------------------------------------------------- 00208 // Application 00209 //---------------------------------------------------------------------- 00210 00212 V apply(const V& vec) const 00213 { 00214 return ((*this)*Q(vec)*inverse()).qv; 00215 } 00216 00218 V apply_unit(const V& vec) const 00219 { 00220 assert(fabs(norm() - 1.0) < SMALL); 00221 return ((*this)*Q(vec)*conjugate()).qv; 00222 } 00223 }; 00224 00225 template<class T, class V, class Q> 00226 inline Q operator*(T scalar, const ArithQuat<T,V,Q>& q) 00227 { 00228 return q*scalar; 00229 } 00230 00237 template<class T, class V, class Q> 00238 inline Q slerp(const ArithQuat<T,V,Q>& q0, const ArithQuat<T,V,Q>& q1, T t) 00239 { 00240 T angle = std::acos(q0.qv[0]*q1.qv[0] + q0.qv[1]*q1.qv[1] 00241 + q0.qv[2]*q1.qv[2] + q0.qw*q1.qw); 00242 return (q0*std::sin((1 - t)*angle) + q1*std::sin(t*angle))*(1/std::sin(angle)); 00243 } 00244 00246 template<class T, class V, class Q> 00247 inline std::ostream& operator<<(std::ostream&os, const ArithQuat<T,V,Q>& v) 00248 { 00249 os << "[ "; 00250 for(unsigned int i=0;i<3;i++) os << v.qv[i] << " "; 00251 os << "~ " << v.qw << " "; 00252 os << "]"; 00253 00254 return os; 00255 } 00256 } 00257 00258 00259 00260 00261 00262 00263 00264 00265 00266 00267 00268 00269 00270 00271 00272 00273 00274 #endif // __CGLA_ARITHQUAT_H__