00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef WMATRIX_H
00021 #define WMATRIX_H
00022
00023 #include "worldsimconfig.h"
00024 #include "wvector.h"
00025 #include <cstring>
00026
00027 #ifdef FARSA_USE_GSL
00028 #include <gsl/gsl_blas.h>
00029 #endif
00030
00031 namespace farsa {
00032
00033 class wQuaternion;
00034
00046 class FARSA_WSIM_TEMPLATE wMatrix {
00047 public:
00049 wMatrix();
00056 wMatrix( const wVector &X, const wVector &Y, const wVector &Z, const wVector &P );
00061 wMatrix( const wQuaternion &rotation, const wVector &position );
00067 wMatrix( const real* position, const real* rotation );
00068
00070 wMatrix( const wMatrix &other );
00072 wMatrix& operator=( const wMatrix &other );
00073
00075 wVectorT<true>& operator[](int i);
00077 const wVectorT<true>& operator[](int i) const;
00078
00080 wMatrix inverse() const;
00082 wMatrix transpose() const;
00084 wMatrix transpose4X4() const;
00086 wVector getEuleroAngles() const;
00092 wMatrix rotateAround( const wVector& axis, const wVector& centre, real angle ) const;
00094 wMatrix rotateMatrix( const wMatrix& tm ) const;
00096 wVector rotateVector(const wVector &v) const;
00098 wVector unrotateVector(const wVector &v) const;
00100 wVector transformVector(const wVector &v) const;
00102 wVector untransformVector(const wVector &v) const;
00104 wVector transformPlane(const wVector &localPlane) const;
00106 wVector untransformPlane(const wVector &globalPlane) const;
00112 void transformTriplex( real* dst, int dstStrideInBytes, real* src, int srcStrideInBytes, int count) const;
00113
00115 wMatrix operator*( const wMatrix &B ) const;
00116
00118 bool sanityCheck();
00120 void sanitifize();
00121
00123 static wMatrix identity();
00125 static wMatrix zero();
00129 static wMatrix grammSchmidt(const wVector& dir);
00131 static wMatrix pitch( real ang );
00133 static wMatrix yaw( real ang );
00135 static wMatrix roll( real ang );
00136
00137 wVectorT<true> x_ax;
00138 wVectorT<true> y_ax;
00139 wVectorT<true> z_ax;
00140 wVectorT<true> w_pos;
00141
00142 private:
00143 real data[16];
00144 wVectorT<true>* vecs[4];
00145 };
00146
00147 }
00148
00149
00150 #include "wquaternion.h"
00151
00152 namespace farsa {
00153
00154 inline wMatrix::wMatrix() : x_ax(&data[0]), y_ax(&data[4]), z_ax(&data[8]), w_pos(&data[12]) {
00155 vecs[0] = &x_ax;
00156 vecs[1] = &y_ax;
00157 vecs[2] = &z_ax;
00158 vecs[3] = &w_pos;
00159 }
00160
00161 inline wMatrix::wMatrix ( const wVector &X, const wVector &Y, const wVector &Z, const wVector &P) : x_ax(&data[0]), y_ax(&data[4]), z_ax(&data[8]), w_pos(&data[12]) {
00162 vecs[0] = &x_ax;
00163 vecs[1] = &y_ax;
00164 vecs[2] = &z_ax;
00165 vecs[3] = &w_pos;
00166 x_ax = X;
00167 y_ax = Y;
00168 z_ax = Z;
00169 w_pos = P;
00170 }
00171
00172 inline wMatrix::wMatrix( const wQuaternion &rotation, const wVector &position ) : x_ax(&data[0]), y_ax(&data[4]), z_ax(&data[8]), w_pos(&data[12]) {
00173 vecs[0] = &x_ax;
00174 vecs[1] = &y_ax;
00175 vecs[2] = &z_ax;
00176 vecs[3] = &w_pos;
00177 real x2;
00178 real y2;
00179 real z2;
00180
00181 real xy;
00182 real xz;
00183 real xw;
00184 real yz;
00185 real yw;
00186 real zw;
00187
00188
00189 x2 = 2.0 * rotation.q1 * rotation.q1;
00190 y2 = 2.0 * rotation.q2 * rotation.q2;
00191 z2 = 2.0 * rotation.q3 * rotation.q3;
00192
00193
00194 xy = 2.0 * rotation.q1 * rotation.q2;
00195 xz = 2.0 * rotation.q1 * rotation.q3;
00196 xw = 2.0 * rotation.q1 * rotation.q0;
00197 yz = 2.0 * rotation.q2 * rotation.q3;
00198 yw = 2.0 * rotation.q2 * rotation.q0;
00199 zw = 2.0 * rotation.q3 * rotation.q0;
00200
00201 x_ax = wVector( 1.0-y2-z2, xy+zw, xz-yw, 0.0 );
00202 y_ax = wVector( xy-zw, 1.0-x2-z2, yz+xw, 0.0 );
00203 z_ax = wVector( xz+yw, yz-xw, 1.0-x2-y2, 0.0 );
00204
00205 w_pos.x = position.x;
00206 w_pos.y = position.y;
00207 w_pos.z = position.z;
00208 w_pos.w = 1.0;
00209 }
00210
00211 inline wMatrix::wMatrix( const real* pos, const real* rot ) : x_ax(&data[0]), y_ax(&data[4]), z_ax(&data[8]), w_pos(&data[12]) {
00212 vecs[0] = &x_ax;
00213 vecs[1] = &y_ax;
00214 vecs[2] = &z_ax;
00215 vecs[3] = &w_pos;
00216 x_ax[0]=rot[0]; x_ax[1]=rot[1]; x_ax[2]=rot[2]; x_ax[3]=0.0 ;
00217 y_ax[0]=rot[4]; y_ax[1]=rot[5]; y_ax[2]=rot[6]; y_ax[3]=0.0 ;
00218 z_ax[0]=rot[8]; z_ax[1]=rot[9]; z_ax[2]=rot[10]; z_ax[3]=0.0 ;
00219 w_pos[0]=pos[0]; w_pos[1]=pos[1]; w_pos[2]=pos[2]; w_pos[3]=1.0 ;
00220 }
00221
00222 inline wMatrix::wMatrix( const wMatrix &other ) : x_ax(&data[0]), y_ax(&data[4]), z_ax(&data[8]), w_pos(&data[12]) {
00223 vecs[0] = &x_ax;
00224 vecs[1] = &y_ax;
00225 vecs[2] = &z_ax;
00226 vecs[3] = &w_pos;
00227 memcpy(data, other.data, 16 * sizeof(real));
00228 }
00229
00230 inline wMatrix& wMatrix::operator=( const wMatrix &other )
00231 {
00232 if (&other == this) {
00233 return *this;
00234 }
00235
00236 memcpy(data, other.data, 16 * sizeof(real));
00237
00238 return *this;
00239 }
00240
00241 inline wVectorT<true>& wMatrix::operator[](int i) {
00242 return *(vecs[i]);
00243 }
00244
00245 inline const wVectorT<true>& wMatrix::operator[](int i) const {
00246 return *(vecs[i]);
00247 }
00248
00249 inline wMatrix wMatrix::inverse() const {
00250 return wMatrix( wVector(x_ax.x, y_ax.x, z_ax.x, 0.0f),
00251 wVector(x_ax.y, y_ax.y, z_ax.y, 0.0f),
00252 wVector(x_ax.z, y_ax.z, z_ax.z, 0.0f),
00253 wVector(- (w_pos % x_ax), - (w_pos % y_ax), - (w_pos % z_ax), 1.0f));
00254 }
00255
00256 inline wMatrix wMatrix::transpose() const {
00257 return wMatrix( wVector(x_ax.x, y_ax.x, z_ax.x, 0.0f),
00258 wVector(x_ax.y, y_ax.y, z_ax.y, 0.0f),
00259 wVector(x_ax.z, y_ax.z, z_ax.z, 0.0f),
00260 wVector(0.0f, 0.0f, 0.0f, 1.0f));
00261 }
00262
00263 inline wMatrix wMatrix::transpose4X4() const {
00264 return wMatrix( wVector(x_ax.x, y_ax.x, z_ax.x, w_pos.x),
00265 wVector(x_ax.y, y_ax.y, z_ax.y, w_pos.y),
00266 wVector(x_ax.z, y_ax.z, z_ax.z, w_pos.z),
00267 wVector(x_ax.w, y_ax.w, z_ax.w, w_pos.w));
00268 }
00269
00270 inline wVector wMatrix::getEuleroAngles() const {
00271 real yaw;
00272 real roll = 0.0;
00273 real pitch = 0.0;
00274 const real minSin = 0.99995f;
00275 const wMatrix& matrix = *this;
00276
00277 yaw = asin( -min( max( matrix[0][2], -0.999999 ), 0.999999) );
00278 if( matrix[0][2] < minSin ) {
00279 if( matrix[0][2] > -minSin ) {
00280 roll = atan2( matrix[0][1], matrix[0][0] );
00281 pitch = atan2( matrix[1][2], matrix[2][2] );
00282 } else {
00283 pitch = atan2( matrix[1][0], matrix[1][1] );
00284 }
00285 } else {
00286 pitch = -atan2( matrix[1][0], matrix[1][1] );
00287 }
00288
00289 return wVector(pitch, yaw, roll, 0.0);
00290 }
00291
00292 inline wMatrix wMatrix::rotateAround( const wVector& axis, const wVector& centre, real angle ) const {
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 wMatrix ret = *this;
00316 ret.x_ax.rotateAround( axis, angle );
00317 ret.y_ax.rotateAround( axis, angle );
00318 ret.z_ax.rotateAround( axis, angle );
00319 wVector diffCentre = ret.w_pos - centre;
00320 diffCentre.rotateAround( axis, angle );
00321 ret.w_pos = diffCentre + centre;
00322 return ret;
00323 }
00324
00325 inline wMatrix wMatrix::rotateMatrix( const wMatrix& B ) const {
00326 const wMatrix& A = *this;
00327 return wMatrix (wVector (A[0][0] * B[0][0] + A[0][1] * B[1][0] + A[0][2] * B[2][0] + A[0][3] * B[3][0],
00328 A[0][0] * B[0][1] + A[0][1] * B[1][1] + A[0][2] * B[2][1] + A[0][3] * B[3][1],
00329 A[0][0] * B[0][2] + A[0][1] * B[1][2] + A[0][2] * B[2][2] + A[0][3] * B[3][2],
00330 A[0][0] * B[0][3] + A[0][1] * B[1][3] + A[0][2] * B[2][3] + A[0][3] * B[3][3]),
00331 wVector (A[1][0] * B[0][0] + A[1][1] * B[1][0] + A[1][2] * B[2][0] + A[1][3] * B[3][0],
00332 A[1][0] * B[0][1] + A[1][1] * B[1][1] + A[1][2] * B[2][1] + A[1][3] * B[3][1],
00333 A[1][0] * B[0][2] + A[1][1] * B[1][2] + A[1][2] * B[2][2] + A[1][3] * B[3][2],
00334 A[1][0] * B[0][3] + A[1][1] * B[1][3] + A[1][2] * B[2][3] + A[1][3] * B[3][3]),
00335 wVector (A[2][0] * B[0][0] + A[2][1] * B[1][0] + A[2][2] * B[2][0] + A[2][3] * B[3][0],
00336 A[2][0] * B[0][1] + A[2][1] * B[1][1] + A[2][2] * B[2][1] + A[2][3] * B[3][1],
00337 A[2][0] * B[0][2] + A[2][1] * B[1][2] + A[2][2] * B[2][2] + A[2][3] * B[3][2],
00338 A[2][0] * B[0][3] + A[2][1] * B[1][3] + A[2][2] * B[2][3] + A[2][3] * B[3][3]),
00339 wVector ( A[3][3] * B[3][0],
00340 A[3][3] * B[3][1],
00341 A[3][3] * B[3][2],
00342 A[3][3] * B[3][3]));
00343 }
00344
00345 inline wVector wMatrix::rotateVector(const wVector &v) const {
00346 return wVector( v.x * x_ax.x + v.y * y_ax.x + v.z * z_ax.x,
00347 v.x * x_ax.y + v.y * y_ax.y + v.z * z_ax.y,
00348 v.x * x_ax.z + v.y * y_ax.z + v.z * z_ax.z);
00349 }
00350
00351 inline wVector wMatrix::unrotateVector(const wVector &v) const {
00352 return wVector( v%x_ax, v%y_ax, v%z_ax );
00353 }
00354
00355 inline wVector wMatrix::transformVector(const wVector &v) const {
00356 return w_pos + rotateVector(v);
00357 }
00358
00359 inline wVector wMatrix::untransformVector(const wVector &v) const {
00360 return unrotateVector( v-w_pos );
00361 }
00362
00363 inline void wMatrix::transformTriplex( real* dst, int dstStrideInBytes, real* src, int srcStrideInBytes, int count ) const {
00364 real x;
00365 real y;
00366 real z;
00367
00368 dstStrideInBytes /= sizeof(real);
00369 srcStrideInBytes /= sizeof(real);
00370
00371 for( int i=0; i<count; i++ ) {
00372 x = src[0];
00373 y = src[1];
00374 z = src[2];
00375 dst[0] = x*x_ax.x + y*y_ax.x + z*z_ax.x + w_pos.x;
00376 dst[1] = x*x_ax.y + y*y_ax.y + z*z_ax.y + w_pos.y;
00377 dst[2] = x*x_ax.z + y*y_ax.z + z*z_ax.z + w_pos.z;
00378 dst += dstStrideInBytes;
00379 src += srcStrideInBytes;
00380 }
00381 }
00382
00383 inline wMatrix wMatrix::operator*( const wMatrix &B ) const {
00384 const wMatrix& A = *this;
00385 #ifdef FARSA_USE_GSL
00386 wMatrix res;
00387 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 4, 4, 4, 1.0, A.data, 4, B.data, 4, 0.0, res.data, 4);
00388
00389 return res;
00390 #else
00391 return wMatrix (wVector (A[0][0] * B[0][0] + A[0][1] * B[1][0] + A[0][2] * B[2][0] + A[0][3] * B[3][0],
00392 A[0][0] * B[0][1] + A[0][1] * B[1][1] + A[0][2] * B[2][1] + A[0][3] * B[3][1],
00393 A[0][0] * B[0][2] + A[0][1] * B[1][2] + A[0][2] * B[2][2] + A[0][3] * B[3][2],
00394 A[0][0] * B[0][3] + A[0][1] * B[1][3] + A[0][2] * B[2][3] + A[0][3] * B[3][3]),
00395 wVector (A[1][0] * B[0][0] + A[1][1] * B[1][0] + A[1][2] * B[2][0] + A[1][3] * B[3][0],
00396 A[1][0] * B[0][1] + A[1][1] * B[1][1] + A[1][2] * B[2][1] + A[1][3] * B[3][1],
00397 A[1][0] * B[0][2] + A[1][1] * B[1][2] + A[1][2] * B[2][2] + A[1][3] * B[3][2],
00398 A[1][0] * B[0][3] + A[1][1] * B[1][3] + A[1][2] * B[2][3] + A[1][3] * B[3][3]),
00399 wVector (A[2][0] * B[0][0] + A[2][1] * B[1][0] + A[2][2] * B[2][0] + A[2][3] * B[3][0],
00400 A[2][0] * B[0][1] + A[2][1] * B[1][1] + A[2][2] * B[2][1] + A[2][3] * B[3][1],
00401 A[2][0] * B[0][2] + A[2][1] * B[1][2] + A[2][2] * B[2][2] + A[2][3] * B[3][2],
00402 A[2][0] * B[0][3] + A[2][1] * B[1][3] + A[2][2] * B[2][3] + A[2][3] * B[3][3]),
00403 wVector (A[3][0] * B[0][0] + A[3][1] * B[1][0] + A[3][2] * B[2][0] + A[3][3] * B[3][0],
00404 A[3][0] * B[0][1] + A[3][1] * B[1][1] + A[3][2] * B[2][1] + A[3][3] * B[3][1],
00405 A[3][0] * B[0][2] + A[3][1] * B[1][2] + A[3][2] * B[2][2] + A[3][3] * B[3][2],
00406 A[3][0] * B[0][3] + A[3][1] * B[1][3] + A[3][2] * B[2][3] + A[3][3] * B[3][3]));
00407 #endif
00408 }
00409
00410 inline wVector wMatrix::transformPlane( const wVector &localPlane ) const {
00411 wVector tmp( rotateVector(localPlane) );
00412 tmp.w = localPlane.w - ( localPlane%unrotateVector( w_pos ) );
00413 return tmp;
00414 }
00415
00416 inline wVector wMatrix::untransformPlane( const wVector &globalPlane ) const {
00417 wVector tmp( unrotateVector( globalPlane ) );
00418 tmp.w = globalPlane % w_pos + globalPlane.w;
00419 return tmp;
00420 }
00421
00422 inline bool wMatrix::sanityCheck() {
00423
00424 real zz = (x_ax.y*y_ax.z - x_ax.z*y_ax.y)*z_ax.x
00425 + (x_ax.z*y_ax.x - x_ax.x*y_ax.z)*z_ax.y
00426 + (x_ax.x*y_ax.y - x_ax.y*y_ax.x)*z_ax.z;
00427
00428
00429
00430 if( fabs( zz ) < 0.99f) {
00431
00432 return false;
00433 }
00434 x_ax.w = 0.0;
00435 y_ax.w = 0.0;
00436 z_ax.w = 0.0;
00437 w_pos.w = 1.0;
00438 return true;
00439 }
00440
00441 inline void wMatrix::sanitifize() {
00442
00443
00444
00445 x_ax.w = 0.0;
00446 y_ax.w = 0.0;
00447 z_ax.w = 0.0;
00448 w_pos.w = 1.0;
00449 }
00450
00451 inline wMatrix wMatrix::identity() {
00452 return wMatrix( wVector (1.0f, 0.0f, 0.0f, 0.0f),
00453 wVector (0.0f, 1.0f, 0.0f, 0.0f),
00454 wVector (0.0f, 0.0f, 1.0f, 0.0f),
00455 wVector (0.0f, 0.0f, 0.0f, 1.0f) );
00456 }
00457
00458 inline wMatrix wMatrix::zero() {
00459 return wMatrix( wVector (0.0f, 0.0f, 0.0f, 0.0f),
00460 wVector (0.0f, 0.0f, 0.0f, 0.0f),
00461 wVector (0.0f, 0.0f, 0.0f, 0.0f),
00462 wVector (0.0f, 0.0f, 0.0f, 0.0f) );
00463 }
00464
00465 inline wMatrix wMatrix::grammSchmidt(const wVector& dir) {
00466 wVector X;
00467 wVector Y;
00468 wVector Z( dir );
00469
00470 Z.normalize();
00471 if( fabs(Z.z) > 0.577f ) {
00472 X = Z * wVector( -Z.y, Z.z, 0.0f );
00473 } else {
00474 X = Z * wVector( -Z.y, Z.x, 0.0f );
00475 }
00476 X.normalize();
00477 Y = Z * X;
00478
00479 X.w = 0.0f;
00480 Y.w = 0.0f;
00481 Z.w = 0.0f;
00482 return wMatrix( X, Y, Z, wVector(0.0f, 0.0f, 0.0f, 1.0f) );
00483 }
00484
00485 inline wMatrix wMatrix::pitch( real ang ) {
00486 real cosAng = cos(ang);
00487 real sinAng = sin(ang);
00488 return wMatrix( wVector(1.0f, 0.0f, 0.0f, 0.0f),
00489 wVector(0.0f, cosAng, sinAng, 0.0f),
00490 wVector(0.0f, -sinAng, cosAng, 0.0f),
00491 wVector(0.0f, 0.0f, 0.0f, 1.0f) );
00492 }
00493
00494 inline wMatrix wMatrix::yaw( real ang) {
00495 real cosAng = cos(ang);
00496 real sinAng = sin(ang);
00497 return wMatrix( wVector (cosAng, 0.0f, -sinAng, 0.0f),
00498 wVector (0.0f, 1.0f, 0.0f, 0.0f),
00499 wVector (sinAng, 0.0f, cosAng, 0.0f),
00500 wVector (0.0f, 0.0f, 0.0f, 1.0f) );
00501 }
00502
00503 inline wMatrix wMatrix::roll( real ang ) {
00504 real cosAng = cos(ang);
00505 real sinAng = sin(ang);
00506 return wMatrix( wVector ( cosAng, sinAng, 0.0f, 0.0f),
00507 wVector (-sinAng, cosAng, 0.0f, 0.0f),
00508 wVector ( 0.0f, 0.0f, 1.0f, 0.0f),
00509 wVector ( 0.0f, 0.0f, 0.0f, 1.0f) );
00510 }
00511
00512 }
00513
00514 #endif