|
World of Rigid Bodies (WoRB)
|
00001 #ifndef _QTENSOR_H_INCLUDED 00002 #define _QTENSOR_H_INCLUDED 00003 00004 /** 00005 * @file QTensor.h 00006 * @brief Definitions for the QTensor class that represents a quaternionic tensor. 00007 * @author Mikica Kocic 00008 * @version 0.5 00009 * @date 2012-05-05 00010 * @copyright GNU Public License. 00011 */ 00012 00013 #include "Quaternion.h" 00014 00015 namespace WoRB 00016 { 00017 ///////////////////////////////////////////////////////////////////////////////////// 00018 /** @class QTensor 00019 * 00020 * Encapsulates a quaternionic tensor (q-tensor) as a 4x4 row-major matrix. 00021 * 00022 * @note The QTensor class is implemented with inline methods only. 00023 */ 00024 class QTensor 00025 { 00026 const static int Length = 16; //!< Number of components 00027 00028 public: 00029 ///////////////////////////////////////////////////////////////////////////////// 00030 /** @name Q-Tensor components */ 00031 ///////////////////////////////////////////////////////////////////////////////// 00032 /*@{*/ 00033 /** Represents tensor components in a *column-major* order. 00034 * 00035 * Components are stored contiguously in linear memory as: 00036 * 00037 * `m.xx`, `m.yx`, `m.zx`... `m.zw`, `m.ww`. 00038 * 00039 * Offset of the component is calculated as `row + column * NumRows` 00040 * 00041 * @note C/C++ stores matrices in _row-major_ order. MATLAB and OpenGL 00042 * stores matrices in column-major order. 00043 * 00044 * See <a href="http://en.wikipedia.org/wiki/Row-major_order"> 00045 * Row-Major Order on Wikipedia </a> 00046 */ 00047 struct Components 00048 { 00049 double xx, yx, zx, /**/ wx; 00050 double xy, yy, zy, /**/ wy; 00051 double xz, yz, zz, /**/ wz; 00052 ///////////////////////////**/////// 00053 double xw, yw, zw, /**/ ww; 00054 }; 00055 00056 union 00057 { 00058 /** Holds the tensor components as a column-major matrix. 00059 */ 00060 Components m; 00061 00062 /** Holds the contigous memory array of the components 00063 */ 00064 double data[ Length ]; 00065 }; 00066 /*@}*/ 00067 ///////////////////////////////////////////////////////////////////////////////// 00068 /** @name Constructors and assignment operators */ 00069 ///////////////////////////////////////////////////////////////////////////////// 00070 /*@{*/ 00071 /** Represents type of initial matrix data for QTensor constructor. 00072 */ 00073 enum Initializer 00074 { 00075 Uninitialized, //!< Matrix with uninitialized components 00076 Normalized, //!< Matrix with m.ww = 1 and other components set to zero 00077 Zero, //!< Matrix with all components set to zero 00078 Identity //!< Identity matrix, i.e. 1 on the main diagonal 00079 }; 00080 00081 /** Creates a tensor with initial contents according to the given type. 00082 */ 00083 QTensor( Initializer type = Normalized ) 00084 { 00085 switch( type ) 00086 { 00087 case Uninitialized: 00088 break; 00089 00090 case Normalized: 00091 SetComponents( 0 ); 00092 m.ww = 1.0; 00093 break; 00094 00095 case Zero: 00096 SetComponents( 0 ); 00097 break; 00098 00099 case Identity: 00100 SetComponents( 0 ); 00101 m.xx = m.yy = m.zz = m.ww = 1.0; 00102 break; 00103 } 00104 } 00105 00106 /** Sets the main diagonal with quaternion components. 00107 */ 00108 QTensor( const Quaternion& q ) 00109 { 00110 SetComponents( 0 ); 00111 m.xx = q.x; 00112 m.yy = q.y; 00113 m.zz = q.z; 00114 m.ww = q.w; 00115 } 00116 00117 /** Sets the matrix with values along the main diagonal. 00118 */ 00119 QTensor( double xx, double yy, double zz, double ww = 1.0 ) 00120 { 00121 SetComponents( 0 ); 00122 m.xx = xx; 00123 m.yy = yy; 00124 m.zz = zz; 00125 m.ww = ww; 00126 } 00127 00128 /** Sets the main diagonal with the given value. 00129 */ 00130 QTensor& operator = ( double valueOnDiagonal ) 00131 { 00132 SetComponents( 0 ); 00133 m.xx = m.yy = m.zz = m.ww = valueOnDiagonal; 00134 return *this; 00135 } 00136 /*@}*/ 00137 ///////////////////////////////////////////////////////////////////////////////// 00138 /** @name Indexing operators */ 00139 ///////////////////////////////////////////////////////////////////////////////// 00140 /*@{*/ 00141 double& operator [] ( unsigned index ) 00142 { 00143 return *( &m.xx + index ); 00144 } 00145 /*@}*/ 00146 ///////////////////////////////////////////////////////////////////////////////// 00147 /** @name Components setters */ 00148 ///////////////////////////////////////////////////////////////////////////////// 00149 /*@{*/ 00150 /** Sets all components to the same value. 00151 */ 00152 QTensor& SetComponents( double valueForAllComponents ) 00153 { 00154 for ( int i = 0; i < Length; ++i ) { 00155 data[i] = valueForAllComponents; 00156 } 00157 return *this; 00158 } 00159 00160 /** Sets the q-tensor values from the given three vector components. 00161 * 00162 * These are arranged as the three columns of the vector. 00163 */ 00164 QTensor& SetColumnVectors( 00165 const Quaternion& v1, const Quaternion& v2, const Quaternion& v3 ) 00166 { 00167 m.xx = v1.x ; m.xy = v2.x ; m.xz = v3.x ; m.xw = 0 ; 00168 m.yx = v1.y ; m.yy = v2.y ; m.yz = v3.y ; m.yw = 0 ; 00169 m.zx = v1.z ; m.zy = v2.z ; m.zz = v3.z ; m.zw = 0 ; 00170 m.wx = 0 ; m.wy = 0 ; m.wz = 0 ; m.ww = 1 ; 00171 00172 return *this; 00173 } 00174 00175 /** Sets the matrix to be a skew symmetric matrix based on 00176 * the given quaternion. 00177 */ 00178 QTensor& SetSkewSymmetric( const Quaternion& q ) 00179 { 00180 m.xx = 0 ; m.xy = -q.z ; m.xz = q.y ; m.xw = 0 ; 00181 m.yx = q.z ; m.yy = 0 ; m.yz = -q.x ; m.yw = 0 ; 00182 m.zx = -q.y ; m.zy = q.x ; m.zz = 0 ; m.zw = 0 ; 00183 m.wx = 0 ; m.wy = 0 ; m.wz = 0 ; m.ww = 0 ; 00184 00185 return *this; 00186 } 00187 00188 /** Sets the q-tensor to represent a "left-multiplier quaternion" matrix L(q). 00189 * 00190 * See "Rotation of Moment of Inertia Tensor" Mathematica notebook by MBK. 00191 */ 00192 QTensor& SetLeftMultiplier( const Quaternion& q ) 00193 { 00194 m.xx = q.w ; m.xy = -q.z ; m.xz = q.y ; m.xw = q.x ; 00195 m.yx = q.z ; m.yy = q.w ; m.yz = -q.x ; m.yw = q.y ; 00196 m.zx = -q.y ; m.zy = q.x ; m.zz = q.w ; m.zw = q.z ; 00197 m.wx = -q.x ; m.wy = -q.y ; m.wz = -q.z ; m.ww = q.w ; 00198 00199 return *this; 00200 } 00201 00202 /** Sets the q-tensor to represent a "right-multiplier quaternion" matrix R(q). 00203 * 00204 * See "Rotation of Moment of Inertia Tensor" Mathematica notebook by MBK. 00205 */ 00206 QTensor& SetRightMultiplier( const Quaternion& q ) 00207 { 00208 m.xx = q.w ; m.xy = q.z ; m.xz = -q.y ; m.xw = q.x ; 00209 m.yx = -q.z ; m.yy = q.w ; m.yz = q.x ; m.yw = q.y ; 00210 m.zx = q.y ; m.zy = -q.x ; m.zz = q.w ; m.zw = q.z ; 00211 m.wx = -q.x ; m.wy = -q.y ; m.wz = -q.z ; m.ww = q.w ; 00212 00213 return *this; 00214 } 00215 00216 /** Creates a transform matrix from a position and orientation. 00217 * 00218 * This is so called Shoemake's matrix, which is obtained as L(q) * R(q*). 00219 * See "Rotation of Moment of Inertia Tensor" Mathematica notebook by MBK. 00220 */ 00221 QTensor& SetFromOrientationAndPosition( 00222 const Quaternion& q, const Quaternion& translate ) 00223 { 00224 m.xx = 1 - 2 * ( q.y * q.y + q.z * q.z ) ; 00225 m.xy = 2 * ( q.x * q.y - q.w * q.z ) ; 00226 m.xz = 2 * ( q.x * q.z + q.w * q.y ) ; 00227 m.xw = translate.x; 00228 00229 m.yx = 2 * ( q.x * q.y + q.w * q.z ) ; 00230 m.yy = 1 - 2 * ( q.x * q.x + q.z * q.z ) ; 00231 m.yz = 2 * ( q.y * q.z - q.w * q.x ) ; 00232 m.yw = translate.y; 00233 00234 m.zx = 2 * ( q.x * q.z - q.w * q.y ) ; 00235 m.zy = 2 * ( q.y * q.z + q.w * q.x ) ; 00236 m.zz = 1 - 2 * ( q.x * q.x + q.y * q.y ) ; 00237 m.zw = translate.z; 00238 00239 m.wx = m.wy = m.wz = 0; m.ww = 1; 00240 00241 return *this; 00242 } 00243 /*@}*/ 00244 ///////////////////////////////////////////////////////////////////////////////// 00245 /** @name Components getters */ 00246 ///////////////////////////////////////////////////////////////////////////////// 00247 /*@{*/ 00248 /** Gets a quaternion representing one row in the matrix. 00249 */ 00250 Quaternion Row( unsigned i /*!< Row index */ ) const 00251 { 00252 const double* p = data; 00253 return Quaternion( p[i+12], p[i], p[i+4], p[i+8] ); 00254 } 00255 00256 /** Gets a quaternion representing one unit base vector (axis). 00257 * Axis vectors are columns in the matrix. 00258 * Axis with index 3 corresponds to the position of the transform matrix. 00259 */ 00260 Quaternion Column( unsigned j /*!< Column index */ ) const 00261 { 00262 const double* p = data + j * 4; 00263 return Quaternion( p[3], p[0], p[1], p[2] ); 00264 } 00265 00266 /** Gets an OpenGL transform representing a combined translation and rotation. 00267 */ 00268 void GetGLTransform( double d[Length] ) const 00269 { 00270 // We can do simple memcpy since GL also use column-major matrix. 00271 // 00272 for ( int i = 0 ; i < Length; ++i ) { 00273 d[i] = data[i]; 00274 } 00275 00276 // Otherwise, we should setup GL matrix explicitly: 00277 // d[0] = m.xx ; d[4] = m.xy ; d[ 8] = m.xz ; d[12] = m.xw ; 00278 // d[1] = m.yx ; d[5] = m.yy ; d[ 9] = m.yz ; d[13] = m.yw ; 00279 // d[2] = m.zx ; d[6] = m.zy ; d[10] = m.zz ; d[14] = m.zw ; 00280 // d[3] = m.wx ; d[7] = m.wy ; d[11] = m.wz ; d[15] = m.ww ; 00281 } 00282 /*@}*/ 00283 ///////////////////////////////////////////////////////////////////////////////// 00284 /** @name Unary operations */ 00285 ///////////////////////////////////////////////////////////////////////////////// 00286 /*@{*/ 00287 /** Flips signs of all the components of the matrix 00288 */ 00289 QTensor operator - () const 00290 { 00291 QTensor result( Uninitialized ); 00292 00293 for ( int i = 0; i < Length; ++i ) { 00294 result.data[i] = - data[i]; 00295 } 00296 00297 return result; 00298 } 00299 /*@}*/ 00300 ///////////////////////////////////////////////////////////////////////////////// 00301 /** @name Binary operations */ 00302 ///////////////////////////////////////////////////////////////////////////////// 00303 /*@{*/ 00304 /** Does a component-wise addition of this matrix and other matrix. 00305 */ 00306 QTensor operator + ( const QTensor& T ) 00307 { 00308 QTensor result( Uninitialized ); 00309 00310 for ( int i = 0; i < Length; ++i ) { 00311 result.data[i] = data[i] + T.data[i]; 00312 } 00313 return result; 00314 } 00315 00316 /** Does a component-wise addition of this matrix and other matrix. 00317 */ 00318 QTensor& operator += ( const QTensor& T ) 00319 { 00320 for ( int i = 0; i < Length; ++i ) { 00321 data[i] += T.data[i]; 00322 } 00323 return *this; 00324 } 00325 00326 /** Does a component-wise subtraction of this matrix and other matrix. 00327 */ 00328 QTensor operator - ( const QTensor& T ) 00329 { 00330 QTensor result( Uninitialized ); 00331 00332 for ( int i = 0; i < Length; ++i ) { 00333 result.data[i] = data[i] - T.data[i]; 00334 } 00335 return result; 00336 } 00337 00338 /** Does a component-wise subtraction of this matrix and other matrix. 00339 */ 00340 QTensor& operator -= ( const QTensor& T ) 00341 { 00342 for ( int i = 0; i < Length; ++i ) { 00343 data[i] -= T.data[i]; 00344 } 00345 return *this; 00346 } 00347 00348 /** Multiplies this matrix by the given scalar. 00349 */ 00350 QTensor operator * ( double scalar ) const 00351 { 00352 QTensor result( Uninitialized ); 00353 00354 for ( int i = 0; i < Length; ++i ) { 00355 result.data[i] = data[i] * scalar; 00356 } 00357 return result; 00358 } 00359 00360 /** Multiplies this matrix by the given scalar. 00361 */ 00362 QTensor& operator *= ( double scalar ) 00363 { 00364 for ( int i = 0; i < Length; ++i ) { 00365 data[i] *= scalar; 00366 } 00367 return *this; 00368 } 00369 00370 /** Transform the vector part of a quaternion by this matrix. 00371 */ 00372 Quaternion operator * ( const Quaternion& q ) const 00373 { 00374 return Quaternion( 0, 00375 q.x * m.xx + q.y * m.xy + q.z * m.xz + m.xw, 00376 q.x * m.yx + q.y * m.yy + q.z * m.yz + m.yw, 00377 q.x * m.zx + q.y * m.zy + q.z * m.zz + m.zw 00378 ); 00379 } 00380 00381 /** Returns a q-tensor which is this matrix multiplied by 00382 * the given other q-tensor. 00383 */ 00384 QTensor operator * ( const QTensor& T ) const 00385 { 00386 QTensor result( Uninitialized ); 00387 00388 result.m.xx = m.xx * T.m.xx + m.xy * T.m.yx + m.xz * T.m.zx ; 00389 result.m.xy = m.xx * T.m.xy + m.xy * T.m.yy + m.xz * T.m.zy ; 00390 result.m.xz = m.xx * T.m.xz + m.xy * T.m.yz + m.xz * T.m.zz ; 00391 result.m.xw = m.xx * T.m.xw + m.xy * T.m.yw + m.xz * T.m.zw + m.xw ; 00392 00393 result.m.yx = m.yx * T.m.xx + m.yy * T.m.yx + m.yz * T.m.zx ; 00394 result.m.yy = m.yx * T.m.xy + m.yy * T.m.yy + m.yz * T.m.zy ; 00395 result.m.yz = m.yx * T.m.xz + m.yy * T.m.yz + m.yz * T.m.zz ; 00396 result.m.yw = m.yx * T.m.xw + m.yy * T.m.yw + m.yz * T.m.zw + m.yw ; 00397 00398 result.m.zx = m.zx * T.m.xx + m.zy * T.m.yx + m.zz * T.m.zx ; 00399 result.m.zy = m.zx * T.m.xy + m.zy * T.m.yy + m.zz * T.m.zy ; 00400 result.m.zz = m.zx * T.m.xz + m.zy * T.m.yz + m.zz * T.m.zz ; 00401 result.m.zw = m.zx * T.m.xw + m.zy * T.m.yw + m.zz * T.m.zw + m.zw ; 00402 00403 result.m.wx = result.m.wy = result.m.wz = 0; 00404 result.m.ww = 1; 00405 00406 return result; 00407 } 00408 00409 /** Multiplies this matrix in place by the given other matrix. 00410 */ 00411 QTensor& operator *= ( const QTensor& T ) 00412 { 00413 return *this = *this * T; 00414 } 00415 /*@}*/ 00416 ///////////////////////////////////////////////////////////////////////////////// 00417 /** @name Transpose and related methods */ 00418 ///////////////////////////////////////////////////////////////////////////////// 00419 /*@{*/ 00420 /** Sets the matrix to be the transpose of the given matrix. 00421 */ 00422 QTensor& SetTransposeOf( const QTensor& T ) 00423 { 00424 m.xx = T.m.xx ; m.xy = T.m.yx ; m.xz = T.m.zx ; m.xw = T.m.wx ; 00425 m.yx = T.m.xy ; m.yy = T.m.yy ; m.yz = T.m.zy ; m.yw = T.m.wy ; 00426 m.zx = T.m.xz ; m.zy = T.m.yz ; m.zz = T.m.zz ; m.zw = T.m.wz ; 00427 m.wx = T.m.xw ; m.wy = T.m.yw ; m.wz = T.m.zw ; m.ww = T.m.ww ; 00428 00429 return *this; 00430 } 00431 00432 /** Returns a new matrix containing the transpose of this matrix. 00433 */ 00434 QTensor Transpose () const 00435 { 00436 return QTensor( Uninitialized ).SetTransposeOf( *this ); 00437 } 00438 /*@}*/ 00439 ///////////////////////////////////////////////////////////////////////////////// 00440 /** @name Determinant, matrix Inverse and related methods */ 00441 ///////////////////////////////////////////////////////////////////////////////// 00442 /*@{*/ 00443 /** Returns the determinant of the matrix. 00444 */ 00445 double Determinant () const 00446 { 00447 return - m.zx * m.yy * m.xz 00448 + m.yx * m.zy * m.xz 00449 + m.zx * m.xy * m.yz 00450 - m.xx * m.zy * m.yz 00451 - m.yx * m.xy * m.zz 00452 + m.xx * m.yy * m.zz; 00453 } 00454 00455 /** Sets the matrix to be the inverse of the given matrix. 00456 */ 00457 QTensor& SetInverseOf( const QTensor& T ) 00458 { 00459 double det_T = T.Determinant(); 00460 00461 // Make sure the determinant is non-zero. 00462 // 00463 if ( det_T == 0 ) { 00464 SetComponents( 0 ); 00465 return *this; 00466 } 00467 00468 m.xx = - T.m.zy * T.m.yz + T.m.yy * T.m.zz; 00469 m.yx = T.m.zx * T.m.yz - T.m.yx * T.m.zz; 00470 m.zx = - T.m.zx * T.m.yy + T.m.yx * T.m.zy; 00471 00472 m.xy = T.m.zy * T.m.xz - T.m.xy * T.m.zz; 00473 m.yy = - T.m.zx * T.m.xz + T.m.xx * T.m.zz; 00474 m.zy = T.m.zx * T.m.xy - T.m.xx * T.m.zy; 00475 00476 m.xz = - T.m.yy * T.m.xz + T.m.xy * T.m.yz; 00477 m.yz = T.m.yx * T.m.xz - T.m.xx * T.m.yz; 00478 m.zz = - T.m.yx * T.m.xy + T.m.xx * T.m.yy; 00479 00480 m.xw = T.m.zy * T.m.yz * T.m.xw 00481 - T.m.yy * T.m.zz * T.m.xw 00482 - T.m.zy * T.m.xz * T.m.yw 00483 + T.m.xy * T.m.zz * T.m.yw 00484 + T.m.yy * T.m.xz * T.m.zw 00485 - T.m.xy * T.m.yz * T.m.zw; 00486 00487 m.yw = - T.m.zx * T.m.yz * T.m.xw 00488 + T.m.yx * T.m.zz * T.m.xw 00489 + T.m.zx * T.m.xz * T.m.yw 00490 - T.m.xx * T.m.zz * T.m.yw 00491 - T.m.yx * T.m.xz * T.m.zw 00492 + T.m.xx * T.m.yz * T.m.zw; 00493 00494 m.zw = T.m.zx * T.m.yy * T.m.xw 00495 - T.m.yx * T.m.zy * T.m.xw 00496 - T.m.zx * T.m.xy * T.m.yw 00497 + T.m.xx * T.m.zy * T.m.yw 00498 + T.m.yx * T.m.xy * T.m.zw 00499 - T.m.xx * T.m.yy * T.m.zw; 00500 00501 for ( int i = 0; i < Length; ++ i ) { 00502 data[i] /= det_T; 00503 } 00504 return *this; 00505 } 00506 00507 /** Returns a new matrix containing the inverse of this matrix. 00508 */ 00509 QTensor Inverse () const 00510 { 00511 return QTensor( Uninitialized ).SetInverseOf( *this ); 00512 } 00513 /*@}*/ 00514 ///////////////////////////////////////////////////////////////////////////////// 00515 /** @name Spatial transformations related methods */ 00516 ///////////////////////////////////////////////////////////////////////////////// 00517 /*@{*/ 00518 /** Transform the vector part of a quaternion by this matrix. 00519 */ 00520 Quaternion operator () ( const Quaternion& q ) const 00521 { 00522 return Quaternion( 0, 00523 q.x * m.xx + q.y * m.xy + q.z * m.xz + m.xw, 00524 q.x * m.yx + q.y * m.yy + q.z * m.yz + m.yw, 00525 q.x * m.zx + q.y * m.zy + q.z * m.zz + m.zw 00526 ); 00527 } 00528 00529 /** Transform the given quaternion by the inverse of this matrix. 00530 */ 00531 Quaternion TransformInverse( const Quaternion &q ) const 00532 { 00533 Quaternion del = q - Quaternion( 0, m.xw, m.yw, m.zw ); 00534 00535 return Quaternion( 0, 00536 del.x * m.xx + del.y * m.yx + del.z * m.zx, 00537 del.x * m.xy + del.y * m.yy + del.z * m.zy, 00538 del.x * m.xz + del.y * m.yz + del.z * m.zz 00539 ); 00540 } 00541 00542 /** Transforms a tensor from one to another frame of reference. 00543 * 00544 * Equivalent to: `result = (*this) * T * Transpose()` 00545 */ 00546 QTensor operator () ( const QTensor& T ) const 00547 { 00548 QTensor result( Uninitialized ); 00549 00550 double t_xx = m.xx * T.m.xx + m.xy * T.m.yx + m.xz * T.m.zx ; 00551 double t_xy = m.xx * T.m.xy + m.xy * T.m.yy + m.xz * T.m.zy ; 00552 double t_xz = m.xx * T.m.xz + m.xy * T.m.yz + m.xz * T.m.zz ; 00553 00554 double t_yx = m.yx * T.m.xx + m.yy * T.m.yx + m.yz * T.m.zx ; 00555 double t_yy = m.yx * T.m.xy + m.yy * T.m.yy + m.yz * T.m.zy ; 00556 double t_yz = m.yx * T.m.xz + m.yy * T.m.yz + m.yz * T.m.zz ; 00557 00558 double t_zx = m.zx * T.m.xx + m.zy * T.m.yx + m.zz * T.m.zx ; 00559 double t_zy = m.zx * T.m.xy + m.zy * T.m.yy + m.zz * T.m.zy ; 00560 double t_zz = m.zx * T.m.xz + m.zy * T.m.yz + m.zz * T.m.zz ; 00561 00562 result.m.xx = t_xx * m.xx + t_xy * m.xy + t_xz * m.xz ; 00563 result.m.xy = t_xx * m.yx + t_xy * m.yy + t_xz * m.yz ; 00564 result.m.xz = t_xx * m.zx + t_xy * m.zy + t_xz * m.zz ; 00565 result.m.xw = 0 ; 00566 00567 result.m.yx = t_yx * m.xx + t_yy * m.xy + t_yz * m.xz ; 00568 result.m.yy = t_yx * m.yx + t_yy * m.yy + t_yz * m.yz ; 00569 result.m.yz = t_yx * m.zx + t_yy * m.zy + t_yz * m.zz ; 00570 result.m.yw = 0 ; 00571 00572 result.m.zx = t_zx * m.xx + t_zy * m.xy + t_zz * m.xz ; 00573 result.m.zy = t_zx * m.yx + t_zy * m.yy + t_zz * m.yz ; 00574 result.m.zz = t_zx * m.zx + t_zy * m.zy + t_zz * m.zz ; 00575 result.m.zw = 0 ; 00576 00577 result.m.wx = result.m.wy = result.m.ww = 0; 00578 result.m.ww = 1; 00579 00580 return result; 00581 } 00582 00583 /** Transform the given matrix by the inverse of this matrix. 00584 * 00585 * Equivalent to: `result = Transpose() * T * (*this)` 00586 */ 00587 QTensor TransformInverse( const QTensor &T ) const 00588 { 00589 QTensor result( Uninitialized ); 00590 00591 double t_xx = m.xx * T.m.xx + m.yx * T.m.yx + m.zx * T.m.zx ; 00592 double t_xy = m.xx * T.m.xy + m.yx * T.m.yy + m.zx * T.m.zy ; 00593 double t_xz = m.xx * T.m.xz + m.yx * T.m.yz + m.zx * T.m.zz ; 00594 00595 double t_yx = m.xy * T.m.xx + m.yy * T.m.yx + m.zy * T.m.zx ; 00596 double t_yy = m.xy * T.m.xy + m.yy * T.m.yy + m.zy * T.m.zy ; 00597 double t_yz = m.xy * T.m.xz + m.yy * T.m.yz + m.zy * T.m.zz ; 00598 00599 double t_zx = m.xz * T.m.xx + m.yz * T.m.yx + m.zz * T.m.zx ; 00600 double t_zy = m.xz * T.m.xy + m.yz * T.m.yy + m.zz * T.m.zy ; 00601 double t_zz = m.xz * T.m.xz + m.yz * T.m.yz + m.zz * T.m.zz ; 00602 00603 result.m.xx = t_xx * m.xx + t_xy * m.yx + t_xz * m.zx ; 00604 result.m.xy = t_xx * m.xy + t_xy * m.yy + t_xz * m.zy ; 00605 result.m.xz = t_xx * m.xz + t_xy * m.yz + t_xz * m.zz ; 00606 result.m.xw = 0 ; 00607 00608 result.m.yx = t_yx * m.xx + t_yy * m.yx + t_yz * m.zx ; 00609 result.m.yy = t_yx * m.xy + t_yy * m.yy + t_yz * m.zy ; 00610 result.m.yz = t_yx * m.xz + t_yy * m.yz + t_yz * m.zz ; 00611 result.m.yw = 0 ; 00612 00613 result.m.zx = t_zx * m.xx + t_zy * m.yx + t_zz * m.zx ; 00614 result.m.zy = t_zx * m.xy + t_zy * m.yy + t_zz * m.zy ; 00615 result.m.zz = t_zx * m.xz + t_zy * m.yz + t_zz * m.zz ; 00616 result.m.zw = 0 ; 00617 00618 result.m.wx = result.m.wy = result.m.ww = 0; 00619 result.m.ww = 1; 00620 00621 return result; 00622 } 00623 /*@}*/ 00624 ///////////////////////////////////////////////////////////////////////////////// 00625 }; 00626 00627 } // namespace WoRB 00628 00629 #endif // _QTENSOR_H_INCLUDED