00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "Quaternion.h"
00031
00032
00033 #include <cassert>
00034
00035
00036 #include "Vec3r.h"
00037
00038 namespace opal
00039 {
00040 Quaternion::Quaternion()
00041 {
00042 w = 0;
00043 x = 0;
00044 y = 0;
00045 z = 0;
00046 }
00047
00048 Quaternion::Quaternion( real ww, real xx, real yy, real zz )
00049 {
00050 w = ww;
00051 x = xx;
00052 y = yy;
00053 z = zz;
00054 }
00055
00056 Quaternion::Quaternion( const Quaternion& src )
00057 {
00058 w = src.w;
00059 x = src.x;
00060 y = src.y;
00061 z = src.z;
00062 }
00063
00064 void Quaternion::set( real ww, real xx, real yy, real zz )
00065 {
00066 w = ww;
00067 x = xx;
00068 y = yy;
00069 z = zz;
00070 }
00071
00072 real Quaternion::lengthSquared() const
00073 {
00074 return w * w + x * x + y * y + z * z;
00075 }
00076
00077 real Quaternion::length() const
00078 {
00079 return sqrt( lengthSquared() );
00080 }
00081
00082 void Quaternion::normalize()
00083 {
00084 real len = length();
00085 if ( len > 0 )
00086 {
00087 real factor = 1 / len;
00088 ( *this ) = ( *this ) * factor;
00089 }
00090 }
00091
00092 void Quaternion::getAngleAxis( real& angle, Vec3r& axis ) const
00093 {
00094 real sqrLen = x * x + y * y + z * z;
00095
00096 if ( sqrLen > 0 )
00097 {
00098 angle = 2 * acos( w );
00099 real invLen = 1 / sqrt( sqrLen );
00100 axis.x = x * invLen;
00101 axis.y = y * invLen;
00102 axis.z = z * invLen;
00103 }
00104 else
00105 {
00106 angle = 0;
00107 axis.x = 1;
00108 axis.y = 0;
00109 axis.z = 0;
00110 }
00111
00112
00113 angle = radToDeg( angle );
00114 }
00115
00116 real Quaternion::getRoll() const
00117 {
00118 return radToDeg( atan2( 2 * ( y * z + w * x ),
00119 w * w - x * x - y * y +
00120 z * z ) );
00121 }
00122
00123 real Quaternion::getPitch() const
00124 {
00125 return radToDeg( asin( -2 * ( x * z - w * y ) ) );
00126 }
00127
00128 real Quaternion::getYaw() const
00129 {
00130 return radToDeg( atan2( 2 * ( x * y + w * z ),
00131 w * w + x * x - y * y -
00132 z * z ) );
00133 }
00134
00135 real & Quaternion::operator[] ( unsigned int i )
00136 {
00137 switch ( i )
00138 {
00139 case 0: return w;
00140 case 1: return x;
00141 case 2: return y;
00142 case 3: return z;
00143 }
00144 assert( i < 4 );
00145 return w;
00146 }
00147
00148 const real & Quaternion::operator[] ( unsigned int i ) const
00149 {
00150 switch ( i )
00151 {
00152 case 0: return w;
00153 case 1: return x;
00154 case 2: return y;
00155 case 3: return z;
00156 }
00157 assert( i < 4 );
00158 return w;
00159 }
00160
00161 Quaternion operator+( const Quaternion &q1, const Quaternion &q2 )
00162 {
00163 return Quaternion( q1.w + q2.w, q1.x + q2.x, q1.y + q2.y, q1.z + q2.z );
00164 }
00165
00166 Quaternion operator-( const Quaternion &q1, const Quaternion &q2 )
00167 {
00168 return Quaternion( q1.w - q2.w, q1.x - q2.x, q1.y - q2.y, q1.z - q2.z );
00169 }
00170
00171 bool operator==( const Quaternion &q1, const Quaternion &q2 )
00172 {
00173 if ( !areEqual( q1.w, q2.w ) || !areEqual( q1.x , q2.x ) ||
00174 !areEqual( q1.y , q2.y ) || !areEqual( q1.z , q2.z ) )
00175 return false;
00176 else
00177 return true;
00178 }
00179
00180 bool operator!=( const Quaternion &q1, const Quaternion &q2 )
00181 {
00182 if ( !areEqual( q1.w, q2.w ) || !areEqual( q1.x , q2.x ) ||
00183 !areEqual( q1.y , q2.y ) || !areEqual( q1.z , q2.z ) )
00184 return true;
00185 else
00186 return false;
00187 }
00188
00189 Quaternion operator*( const Quaternion& q, real scalar )
00190 {
00191 return Quaternion( scalar * q.w, scalar * q.x, scalar * q.y, scalar * q.z );
00192 }
00193
00194 Quaternion operator*( real scalar, const Quaternion& q )
00195 {
00196 return Quaternion( scalar * q.w, scalar * q.x, scalar * q.y, scalar * q.z );
00197 }
00198
00199 std::ostream& operator<<( std::ostream& o, const Quaternion& q )
00200 {
00201 return o << "[" << q.w << " " << q.x << " " << q.y << " " << q.z << "]";
00202 }
00203 }