"L. Spiro Engine"
|
00001 00017 #ifndef __LSM_HELPERS_H__ 00018 #define __LSM_HELPERS_H__ 00019 00020 #include "../LSMMathLib.h" 00021 #include "../Matrix/LSMMatrix3x3.h" 00022 #include "../Matrix/LSMMatrix4x4.h" 00023 #include "../Quaternion/LSMQuaternion.h" 00024 #include "../Vector/LSMVector2.h" 00025 #include "../Vector/LSMVector3.h" 00026 00027 namespace lsm { 00028 00035 class CHelpers { 00036 public : 00048 static LSVOID LSE_FCALL DecomposeMatrix( const CMatrix4x4 &_mMatrix, 00049 CQuaternion &_qRot, 00050 CVector3 &_vScale, 00051 CVector3 &_vPos ); 00052 00063 static CMatrix4x4 & LSE_FCALL ComposeMatrix( CMatrix4x4 &_mMatrix, 00064 const CQuaternion &_qRot, 00065 const CVector3 &_vPos ); 00066 00077 static CMatrix4x4 & LSE_FCALL ComposeMatrix( CMatrix4x4 &_mMatrix, 00078 const CQuaternion &_qRot, 00079 const CVector3 &_vScale, 00080 const CVector3 &_vPos ); 00081 00097 static CMatrix4x4 & LSE_FCALL TransformInterp( CMatrix4x4 &_mMatrix, 00098 const CQuaternion &_qRot, 00099 const CVector3 &_vScale, 00100 const CVector3 &_vPos, 00101 const CMatrix4x4 &_mTarget, 00102 LSREAL _fFrac ); 00103 00120 static CMatrix4x4 & LSE_FCALL TransformInterp( CMatrix4x4 &_mMatrix, 00121 const CQuaternion &_qRot, 00122 const CVector3 &_vScale, 00123 const CVector3 &_vPos, 00124 const CQuaternion &_qTargetRot, 00125 const CVector3 &_vTargetScale, 00126 const CVector3 &_vTargetPos, 00127 LSREAL _fFrac ); 00128 00136 static LSVOID LSE_FCALL TransformInertiaTensor( CMatrix3x3 &_mWorld, 00137 const CMatrix3x3 &_mInvInertiaTensor, 00138 const CMatrix4x4 &_mRot ); 00139 00149 static LSVOID LSE_FCALL MakeOrthonormalBasis( const CVector3 &_vX, 00150 CVector3 &_vY, 00151 CVector3 &_vZ ); 00152 00163 static LSVOID LSE_FCALL MakeOrthonormalBasisSlow( const CVector3 &_vX, 00164 CVector3 &_vY, 00165 CVector3 &_vZ ); 00166 00174 static LSREAL LSE_FCALL GetNormalizedZ( LSREAL _fX, LSREAL _fY ); 00175 00187 static CVector2 LSE_CALL InterpolateNonUniformQuad( const CVector2 &_vP0, const CVector2 &_vP1, const CVector2 &_vP2, const CVector2 &_vP3, 00188 LSREAL _fX, LSREAL _fY ); 00189 00190 }; 00191 00192 00193 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00194 // DEFINITIONS 00195 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00196 // == Functions. 00207 LSE_INLINE CMatrix4x4 & LSE_FCALL CHelpers::ComposeMatrix( CMatrix4x4 &_mMatrix, 00208 const CQuaternion &_qRot, 00209 const CVector3 &_vPos ) { 00210 00211 _qRot.ToRotationMatrix( _mMatrix ); 00212 _mMatrix( 0, 3 ) = LSM_ZERO; 00213 _mMatrix( 1, 3 ) = LSM_ZERO; 00214 _mMatrix( 2, 3 ) = LSM_ZERO; 00215 _mMatrix( 3, 3 ) = LSM_ONE; 00216 _mMatrix.SetRow( 3, _vPos ); 00217 return _mMatrix; 00218 } 00219 00230 LSE_INLINE CMatrix4x4 & LSE_FCALL CHelpers::ComposeMatrix( CMatrix4x4 &_mMatrix, 00231 const CQuaternion &_qRot, 00232 const CVector3 &_vScale, 00233 const CVector3 &_vPos ) { 00234 _qRot.ToRotationMatrix( _mMatrix ); 00235 _mMatrix( 0, 0 ) *= _vScale.x; 00236 _mMatrix( 0, 1 ) *= _vScale.x; 00237 _mMatrix( 0, 2 ) *= _vScale.x; 00238 _mMatrix( 1, 0 ) *= _vScale.y; 00239 _mMatrix( 1, 1 ) *= _vScale.y; 00240 _mMatrix( 1, 2 ) *= _vScale.y; 00241 _mMatrix( 2, 0 ) *= _vScale.z; 00242 _mMatrix( 2, 1 ) *= _vScale.z; 00243 _mMatrix( 2, 2 ) *= _vScale.z; 00244 _mMatrix( 0, 3 ) = LSM_ZERO; 00245 _mMatrix( 1, 3 ) = LSM_ZERO; 00246 _mMatrix( 2, 3 ) = LSM_ZERO; 00247 _mMatrix( 3, 3 ) = LSM_ONE; 00248 _mMatrix.SetRow( 3, _vPos ); 00249 return _mMatrix; 00250 } 00251 00259 LSE_INLINE LSVOID LSE_FCALL CHelpers::TransformInertiaTensor( CMatrix3x3 &_mWorld, 00260 const CMatrix3x3 &_mInvInertiaTensor, 00261 const CMatrix4x4 &_mRot ) { 00262 00263 LSREAL fT0 = _mRot( 0, 0 ) * _mInvInertiaTensor( 0, 0 ) + 00264 _mRot( 1, 0 ) * _mInvInertiaTensor( 0, 1 ) + 00265 _mRot( 2, 0 ) * _mInvInertiaTensor( 0, 2 ); 00266 LSREAL fT1 = _mRot( 0, 0 ) * _mInvInertiaTensor( 1, 0 ) + 00267 _mRot( 1, 0 ) * _mInvInertiaTensor( 1, 1 ) + 00268 _mRot( 2, 0 ) * _mInvInertiaTensor( 1, 2 ); 00269 LSREAL fT2 = _mRot( 0, 0 ) * _mInvInertiaTensor( 2, 0 ) + 00270 _mRot( 1, 0 ) * _mInvInertiaTensor( 2, 1 ) + 00271 _mRot( 2, 0 ) * _mInvInertiaTensor( 2, 2 ); 00272 LSREAL fT3 = _mRot( 0, 1 ) * _mInvInertiaTensor( 0, 0 ) + 00273 _mRot( 1, 1 ) * _mInvInertiaTensor( 0, 1 ) + 00274 _mRot( 2, 1 ) * _mInvInertiaTensor( 0, 2 ); 00275 LSREAL fT4 = _mRot( 0, 1 ) * _mInvInertiaTensor( 1, 0 ) + 00276 _mRot( 1, 1 ) * _mInvInertiaTensor( 1, 1 ) + 00277 _mRot( 2, 1 ) * _mInvInertiaTensor( 1, 2 ); 00278 LSREAL fT5 = _mRot( 0, 1 ) * _mInvInertiaTensor( 2, 0 ) + 00279 _mRot( 1, 1 ) * _mInvInertiaTensor( 2, 1 ) + 00280 _mRot( 2, 1 ) * _mInvInertiaTensor( 2, 2 ); 00281 LSREAL fT6 = _mRot( 0, 2 ) * _mInvInertiaTensor( 0, 0 ) + 00282 _mRot( 1, 2 ) * _mInvInertiaTensor( 0, 1 ) + 00283 _mRot( 2, 2 ) * _mInvInertiaTensor( 0, 2 ); 00284 LSREAL fT7 = _mRot( 0, 2 ) * _mInvInertiaTensor( 1, 0 ) + 00285 _mRot( 1, 2 ) * _mInvInertiaTensor( 1, 1 ) + 00286 _mRot( 2, 2 ) * _mInvInertiaTensor( 1, 2 ); 00287 LSREAL fT8 = _mRot( 0, 2 ) * _mInvInertiaTensor( 2, 0 ) + 00288 _mRot( 1, 2 ) * _mInvInertiaTensor( 2, 1 ) + 00289 _mRot( 2, 2 ) * _mInvInertiaTensor( 2, 2 ); 00290 00291 _mWorld( 0, 0 ) = fT0 * _mRot( 0, 0 ) + 00292 fT1 * _mRot( 1, 0 ) + 00293 fT2 * _mRot( 2, 0 ); 00294 _mWorld( 1, 0 ) = fT0 * _mRot( 0, 1 ) + 00295 fT1 * _mRot( 1, 1 ) + 00296 fT2 * _mRot( 2, 1 ); 00297 _mWorld( 2, 0 ) = fT0 * _mRot( 0, 2 ) + 00298 fT1 * _mRot( 1, 2 ) + 00299 fT2 * _mRot( 2, 2 ); 00300 _mWorld( 0, 1 ) = fT3 * _mRot( 0, 0 ) + 00301 fT4 * _mRot( 1, 0 ) + 00302 fT5 * _mRot( 2, 0 ); 00303 _mWorld( 1, 1 ) = fT3 * _mRot( 0, 1 ) + 00304 fT4 * _mRot( 1, 1 ) + 00305 fT5 * _mRot( 2, 1 ); 00306 _mWorld( 2, 1 ) = fT3 * _mRot( 0, 2 ) + 00307 fT4 * _mRot( 1, 2 ) + 00308 fT5 * _mRot( 2, 2 ); 00309 _mWorld( 0, 2 ) = fT6 * _mRot( 0, 0 ) + 00310 fT7 * _mRot( 1, 0 ) + 00311 fT8 * _mRot( 2, 0 ); 00312 _mWorld( 1, 2 ) = fT6 * _mRot( 0, 1 ) + 00313 fT7 * _mRot( 1, 1 ) + 00314 fT8 * _mRot( 2, 1 ); 00315 _mWorld( 2, 2 ) = fT6 * _mRot( 0, 2 ) + 00316 fT7 * _mRot( 1, 2 ) + 00317 fT8 * _mRot( 2, 2 ); 00318 } 00319 00329 LSE_INLINE LSVOID LSE_FCALL CHelpers::MakeOrthonormalBasis( const CVector3 &_vX, 00330 CVector3 &_vY, 00331 CVector3 &_vZ ) { 00332 // Check whether the X-axis is nearer to the X or Y axis. 00333 if ( CMathLib::Abs( _vX.x ) > CMathLib::Abs( _vX.y ) ) { 00334 // Scaling factor to ensure the results are normalized. 00335 const LSREAL fS = CMathLib::InvSqrt( _vX.z * _vX.z + 00336 _vX.x * _vX.x ); 00337 00338 // The new Y-axis is at right angles to the world Y-axis. 00339 _vY.x = _vX.z * fS; 00340 _vY.y = LSM_ZERO; 00341 _vY.z = -_vX.x * fS; 00342 00343 // The new Z-axis is at right angles to the new X- and Y- axes. 00344 _vZ.x = _vX.y * _vY.x; 00345 _vZ.y = _vX.z * _vY.x - 00346 _vX.x * _vY.z; 00347 _vZ.z = -_vX.y * _vY.x; 00348 } 00349 else { 00350 // Scaling factor to ensure the results are normalized. 00351 const LSREAL fS = CMathLib::InvSqrt( _vX.z * _vX.z + 00352 _vX.y * _vX.y ); 00353 00354 // The new Y-axis is at right angles to the world X-axis. 00355 _vY.x = LSM_ZERO; 00356 _vY.y = -_vX.z * fS; 00357 _vY.z = _vX.y * fS; 00358 00359 // The new Z-axis is at right angles to the new X- and Y- axes. 00360 _vZ.x = _vX.y * _vY.z - 00361 _vX.z * _vY.y; 00362 _vZ.y = -_vX.x * _vY.z; 00363 _vZ.z = _vX.x * _vY.y; 00364 } 00365 } 00366 00377 LSE_INLINE LSVOID LSE_FCALL CHelpers::MakeOrthonormalBasisSlow( const CVector3 &_vX, 00378 CVector3 &_vY, 00379 CVector3 &_vZ ) { 00380 00381 // Check whether the Z-axis is nearer to the X or Y axis. 00382 if ( CMathLib::Abs( _vX.x ) > CMathLib::Abs( _vX.y ) ) { 00383 _vZ = CVector3( LSM_ZERO, LSM_ONE, LSM_ZERO ) % _vX; 00384 } 00385 else { 00386 _vZ = CVector3( LSM_ONE, LSM_ZERO, LSM_ZERO ) % _vX; 00387 } 00388 _vY = _vX % _vZ; 00389 00390 _vZ.Normalize(); 00391 _vY.Normalize(); 00392 } 00393 00401 LSE_INLINE LSREAL LSE_FCALL CHelpers::GetNormalizedZ( LSREAL _fX, LSREAL _fY ) { 00402 LSREAL fTemp = LSM_ONE - ((_fX * _fX) + (_fY * _fY)); 00403 if ( CMathLib::Equals( fTemp, LSM_ZERO, LSM_REAL_EPSILON ) ) { return LSM_ZERO; } 00404 return CMathLib::Sqrt( fTemp ); 00405 } 00406 00407 } // namespace lsm 00408 00409 #endif // __LSM_HELPERS_H__