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
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
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
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
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
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
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
00070 inline void qconj( quat& a ) {
00071 a.x = -a.x;
00072 a.y = -a.y;
00073 a.z = -a.z;
00074 }
00075
00076
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
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
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
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
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
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
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
00146 inline float qnorm( const quat& a ) {
00147 return sqr( a.x ) + sqr( a.y ) + sqr( a.z ) + sqr( a.w );
00148 }
00149
00150
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
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
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
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
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
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