33 #ifndef __VMML__QUATERNION__HPP__
34 #define __VMML__QUATERNION__HPP__
36 #include <vmmlib/enable_if.hpp>
37 #include <vmmlib/types.hpp>
38 #include <vmmlib/vector.hpp>
68 T tolerance = std::numeric_limits< T >::epsilon( ))
const;
70 T x()
const {
return array[0]; }
71 T y()
const {
return array[1]; }
72 T z()
const {
return array[2]; }
73 T w()
const {
return array[3]; }
102 Quaternion operator+(
const Quaternion< T >& a )
const;
106 Quaternion operator*(
const Quaternion< T >& a )
const;
107 void operator+=(
const Quaternion< T >& a );
108 void operator-=(
const Quaternion< T >& a );
111 void operator*=(
const Quaternion< T >& a );
119 void operator*=( T a );
120 void operator/=( T a );
123 friend std::ostream& operator<< ( std::ostream& os,
const Quaternion& q )
125 const std::ios::fmtflags flags = os.flags();
126 const int prec = os.precision();
128 os.setf( std::ios::right, std::ios::adjustfield );
132 << std::setw(10) << q.x() <<
" "
133 << std::setw(10) << q.y() <<
" "
134 << std::setw(10) << q.z() <<
" "
135 << std::setw(10) << q.w() <<
" "
138 os.precision( prec );
148 #include <vmmlib/matrix.hpp>
154 template <
typename T >
155 T dot(
const Quaternion< T >& p,
const Quaternion< T >& q )
157 return p.array[3] * q.array[3] + p.array[0] * q.array[0] +
158 p.array[1] * q.array[1] + p.array[2] * q.array[2];
161 template <
typename T >
162 vector< 3, T > cross(
const Quaternion< T >& p,
const Quaternion< T >& q )
164 return vector< 3, T >( p.array[1] * q.array[2] - p.array[2] * q.array[1],
165 p.array[2] * q.array[0] - p.array[0] * q.array[2],
166 p.array[0] * q.array[1] - p.array[1] * q.array[0] );
178 template<
typename T >
template<
size_t M >
180 typename enable_if< M >= 3 >::type* )
182 const T trace = rot( 0, 0 ) + rot( 1, 1 ) + rot( 2,2 ) + T( 1 );
183 static const T TRACE_EPSILON = 1e-5;
186 if( trace > TRACE_EPSILON )
188 T s = 0.5 / std::sqrt( trace );
189 array[0] = rot( 2, 1 ) - rot( 1, 2 );
192 array[1] = rot( 0, 2 ) - rot( 2, 0 );
195 array[2] = rot( 1, 0 ) - rot( 0, 1 );
202 const vector< 3, T > diag( rot( 0, 0 ), rot( 1, 1 ), rot( 2, 2 ) );
203 const size_t largest = diag.find_max_index();
208 const T s = 0.5 / std::sqrt( T( 1 ) + rot( 0,0 ) - rot( 1,1 ) -
212 array[1] = rot( 0,1 ) + rot( 1,0 );
215 array[2] = rot( 0,2 ) + rot( 2,0 );
218 array[3] = rot( 1,2 ) - rot( 2,1 );
221 else if ( largest == 1 )
223 const T s = 0.5 / std::sqrt( T( 1 ) + rot( 1,1 ) - rot( 0,0 ) -
225 array[0] = rot( 0,1 ) + rot( 1,0 );
230 array[2] = rot( 1,2 ) + rot( 2,1 );
233 array[3] = rot( 0,2 ) - rot( 2,0 );
237 else if ( largest == 2 )
239 const T s = 0.5 / std::sqrt( T( 1 ) + rot( 2,2 ) - rot( 0,0 ) -
241 array[0] = rot( 0,2 ) + rot( 2,0 );
244 array[1] = rot( 1,2 ) + rot( 2,1 );
249 array[3] = rot( 0,1 ) - rot( 1,0 );
254 throw std::runtime_error(
"no clue why, but should not get here" );
260 template<
typename T >
264 const T sinAngle2 = std::sin( angle * 0.5 );
265 array[0] = axis.x() * sinAngle2;
266 array[1] = axis.y() * sinAngle2;
267 array[2] = axis.z() * sinAngle2;
268 array[3] = std::cos( angle * 0.5 );
271 template<
typename T >
274 return std::abs( array[0] - other.array[0] ) <= tolerance &&
275 std::abs( array[1] - other.array[1] ) <= tolerance &&
276 std::abs( array[2] - other.array[2] ) <= tolerance &&
277 std::abs( array[3] - other.array[3] ) <= tolerance;
280 template <
typename T >
283 return array[0] == rhs.array[0] && array[1] == rhs.array[1] &&
284 array[2] == rhs.array[2] && array[3] == rhs.array[3];
287 template <
typename T >
290 return ! this->operator==( a );
298 template <
typename T > T Quaternion< T >::abs()
const
300 return std::sqrt( absSquare( ));
303 template <
typename T >T Quaternion< T >::absSquare()
const
305 return array[0] * array[0] + array[1] * array[1] +
306 array[2] * array[2] + array[3] * array[3];
312 const T tmp = T( 1 ) / absSquare();
322 this->operator*=( len );
329 template <
typename T >
330 Quaternion< T > Quaternion< T >::operator+(
const Quaternion< T >& rhs )
const
332 return Quaternion( array[0] + rhs.array[0], array[1] + rhs.array[1],
333 array[2] + rhs.array[2], array[3] + rhs.array[3] );
336 template <
typename T >
339 return Quaternion( array[0] - rhs.array[0], array[1] - rhs.array[1],
340 array[2] - rhs.array[2], array[3] - rhs.array[3] );
344 template <
typename T >
345 Quaternion< T > Quaternion< T >::operator*(
const Quaternion< T >& rhs )
const
347 Quaternion< T > ret( *
this );
353 template <
typename T >
354 void Quaternion< T >::operator*=(
const Quaternion< T >& q )
358 const T& a_ = array[ 3 ];
359 const T& b_ = array[ 0 ];
360 const T& c = array[ 1 ];
361 const T& d = array[ 2 ];
362 const T& _x = q.array[ 3 ];
363 const T& _y = q.array[ 0 ];
364 const T& _z = q.array[ 1 ];
365 const T& _w = q.array[ 2 ];
367 const T tmp_00 = (d - c) * (_z - _w);
368 const T tmp_01 = (a_ + b_) * (_x + _y);
369 const T tmp_02 = (a_ - b_) * (_z + _w);
370 const T tmp_03 = (c + d) * (_x - _y);
371 const T tmp_04 = (d - b_) * (_y - _z);
372 const T tmp_05 = (d + b_) * (_y + _z);
373 const T tmp_06 = (a_ + c) * (_x - _w);
374 const T tmp_07 = (a_ - c) * (_x + _w);
375 const T tmp_08 = tmp_05 + tmp_06 + tmp_07;
376 const T tmp_09 = 0.5 * (tmp_04 + tmp_08);
378 array[ 0 ] = tmp_01 + tmp_09 - tmp_08;
379 array[ 1 ] = tmp_02 + tmp_09 - tmp_07;
380 array[ 2 ] = tmp_03 + tmp_09 - tmp_06;
381 array[ 3 ] = tmp_00 + tmp_09 - tmp_05;
386 return Quaternion( -array[0], -array[1], -array[2], -array[3] );
389 template <
typename T >
392 array[ 0 ] += q.array[ 0 ];
393 array[ 1 ] += q.array[ 1 ];
394 array[ 2 ] += q.array[ 2 ];
395 array[ 3 ] += q.array[ 3 ];
398 template <
typename T >
399 void Quaternion< T >::operator-=(
const Quaternion< T >& q )
401 array[ 0 ] -= q.array[ 0 ];
402 array[ 1 ] -= q.array[ 1 ];
403 array[ 2 ] -= q.array[ 2 ];
404 array[ 3 ] -= q.array[ 3 ];
411 template <
typename T >
412 Quaternion< T > Quaternion< T >::operator*(
const T a_ )
const
414 return Quaternion( array[0] * a_, array[1] * a_,
415 array[2] * a_, array[3] * a_ );
418 template <
typename T >
419 Quaternion< T > Quaternion< T >::operator/( T a_ )
const
422 throw std::runtime_error(
"Division by zero." );
425 return Quaternion( array[0] * a_, array[1] * a_, array[2] * a_,
429 template <
typename T >
void Quaternion< T >::operator*=( T q )
437 template <
typename T >
void Quaternion< T >::operator/=( T q )
440 throw std::runtime_error(
"Division by zero" );
443 this->operator*=( q );
446 template <
typename T >
449 const T w2 = array[3] * array[3];
450 const T x2 = array[0] * array[0];
451 const T y2 = array[1] * array[1];
452 const T z2 = array[2] * array[2];
453 const T wx = array[3] * array[0];
454 const T wy = array[3] * array[1];
455 const T wz = array[3] * array[2];
456 const T xy = array[0] * array[1];
457 const T xz = array[0] * array[2];
458 const T yz = array[1] * array[2];
461 matrix( 0, 0 ) = w2 + x2 - y2 - z2;
462 matrix( 0, 1 ) = 2. * (xy - wz);
463 matrix( 0, 2 ) = 2. * (xz + wy);
464 matrix( 1, 0 ) = 2. * (xy + wz);
465 matrix( 1, 1 ) = w2 - x2 + y2 - z2;
466 matrix( 1, 2 ) = 2. * (yz - wx);
467 matrix( 2, 0 ) = 2. * (xz - wy);
468 matrix( 2, 1 ) = 2. * (yz + wx);
469 matrix( 2, 2 ) = w2 - x2 - y2 + z2;
473 template <
typename T >
476 ::memcpy( array, other.array, 4 *
sizeof( T ) );
bool equals(const Quaternion &other, T tolerance=std::numeric_limits< T >::epsilon()) const
heavily inspired by boost::enable_if http://www.boost.org, file: boost/utility/enable_if.hpp, Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine
bool operator==(const Quaternion &a) const
Matrix< 3, 3, T > getRotationMatrix() const
Quaternion()
Construct an identity quaternion.
Quaternion operator-() const
bool operator!=(const Quaternion &a) const
Matrix with R rows and C columns of element type T.
Quaternion inverse() const