include/crbn/basic/quat.hpp

00001 
00002 #ifndef __quat_hpp__
00003 #define __quat_hpp__
00004 
00005 #include <crbn/basic/scalar.hpp>
00006 #include <crbn/basic/vec3.hpp>
00007 
00008 struct quat {
00009   union {
00010     float data[ 4 ];
00011     struct { float x, y, z, w; };
00012   };
00013 
00014   quat() : x(0.0), y(0.0), z(0.0), w(1.0) {}
00015   quat( const float& i, const float& r = 1.0f ) :
00016     x(i), y(i), z(i), w(r)
00017   {}
00018   quat( const float& a, const float& b, const float& c, const float& d ) :
00019     x(a), y(b), z(c), w(d)
00020   {}
00021   quat( const quat& q ) : x(q.w), y(q.y), z(q.z), w(q.w) {}
00022   // Rotation about unit vector v by an angle t
00023   quat( const vec3& v, const float& t ) {
00024     float s = sin(t * 0.5);
00025     x = s * v.x;
00026     y = s * v.y;
00027     z = s * v.z;
00028     w = cos(t * 0.5);
00029   }
00030 };
00031 
00032 // a = b + c
00033 inline void qadd( quat& a, const quat& b, const quat& c ) {
00034   a.x = b.x + c.x;
00035   a.y = b.y + c.y;
00036   a.z = b.z + c.z;
00037   a.w = b.w + c.w;
00038 }
00039 // a = a + b
00040 inline void qadd( quat& a, const quat& b ) {
00041   a.x += b.x;
00042   a.y += b.y;
00043   a.z += b.z;
00044   a.w += b.w;
00045 }
00046 
00047 // a = b - c
00048 inline void qsub( quat& a, const quat& b, const quat& c ) {
00049   a.x = b.x - c.x;
00050   a.y = b.y - c.y;
00051   a.z = b.z - c.z;
00052   a.w = b.w - c.w;
00053 }
00054 // a = a - b
00055 inline void qsub( quat& a, const quat& b ) {
00056   a.x -= b.x;
00057   a.y -= b.y;
00058   a.z -= b.z;
00059   a.w -= b.w;
00060 }
00061 
00062 // a = conjugate( b )
00063 inline void qconj( quat& a, const quat& b ) {
00064   a.x = -b.x;
00065   a.y = -b.y;
00066   a.z = -b.z;
00067   a.w = b.w;
00068 }
00069 // a = conjugate( a )
00070 inline void qconj( quat& a ) {
00071   a.x = -a.x;
00072   a.y = -a.y;
00073   a.z = -a.z;
00074 }
00075 
00076 // a = f * b = b * f
00077 inline void qmul( quat& a, const float f, const quat& b ) {
00078   a.x = f * b.x;
00079   a.y = f * b.y;
00080   a.z = f * b.z;
00081   a.w = f * b.w;
00082 }
00083 inline void qmul( quat& a, const float f ) {
00084   a.x *= f;
00085   a.y *= f;
00086   a.z *= f;
00087   a.w *= f;
00088 }
00089 
00090 // a = b / f componentwise
00091 inline void qdiv( quat& a, const quat& b, const float f ) {
00092   float d = 1.0f / f;
00093   a.x = b.x * d;
00094   a.y = b.y * d;
00095   a.z = b.z * d;
00096   a.w = b.w * d;
00097 }
00098 // a = a / f componentwise
00099 inline void qdiv( quat& a, const float f ) {
00100   float d = 1.0f / f;
00101   a.x *= d;
00102   a.y *= d;
00103   a.z *= d;
00104   a.w *= d;
00105 }
00106 
00107 // a = b * c
00108 inline void qmul( quat& a, const quat& b, const quat& c ) {
00109   float bx = b.x, by = b.y, bz = b.z, bw = b.w;
00110   float cx = c.x, cy = c.y, cz = c.z, cw = c.w;
00111 
00112   a.x = by * cz - bz * cy + cw * bx + bw * cx;
00113   a.y = bz * cx - bx * cz + cw * by + bw * cy;
00114   a.z = bx * cy - by * cx + cw * bz + bw * cz;
00115   a.w = bw * cw - bx * cx - by * cy - bz * cz;
00116 }
00117 // a = a * b
00118 inline void qmul( quat& a, const quat& b ) {
00119   float bx = a.x, by = a.y, bz = a.z, bw = a.w;
00120   float cx = b.x, cy = b.y, cz = b.z, cw = b.w;
00121 
00122   a.x = by * cz - bz * cy + cw * bx + bw * cx;
00123   a.y = bz * cx - bx * cz + cw * by + bw * cy;
00124   a.z = bx * cy - by * cx + cw * bz + bw * cz;
00125   a.w = bw * cw - bx * cx - by * cy - bz * cz;
00126 }
00127 
00128 // a = b * b
00129 inline void qsqr( quat& a, const quat& b ) {
00130   a.w = b.w * b.w - b.x * b.x - b.y * b.y - b.z * b.z;
00131   a.x = 2.0 * b.w * b.x;     
00132   a.y = 2.0 * b.w * b.y;     
00133   a.z = 2.0 * b.w * b.z;     
00134 }
00135 
00136 // a = a * a
00137 inline void qsqr( quat& a ) {
00138   float w = a.w;
00139   a.w = w * w - a.x * a.x - a.y * a.y - a.z * a.z;
00140   a.x *= 2.0 * w;     
00141   a.y *= 2.0 * w;     
00142   a.z *= 2.0 * w;     
00143 }
00144 
00145 // ret = norm( a )
00146 inline float qnorm( const quat& a ) {
00147   return sqr( a.x ) + sqr( a.y ) + sqr( a.z ) + sqr( a.w );
00148 }
00149 
00150 // ret = length( a )
00151 inline float qnorm( const quat& a ) {
00152   return sqrt(sqr( a.x ) + sqr( a.y ) + sqr( a.z ) + sqr( a.w ));
00153 }
00154 
00155 // ret = dot product of a & b
00156 inline float qdot( const quat& a, const quat& b ) {
00157   return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
00158 }
00159 
00160 inline void qinverse( quat& a, const quat& b ) {
00161   float f = sqr( b.x ) + sqr( b.y ) + sqr( b.z ) + sqr( b.w );
00162   if( f < 1e-6f ) {
00163     f = -1.0f / f;
00164     a.x = b.x * f;
00165     a.y = b.y * f;
00166     a.z = b.z * f;
00167     a.w = b.w * -f;
00168   }
00169 }
00170 inline void qinverse( quat& a ) {
00171   float f = sqr( a.x ) + sqr( a.y ) + sqr( a.z ) + sqr( a.w );
00172   if( f < 1e-6f ) {
00173     f = -1.0f / f;
00174     a.x *= f;
00175     a.y *= f;
00176     a.z *= f;
00177     a.w *= -f;
00178   }
00179 }
00180 
00181 // a = b + f * c
00182 inline void qaddfmul( quat& a, const quat& b, const float f, const quat& c ) {
00183   a.x = b.x + f * c.x;
00184   a.y = b.y + f * c.y;
00185   a.z = b.z + f * c.z;
00186   a.w = b.w + f * c.w;
00187 }
00188 // a += f * b
00189 inline void qaddfmul( quat& a, const float f, const quat& b )
00190 {
00191   a.x += f * b.x;
00192   a.y += f * b.y;
00193   a.z += f * b.z;
00194   a.w += f * b.w;
00195 }
00196 
00197 // spherical linear interpolation of 2 quaternion
00198 inline void qslerp( quat& a, const float& f, const quat& b, const quat& c ) {
00199   float ps = qdot( b, c );
00200   float phi = (float)acos( (double)ps );
00201   float sphi = 1.0f / sinf( phi );
00202 
00203   qmul( a, sphi * sinf( (1.0f-f) * phi ), b );
00204   qaddfmul( a, sphi * sinf( phi * f ) , c );
00205 }
00206 // version 2 or slerp
00207 inline void qslerp2( quat& a, const float& f, const quat& b, const quat& c ) {
00208   quat ib;
00209   qinverse( ib, b );
00210   qmul( ib, c );
00211 
00212   float theta = f * (float)acos( (double)ib.w );
00213   float l = sqr( ib.x ) + sqr( ib.y ) + sqr( ib.z );
00214   qmul( ib, sinf( theta ) / sqrtf( l ) );
00215   ib.w = cosf( theta );
00216   qmul( a, b, ib );
00217 }
00218 
00219 #endif // __quat_hpp__
00220 

Generated on Tue Nov 14 15:40:08 2006 for libcrbn by  doxygen 1.5.0