23 #include "worldsimconfig.h"
52 void scale( real scale );
60 wVector getEuleroAngles()
const;
94 static QUAT_INDEX QIndex [] = {Y_INDEX, Z_INDEX, X_INDEX};
102 trace = matrix[0][0] + matrix[1][1] + matrix[2][2];
105 trace = sqrt( trace + 1.0 );
108 q1 = (matrix[1][2] - matrix[2][1]) * trace;
109 q2 = (matrix[2][0] - matrix[0][2]) * trace;
110 q3 = (matrix[0][1] - matrix[1][0]) * trace;
113 if( matrix[Y_INDEX][Y_INDEX] > matrix[X_INDEX][X_INDEX] ) {
116 if( matrix[Z_INDEX][Z_INDEX] > matrix[i][i] ) {
122 trace = 1.0 + matrix[i][i] - matrix[j][j] - matrix[k][k];
128 q0 = (matrix[j][k] - matrix[k][j]) * trace;
129 ptr[j] = (matrix[i][j] + matrix[j][i]) * trace;
130 ptr[k] = (matrix[i][k] + matrix[k][i]) * trace;
145 real sinAng = sin( angle );
147 q1 = unitAxis.x * sinAng;
148 q2 = unitAxis.y * sinAng;
149 q3 = unitAxis.z * sinAng;
152 inline void wQuaternion::scale(real scale) {
159 inline void wQuaternion::normalize() {
160 scale( 1.0/sqrt( dotProduct(*
this)) );
163 inline real wQuaternion::dotProduct(
const wQuaternion &QB )
const {
164 return q0*QB.q0 + q1*QB.q1 + q2*QB.q2 + q3*QB.q3;
167 inline wQuaternion wQuaternion::inverse()
const {
171 inline wVector wQuaternion::rotateVector(
const wVector& vector )
const {
172 wMatrix matrix( *
this, wVector( 0.0f, 0.0f, 0.0f, 1.0f ) );
173 return matrix.rotateVector( vector );
176 inline wVector wQuaternion::unrotateVector(
const wVector& vector )
const {
177 wMatrix matrix( *
this, wVector( 0.0f, 0.0f, 0.0f, 1.0f ) );
178 return matrix.unrotateVector( vector );
181 inline wQuaternion wQuaternion::operator+(
const wQuaternion &B)
const {
182 return wQuaternion( q0+B.q0, q1+B.q1, q2+B.q2, q3+B.q3);
185 inline wQuaternion wQuaternion::operator-(
const wQuaternion &B )
const {
186 return wQuaternion( q0-B.q0, q1-B.q1, q2-B.q2, q3-B.q3);
189 inline wQuaternion wQuaternion::operator*(
const wQuaternion &B )
const {
190 return wQuaternion( B.q0*q0 - B.q1*q1 - B.q2*q2 - B.q3*q3,
191 B.q1*q0 + B.q0*q1 - B.q3*q2 + B.q2*q3,
192 B.q2*q0 + B.q3*q1 + B.q0*q2 - B.q1*q3,
193 B.q3*q0 - B.q2*q1 + B.q1*q2 + B.q0*q3 );
196 inline wVector wQuaternion::getEuleroAngles()
const {
202 val = 2.0f*( q2*q0 - q3*q1 );
203 if( val >= 0.99995f ) {
204 pitch = 2.0f*atan2( q1, q0 );
207 }
else if( val <= -0.99995f ) {
208 pitch = 2.0f*atan2( q1, q0 );
209 yaw = -0.5f*PI_GRECO;
213 pitch = atan2( 2.0f*( q1*q0 + q3*q2 ), 1.0f-2.0f*( q1*q1 + q2*q2) );
214 roll = atan2( 2.0f*( q3*q0 + q1*q2 ), 1.0f-2.0f*( q2*q2 + q3*q3) );
216 return wVector(pitch, yaw, roll);
219 inline wVector wQuaternion::calcAverageOmega(
const wQuaternion &QB, real dt )
const {
221 wVector omegaDir( dq.q1, dq.q2, dq.q3 );
222 real dirMag2 = omegaDir % omegaDir;
223 if( dirMag2 < 1.0e-10 ) {
224 return wVector( 0.0, 0.0, 0.0, 0.0 );
226 real dirMagInv = 1.0/sqrt( dirMag2 );
227 real dirMag = dirMag2 * dirMagInv;
228 real omegaMag = 2.0*atan2( dirMag, dq.q0 )/dt;
230 return omegaDir.scale( dirMagInv * omegaMag );
233 inline wQuaternion wQuaternion::slerp(
const wQuaternion &QB, real t )
const {
242 dot = dotProduct( QB );
244 if( (dot+1.0) > 1.0e-5f ) {
249 Sclp = sin( (1.0-t) * ang ) * den;
250 Sclq = sin( t*ang ) * den;
255 Q.q0 = q0*Sclp + QB.q0*Sclq;
256 Q.q1 = q1*Sclp + QB.q1*Sclq;
257 Q.q2 = q2*Sclp + QB.q2*Sclq;
258 Q.q3 = q3*Sclp + QB.q3*Sclq;
265 Sclp = sin(1.0-t) * PI_GRECO * 0.5;
266 Sclq = sin( t * PI_GRECO * 0.5 );
268 Q.q0 = q0*Sclp + Q.q0*Sclq;
269 Q.q1 = q1*Sclp + Q.q1*Sclq;
270 Q.q2 = q2*Sclp + Q.q2*Sclq;
271 Q.q3 = q3*Sclp + Q.q3*Sclq;
274 dot = Q.dotProduct( Q );
275 if( dot < (1.0-1.0e-4f) ) {
276 dot = 1.0/sqrt( dot );