#ifndef BLUECORE_QUATERNION_H #define BLUECORE_QUATERNION_H #include "Vector.h" namespace BlueCore { template class QuaternionTemplate { public: T w, x, y, z; /** * constructor */ inline QuaternionTemplate() { w = static_cast(1.0); x = static_cast(0.0); y = static_cast(0.0); z = static_cast(0.0); } /** * contructor */ template inline QuaternionTemplate( S w, S x, S y, S z ) { this->w = static_cast(w); this->x = static_cast(x); this->y = static_cast(y); this->z = static_cast(z); } /** * contructor */ template inline QuaternionTemplate( Vector3Template axis, S angle ) { T half_angle = static_cast(angle)/static_cast(2.0); T sin_half_angle = static_cast( sin( half_angle ) ); w = static_cast( cos( half_angle ) ); x = sin_half_angle * static_cast(axis.x); y = sin_half_angle * static_cast(axis.y); z = sin_half_angle * static_cast(axis.z); } /** * contructor */ template inline QuaternionTemplate( S h, S a, S b ) { T c1 = static_cast( cos(h / 2.0) ); T c2 = static_cast( cos(a / 2.0) ); T c3 = static_cast( cos(b / 2.0) ); T s1 = static_cast( sin(h / 2.0) ); T s2 = static_cast( sin(a / 2.0) ); T s3 = static_cast( sin(b / 2.0) ); w = c1 * c2 * c3 - s1 * s2 * s3; x = s1 * s2 * c3 + c1 * c2 * s3; y = s1 * c2 * c3 + c1 * s2 * s3; z = c1 * s2 * c3 - s1 * c2 * s3; } /** * identity */ inline void identity() { w = static_cast(1.0); x = static_cast(0.0); y = static_cast(0.0); z = static_cast(0.0); } /** * operator + */ template inline QuaternionTemplate operator + ( const QuaternionTemplate &a ) const { return QuaternionTemplate( w + static_cast(a.w), x + static_cast(a.x), y + static_cast(a.y), z + static_cast(a.z) ); } /** * operator += */ template inline QuaternionTemplate &operator += ( const QuaternionTemplate &a ) { w += static_cast(a.w); x += static_cast(a.x); y += static_cast(a.y); z += static_cast(a.z); return *this; } /** * operator - */ template inline QuaternionTemplate operator - ( const QuaternionTemplate &a ) const { return QuaternionTemplate( w - static_cast(a.w), x - static_cast(a.x), y - static_cast(a.y), z - static_cast(a.z) ); } /** * operator * */ template inline QuaternionTemplate operator * ( const QuaternionTemplate &a ) const { return QuaternionTemplate( w * static_cast(a.w) - x * static_cast(a.x) - y * static_cast(a.y) - z * static_cast(a.z), w * static_cast(a.x) + x * static_cast(a.w) + y * static_cast(a.z) - z * static_cast(a.y), w * static_cast(a.y) - x * static_cast(a.z) + y * static_cast(a.w) + z * static_cast(a.x), w * static_cast(a.z) + x * static_cast(a.y) - y * static_cast(a.x) + z * static_cast(a.w) ); } /** * operator *= */ template inline QuaternionTemplate &operator *=( const QuaternionTemplate &a ) { w = w * static_cast(a.w) - x * static_cast(a.x) - y * static_cast(a.y) - z * static_cast(a.z); x = w * static_cast(a.x) + x * static_cast(a.w) + y * static_cast(a.z) - z * static_cast(a.y); y = w * static_cast(a.y) - x * static_cast(a.z) + y * static_cast(a.w) + z * static_cast(a.x); z = w * static_cast(a.z) + x * static_cast(a.y) - y * static_cast(a.x) + z * static_cast(a.w); return *this; } /** * operator -= */ template inline QuaternionTemplate &operator -= ( const QuaternionTemplate &a ) { w -= static_cast(a.w); x -= static_cast(a.x); y -= static_cast(a.y); z -= static_cast(a.z); return *this; } /** * operator = */ template inline QuaternionTemplate &operator = ( const QuaternionTemplate &a ) { w = static_cast(a.w); x = static_cast(a.x); y = static_cast(a.y); z = static_cast(a.z); return *this; } /** * unit */ inline QuaternionTemplate unit() const { T d = 1/sqrt( w*w + x*x + y*y + z*z ); return QuaternionTemplate( w * d, x * d, y * d, z * d ); } /** * inversed */ inline QuaternionTemplate inversed() const { return QuaternionTemplate( w, -x, -y, -z ); } /** * inversed */ inline void inverse() { x = -x; y = -y; z = -z; } /** * normalize */ inline QuaternionTemplate &normalize() { T d = 1/sqrt( w*w + x*x + y*y + z*z ); w *= d; x *= d; y *= d; z *= d; return *this; } /** * apply */ template inline const Vector3Template apply( const Vector3Template &a ) const { T xx = x*x, xy = x*y, xz = x*z, xw = x*w, yy = y*y, yz = y*z, yw = y*w, zz = z*z, zw = z*w; return Vector3Template( 2.0 * ( static_cast(a.x) * ( 0.5 - yy - zz ) + static_cast(a.y) * ( xy - zw ) + static_cast(a.z) * ( xz + yw ) ), 2.0 * ( static_cast(a.x) * ( xy + zw ) + static_cast(a.y) * ( 0.5 - xx - zz ) + static_cast(a.z) * ( yz - xw ) ), 2.0 * ( static_cast(a.x) * ( xz - yw ) + static_cast(a.y) * ( yz + xw ) + static_cast(a.z) * ( 0.5 - xx - yy ) ) ); } /** * apply */ template inline const Vector3Template operator * ( const Vector3Template &a ) const { T xx = x*x, xy = x*y, xz = x*z, xw = x*w, yy = y*y, yz = y*z, yw = y*w, zz = z*z, zw = z*w; return Vector3Template( 2.0 * ( static_cast(a.x) * ( 0.5 - yy - zz ) + static_cast(a.y) * ( xy - zw ) + static_cast(a.z) * ( xz + yw ) ), 2.0 * ( static_cast(a.x) * ( xy + zw ) + static_cast(a.y) * ( 0.5 - xx - zz ) + static_cast(a.z) * ( yz - xw ) ), 2.0 * ( static_cast(a.x) * ( xz - yw ) + static_cast(a.y) * ( yz + xw ) + static_cast(a.z) * ( 0.5 - xx - yy ) ) ); } /** * applyInversed */ template inline Vector3Template applyInversed( const Vector3Template &a ) const { T xx = x*x, xy = x*y, xz = x*z, xw = -x*w, yy = y*y, yz = y*z, yw = -y*w, zz = z*z, zw = -z*w; return Vector3Template( 2.0 * ( static_cast(a.x) * ( 0.5 - yy - zz ) + static_cast(a.y) * ( xy - zw ) + static_cast(a.z) * ( xz + yw ) ), 2.0 * ( static_cast(a.x) * ( xy + zw ) + static_cast(a.y) * ( 0.5 - xx - zz ) + static_cast(a.z) * ( yz - xw ) ), 2.0 * ( static_cast(a.x) * ( xz - yw ) + static_cast(a.y) * ( yz + xw ) + static_cast(a.z) * ( 0.5 - xx - yy ) ) ); } /** * transform from ode to gl coodinates */ inline QuaternionTemplate toGl() const { return QuaternionTemplate( w, x, z, -y ); } /** * transform from gl to ode coodinates */ inline QuaternionTemplate toOde() const { return QuaternionTemplate( w, x, -z, y ); } inline QuaternionTemplate slerp( const QuaternionTemplate &q, const Scalar &t ) { Scalar phi = acos(w*q.w + x*q.x + y*q.y + z*q.z); Scalar s = 1 / sin(phi); Scalar a = sin(phi*(1-t)) * s; Scalar b = sin(phi*t) * s; return QuaternionTemplate( a*w+b*q.w, a*x+b*q.x, a*y+b*q.y, a*z+b*q.z ); } }; typedef QuaternionTemplate QuaternionFloat; typedef QuaternionTemplate QuaternionDouble; typedef QuaternionTemplate Quaternion; } #endif