/* (c) Ubi R&D 1997*/ /* See Philippe Vimont & Alain Robin for any comment or question*/ #ifdef __cplusplus extern "C" { #endif /****************************************************************************/ /* INCLUDES */ /****************************************************************************/ #include "ACP_base.h" #include "cpa_std.h" #include "MTH.h" #include "PosPubSt.h" #include "PosProto.h" #include "safe.h" #define __DeclareGlobalVariableMmgPos_h__ #define __DeclareGlobalVariableErmPos_h__ #include "ErrPos.h" #include "MmgPos.h" #undef __DeclareGlobalVariableMmgPos_h__ #undef __DeclareGlobalVariableErmPos_h__ #include "GEO.h" #ifdef _DEBUG /* {*/ #define POS_M_MustBeValid(handle) \ { \ SAF_M_AssertWithMsg((((handle) != (POS_tdxHandleToPosition)POS_C_ulInvalidHandle)&&(handle != NULL))," Invalid handle ") \ if(((handle) == (POS_tdxHandleToPosition)POS_C_ulInvalidHandle)||(handle == NULL)) \ Erm_M_UpdateLastError(Pos, C_ucErmDefaultChannel, E_uwPosFatalError1, C_lErmNoDebugData, C_ucAllowStopForDebug, C_ucAllowStopForDebug, NULL); \ } #define POS_M_MustBeModifiable(handle) \ { \ SAF_M_AssertWithMsg((handle != POS_g_p_stIdentityMatrix)," Constant matrix can't be modified") \ if(handle == POS_g_p_stIdentityMatrix) \ Erm_M_UpdateLastError(Pos, C_ucErmDefaultChannel, E_uwPosFatalError1, C_lErmNoDebugData, C_ucAllowStopForDebug, C_ucAllowStopForDebug, NULL); \ } #endif /* _DEBUG }*/ #define POS_C_xDeltaScale ((MTH_tdxReal)0.005) /* 0.5% of precision loss*/ #define POS_M_bIsDeltaNull(a) MTH_M_bLess(MTH_M_xAbs((a)),POS_C_xDeltaScale) #define POS_M_xEpsilonEqual ((MTH_tdxReal)0.005) #define POS_M_bIsVectorNull(p_stVect) \ (MTH_M_bIsNullWithEpsilon((p_stVect)->xX,POS_M_xEpsilonEqual) && \ MTH_M_bIsNullWithEpsilon((p_stVect)->xY,POS_M_xEpsilonEqual) && \ MTH_M_bIsNullWithEpsilon((p_stVect)->xZ,POS_M_xEpsilonEqual)) #define POS_M_bIsMatrixIdentity(p_stMatrix) \ (MTH_M_bEqualWithEpsilon((p_stMatrix)->stCol_0.xX,MTH_C_ONE,POS_M_xEpsilonEqual) && \ MTH_M_bIsNullWithEpsilon((p_stMatrix)->stCol_0.xY,POS_M_xEpsilonEqual) && \ MTH_M_bIsNullWithEpsilon((p_stMatrix)->stCol_0.xZ,POS_M_xEpsilonEqual) && \ MTH_M_bIsNullWithEpsilon((p_stMatrix)->stCol_1.xX,POS_M_xEpsilonEqual) && \ MTH_M_bEqualWithEpsilon((p_stMatrix)->stCol_1.xY,MTH_C_ONE,POS_M_xEpsilonEqual) && \ MTH_M_bIsNullWithEpsilon((p_stMatrix)->stCol_1.xZ,POS_M_xEpsilonEqual) && \ MTH_M_bIsNullWithEpsilon((p_stMatrix)->stCol_2.xX,POS_M_xEpsilonEqual) && \ MTH_M_bIsNullWithEpsilon((p_stMatrix)->stCol_2.xY,POS_M_xEpsilonEqual) && \ MTH_M_bEqualWithEpsilon((p_stMatrix)->stCol_2.xZ,MTH_C_ONE,POS_M_xEpsilonEqual)) /***************************/ unsigned long POS_ulIsMatrixDeltaNull(MTH3D_tdstMatrix* _p_stMatrix); #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ ACP_tdxBool POS_g_bAlreadyInitialized=FALSE; #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ POS_tdstCompletePosition *POS_g_p_stIdentityMatrix; /*for internal use: use the constant identity matrix to reset other matrixes more easily*/ INLINE void fn_vSetMatrixAsIdentity(MTH3D_tdstMatrix *_hMatrix) { *_hMatrix = POS_g_p_stIdentityMatrix->stRotationMatrix; } INLINE void fn_vSetVectorAsNull(MTH3D_tdstVector *_hVector) { *_hVector = POS_g_p_stIdentityMatrix->stTranslationVector; } /*---------------------------------------------------------------------------- // Description : POS_fn_vInitPos // Init Error & Memory ----------------------------------------------------------------------------// // Methods : None ----------------------------------------------------------------------------// // Input : // Output : ----------------------------------------------------------------------------// // Creation date : May 97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ void POS_fn_vInitPos() { /* circumvent const qualifier*/ POS_tdstCompletePosition *_hConstPos; GEO_M_CPAMalloc(POS_g_p_stIdentityMatrix,POS_tdstCompletePosition *,sizeof(struct POS_stCompletePosition),E_uwGEONotEnoughtMemory ); _hConstPos = (POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix; /* Fill the reference identity matrix*/ MTH3D_M_vNullVector(&(_hConstPos->stTranslationVector)); MTH3D_M_vSetIdentityMatrix(&(_hConstPos->stRotationMatrix)); MTH3D_M_vSetIdentityMatrix(&(_hConstPos->stTransformMatrix)); _hConstPos->ulType = POS_C_ulIdentityMatrixFlag; } #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ void POS_fn_vFirstInit() { Erm_M_InitErrMsg(Pos); Mmg_M_InitMmg(Pos); Mmg_fn_cCheckAlignmentValidity(); } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /*---------------------------------------------------------------------------- // Description : POS_fn_vInitPos // Init Error & Memory ----------------------------------------------------------------------------// // Methods : None ----------------------------------------------------------------------------// // Input : // Output : ----------------------------------------------------------------------------// // Creation date : May 97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ void POS_fn_vInitPosMemory(unsigned long _ulMemorySize) { if(!POS_g_bAlreadyInitialized) { #ifdef _POS_USE_POSMEM /* MR2207*/ Mmg_M_InitBlock(Pos,E_ucPosBlock1,_ulMemorySize); /* must be into the scripts*/ g_ucPOSMMemMallocMode=E_ucPosBlock1; Mmg_fn_cCheckAlignmentValidity(); #endif POS_g_bAlreadyInitialized=TRUE; } } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /*---------------------------------------------------------------------------- // Description : POS_fn_hCreateMatrix // To create an empty matrix handle (initialized to identity) ----------------------------------------------------------------------------// // Methods : None ----------------------------------------------------------------------------// // Input : None // Output : Handle to the created matrix ----------------------------------------------------------------------------// // Creation date : 29 Jan 97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ /*oooo*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ POS_tdxHandleToPosition POS_fn_hCreateMatrix() { POS_tdxHandleToPosition hNewPosMatrix; #ifdef _POS_USE_POSMEM Mmg_M_SetModeAlloc4Ch(Pos, g_ucPOSMMemMallocMode, C_ucMmgDefaultChannel); #endif /* alloc matrix*/ MMG_fn_vAddMemoryInfo( MMG_C_lTypePosition , MMG_C_lSubTypePosition , 0 ); hNewPosMatrix=(POS_tdxHandleToPosition)Mmg_fn_p_vAlloc4Ch(sizeof(struct POS_stCompletePosition),C_ucMmgDefaultChannel ); /* set to Identity*/ #ifdef _DEBUG if(hNewPosMatrix) #endif { /*circumvent const qualifier*/ POS_fn_vCopyMatrix (hNewPosMatrix,(POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix); } return hNewPosMatrix; } /*---------------------------------------------------------------------------- // Description : POS_fn_vSetMatrixToIdentityConst // To set given handle to the Identity Matrix (the matrix can't be modifier later) ----------------------------------------------------------------------------// // Input : _hMatrix : a pointer to the handle to a position // Output : ----------------------------------------------------------------------------*/ void POS_fn_vSetMatrixToIdentityConst(POS_tdxHandleToPosition *_p_hMatrix) { /*circumvent const qualifier*/ *_p_hMatrix = (POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix; } /*---------------------------------------------------------------------------- // Description : POS_fn_vIsMatrixIdentityConst // ----------------------------------------------------------------------------// // Input : _hMatrix : a pointer to the handle to a position // Output : ----------------------------------------------------------------------------*/ ACP_tdxBool POS_fn_vIsMatrixIdentityConst(POS_tdxHandleToPosition _hMatrix) { return (ACP_tdxBool)((_hMatrix == POS_g_p_stIdentityMatrix) ? TRUE : FALSE); } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /*---------------------------------------------------------------------------- // Description : POS_fn_hGetMatrixIdentityConst // ----------------------------------------------------------------------------// // Input : _hMatrix : a pointer to the handle to a position // Output : ----------------------------------------------------------------------------*/ POS_tdxHandleToPosition POS_fn_hGetMatrixIdentityConst() { /*circumvent const qualifier*/ return (POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix; } /****************************************************************************/ /* INITIALISATION FUNCTIONS */ /****************************************************************************/ /*---------------------------------------------------------------------------- // Description : POS_fn_vResetScaleMatrix // reset the scale of a matrix ----------------------------------------------------------------------------// // Methods : none ----------------------------------------------------------------------------// // Input : _hMatrix : matrix to be initialized // Output : ----------------------------------------------------------------------------// // Creation date : ? Author: ? ----------------------------------------------------------------------------// // Modifications : Remove the transformation matrix computation // Modification date : 07/02/97 Modification author : Alain Robin ------------------------------------------------------------------------------ // Modifications : With the new structure, we have just to copy the rotation // matrix into the transform matrix. // This function is used only for the complete positions. // Modification date : 12/03/97 Modification author : Alain Robin // Modification date : 03/07/98 Modification author : Marc Trabucato ----------------------------------------------------------------------------*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ void POS_fn_vResetScaleMatrix ( POS_tdxHandleToPosition _hMatrix ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); POS_M_MustBeModifiable(_hMatrix); #endif /* We have just to copy the rotation matrix into the transformation matrix */ if ( _hMatrix->ulType > POS_C_ulRotationMatrixFlag ) { MTH3D_M_vCopyMatrix(&(_hMatrix->stTransformMatrix), &(_hMatrix->stRotationMatrix)); _hMatrix->ulType = POS_C_ulRotationMatrixFlag; } } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /*---------------------------------------------------------------------------- // Description : POS_fn_vSetIdentityMatrix // SETTING A MATRIX TO IDENTITY ----------------------------------------------------------------------------// // Input : _hMatrix : matrix to be initialized // Output : None ----------------------------------------------------------------------------// // Creation date : ???/97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : 03/07/98 Modification author : Marc Trabucato ----------------------------------------------------------------------------*/ void POS_fn_vSetIdentityMatrix ( POS_tdxHandleToPosition _hMatrix ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); POS_M_MustBeModifiable(_hMatrix); MTH3D_M_vNullVector(&(_hMatrix->stTranslationVector)); MTH3D_M_vSetIdentityMatrix(&(_hMatrix->stRotationMatrix)); MTH3D_M_vSetIdentityMatrix(&(_hMatrix->stTransformMatrix)); _hMatrix->ulType = POS_C_ulIdentityMatrixFlag; #else /*circumvent const qualifier*/ POS_fn_vCopyMatrix(_hMatrix, (POS_tdstCompletePosition *) POS_g_p_stIdentityMatrix); #endif } /****************************************************************************/ /* COMPLEX FUNCTIONS */ /****************************************************************************/ /*---------------------------------------------------------------------------- // Description : POS_fn_vMulMatrixVertex // MULTIPLYING A MATRIX WITH A VERTEX ----------------------------------------------------------------------------// // Methods : none ----------------------------------------------------------------------------// // Input : _hMatrix : matrix // _p_stSource : source vertex // Output : _p_stDest : pointer to the transformed vertex ----------------------------------------------------------------------------// // Creation date : ???/97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : 03/07/98 Modification author : Marc Trabucato ----------------------------------------------------------------------------*/ void POS_fn_vMulMatrixVertex( MTH3D_tdstVector *_p_stDest, POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stSource ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif switch ( _hMatrix->ulType ) { case POS_C_ulIdentityMatrixFlag: if ( _p_stDest != _p_stSource ) { MTH3D_M_vCopyVector(_p_stDest, _p_stSource); } break; case POS_C_ulTranslationMatrixFlag: /*only the translation vector is safe, the rest might be trash*/ MTH3D_M_vAddVector(_p_stDest, &(_hMatrix->stTranslationVector), _p_stSource); break; case POS_C_ulRotationMatrixFlag: /*only the translation and rotation are safe, the transform data might be trash*/ MTH3D_M_vMulMatrixVector(_p_stDest, &(_hMatrix->stRotationMatrix), _p_stSource); MTH3D_M_vAddVector(_p_stDest, &(_hMatrix->stTranslationVector), _p_stDest); break; case POS_C_ulCompleteMatrixFlag: MTH3D_M_vMulMatrixVector(_p_stDest, &(_hMatrix->stTransformMatrix), _p_stSource); MTH3D_M_vAddVector(_p_stDest, &(_hMatrix->stTranslationVector), _p_stDest); break; default: /*we should never work with uninitialized matrixes!*/ * (long *) 0x00000000 = 5; break; } } /*---------------------------------------------------------------------------- // Description : POS_fn_vMulMatrixVector // MULTIPLYING A MATRIX WITH A VECTOR ----------------------------------------------------------------------------// // Methods : none ----------------------------------------------------------------------------// // Input : _hMatrix : matrix // _p_stSource : source vertor // Output : _p_stDest : pointer to the transformed vertor ----------------------------------------------------------------------------// // Creation date : ???/97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : 03/07/98 Modification author : Marc Trabucato ----------------------------------------------------------------------------*/ void POS_fn_vMulMatrixVector( MTH3D_tdstVector *_p_stDest, POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stSource ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif M_CheckPointer(_p_stDest); M_CheckPointer(_hMatrix); M_CheckPointer(_p_stSource); switch ( _hMatrix->ulType ) { case POS_C_ulIdentityMatrixFlag: case POS_C_ulTranslationMatrixFlag: /*only the translation vector is relevant*/ /*the vector remains unchanged*/ if ( _p_stDest != _p_stSource ) { MTH3D_M_vCopyVector(_p_stDest, _p_stSource); } break; case POS_C_ulRotationMatrixFlag: /*only the translation and rotation are relevant*/ MTH3D_M_vMulMatrixVector(_p_stDest, &(_hMatrix->stRotationMatrix), _p_stSource); break; case POS_C_ulCompleteMatrixFlag: MTH3D_M_vMulMatrixVector(_p_stDest, &(_hMatrix->stTransformMatrix), _p_stSource); break; default: /*we should never work with uninitialized matrixes!*/ * (long *) 0x00000000 = 5; break; } } /*---------------------------------------------------------------------------- // Description : POS_fn_vRotateVector // ROTATE A VECTOR ----------------------------------------------------------------------------// // Methods : multiply a vector with the rotate component ----------------------------------------------------------------------------// // Input : _hMatrix : matrix // _p_stSource : source vertor // Output : _p_stDest : pointer to the transformed vertor ----------------------------------------------------------------------------// // Creation date : 03/06/97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : 03/07/98 Modification author : Marc Trabucato ----------------------------------------------------------------------------*/ void POS_fn_vRotateVector( MTH3D_tdstVector *_p_stDest, POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stSource ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif switch (_hMatrix->ulType ) { case POS_C_ulIdentityMatrixFlag: case POS_C_ulTranslationMatrixFlag: /*the vector remains unchanged*/ if ( _p_stDest != _p_stSource ) { MTH3D_M_vCopyVector(_p_stDest,_p_stSource); } break; case POS_C_ulRotationMatrixFlag: /*we use only the rotation, whether the matrix is scaled or not*/ case POS_C_ulCompleteMatrixFlag: MTH3D_M_vMulMatrixVector(_p_stDest, &(_hMatrix->stRotationMatrix), _p_stSource); break; default: /*we should never work with uninitialized matrixes!*/ * (long *) 0x00000000 = 5; break; } } /******************** RESULT = INV(A)*B ***********************************/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ void POS_fn_vMulInvMatrixMatrix( POS_tdxHandleToPosition _hDest, POS_tdxHandleToPosition _hA, POS_tdxHandleToPosition _hB ) { #ifdef _DEBUG POS_M_MustBeValid(_hA); POS_M_MustBeValid(_hB); POS_M_MustBeValid(_hDest); POS_M_MustBeModifiable(_hDest); #endif if ( _hA->ulType == POS_C_ulIdentityMatrixFlag ) { if ( _hDest != _hB ) { POS_fn_vCopyMatrix(_hDest, _hB); } } else { POS_tdstCompletePosition stInvA; POS_fn_vInvertMatrix(&stInvA, _hA); POS_fn_vMulMatrixMatrix(_hDest, &stInvA, _hB); } } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /******************** INVERTING AN ISOMETRIC MATRIX *********************/ /*---------------------------------------------------------------------------- // Description : INVERTING AN ISOMETRIC MATRIX // Invert a position with an isometric scale -> the result matrix has no scale! ------------------------------------------------------------------------------ // Methods : See code ------------------------------------------------------------------------------ // Input : _hSource : position to invert // Output : _hDest : destination ------------------------------------------------------------------------------ // Creation date : ??? Author: Alain Robin ------------------------------------------------------------------------------ // Modification date : May 98 Modification author : AR // Modifications : Optimisations and correction of bugs ----------------------------------------------------------------------------*/ void POS_fn_vInvertIsoMatrix(POS_tdxHandleToPosition _hDest, POS_tdxHandleToPosition _hSource) { /* Validity tests*/ #ifdef _DEBUG POS_M_MustBeValid(_hSource); POS_M_MustBeValid(_hDest); POS_M_MustBeModifiable(_hDest); #endif switch ( _hSource->ulType ) { case POS_C_ulIdentityMatrixFlag: if( _hDest != _hSource ) { /*_hDest->ulType = POS_C_ulIdentityMatrixFlag;*/ POS_fn_vSetIdentityMatrix( _hDest ); } break; case POS_C_ulTranslationMatrixFlag: MTH3D_M_vNegVector( &(_hDest->stTranslationVector), &(_hSource->stTranslationVector) ); if( _hDest != _hSource ) { fn_vSetMatrixAsIdentity(&(_hDest->stTransformMatrix)); fn_vSetMatrixAsIdentity(&(_hDest->stRotationMatrix)); _hDest->ulType = POS_C_ulTranslationMatrixFlag; } break; default: /*rotation or complete matrixes*/ { MTH3D_tdstVector stVertex; /* Invert rotation*/ if( _hDest != _hSource ) { MTH3D_M_vTranspMatrixWithoutBuffer(&(_hDest->stRotationMatrix),&(_hSource->stRotationMatrix)); } else { MTH3D_M_vTranspMatrix(&(_hDest->stRotationMatrix),&(_hSource->stRotationMatrix)); } /*the transform matrix remains equal to the rotation matrix*/ MTH3D_M_vCopyMatrix(&(_hDest->stTransformMatrix),&(_hDest->stRotationMatrix)); /*invert translation*/ MTH3D_M_vNegVector(&stVertex, &(_hSource->stTranslationVector) ); /*if ( _hSource->ulType > POS_C_ulRotationMatrixFlag ) { MTH3D_M_vMulMatrixVector(&(_hDest->stTranslationVector),&(_hDest->stTransformMatrix),&stVertex); } else {*/ MTH3D_M_vMulMatrixVector(&(_hDest->stTranslationVector),&(_hDest->stTransformMatrix),&stVertex); /*}*/ _hDest->ulType = POS_C_ulRotationMatrixFlag; } break; } } /*---------------------------------------------------------------------------- // Description : INVERTING A POSITION // Invert a position (general case) ------------------------------------------------------------------------------ // Methods : See code ------------------------------------------------------------------------------ // Input : _hSource : position to invert // Output : _hDest : destination ------------------------------------------------------------------------------ // Creation date : ??? Author: Alain Robin ------------------------------------------------------------------------------ // Modification date : May 98 Modification author : AR // Modifications : Optimisations and correction of bugs ----------------------------------------------------------------------------*/ void POS_fn_vInvertMatrix(POS_tdxHandleToPosition _hDest, POS_tdxHandleToPosition _hSource) { #ifdef _DEBUG POS_M_MustBeValid(_hSource); POS_M_MustBeValid(_hDest); POS_M_MustBeModifiable(_hDest); #endif if(_hSource->ulType <= POS_C_ulRotationMatrixFlag ) { POS_fn_vInvertIsoMatrix(_hDest, _hSource); } else { MTH3D_tdstVector stVertex; /*invert the rotation by transposing it*/ if ( _hDest != _hSource ) { MTH3D_M_vTranspMatrixWithoutBuffer(&(_hDest->stRotationMatrix),&(_hSource->stRotationMatrix)); } else { MTH3D_M_vTranspMatrix(&(_hDest->stRotationMatrix),&(_hSource->stRotationMatrix)); } /*invert the transform matrix*/ MTH3D_M_vInverMatrix(&(_hDest->stTransformMatrix),&(_hSource->stTransformMatrix)); /*invert the translation accordingly*/ MTH3D_M_vNegVector(&stVertex, &(_hSource->stTranslationVector) ); MTH3D_M_vMulMatrixVector(&(_hDest->stTranslationVector), &(_hDest->stTransformMatrix), &stVertex); /*do not forget to set the matrix type!*/ _hDest->ulType = POS_C_ulCompleteMatrixFlag; } } /************ NORMALIZING THE 3x3 ROTATION COMPONENT OF A MATRIX **********/ void POS_fn_vNormalizeMatrix(POS_tdxHandleToPosition _hMatrix) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); POS_M_MustBeModifiable(_hMatrix); #endif if ( _hMatrix->ulType >= POS_C_ulRotationMatrixFlag ) { MTH3D_tdstVector *p_stI , *p_stJ , *p_stK ; /*normalize the rotation*/ POS_fn_vGetRotationVector( _hMatrix , &p_stI , &p_stJ , &p_stK ) ; MTH3D_M_vCrossProductVectorWithoutBuffer( p_stJ , p_stK , p_stI ) ; /* J= K*I*/ SAF_M_AssertWithMsg((! MTH3D_M_bIsNullVector(p_stI)),"Normalisation d'une matrice incorrecte") MTH3D_M_vNormalizeVector( p_stI,p_stI ) ; /* |I|= 1*/ SAF_M_AssertWithMsg((! MTH3D_M_bIsNullVector(p_stJ)),"Normalisation d'une matrice incorrecte") MTH3D_M_vNormalizeVector( p_stJ,p_stJ ) ; /* |J|= 1*/ MTH3D_M_vCrossProductVectorWithoutBuffer( p_stK , p_stI , p_stJ ) ; /* K= I*J ; |K|= 1*/ /*MTH3D_M_vNormalizeVector( &stK,&stK ) ; // useless !*/ /*since we worked directly in the position's rotation matrix, it is up-to-date ->*/ /*a call to POS_fn_vSetRotationMatrix() is unnecessary, which */ /*the matrix is not scaled anymore*/ MTH3D_M_vCopyMatrix( &(_hMatrix->stTransformMatrix), &(_hMatrix->stRotationMatrix) ); _hMatrix->ulType = POS_C_ulRotationMatrixFlag; } } /*---------------------------------------------------------------------------- // Description : POS_fn_vMulMatrixMatrix // Multiply 2 positions ----------------------------------------------------------------------------// // Method : Same than MulMatrixMatrix ----------------------------------------------------------------------------// // Input : _hA, _hB : Handle to the positions to be multiplied // Output : _hDest ----------------------------------------------------------------------------// // Creation date : May 97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : // Alexis Vaisse - May 28 1998 : use a temporary matrix only if necesary (-> 10-15 % faster) ----------------------------------------------------------------------------*/ void POS_fn_vMulMatrixMatrix( POS_tdxHandleToPosition _hDest, POS_tdxHandleToPosition _hA, POS_tdxHandleToPosition _hB ) { POS_tdstCompletePosition stTempMatrix , *p_stResult; unsigned long ulResultType; #ifdef _DEBUG POS_M_MustBeValid(_hA); POS_M_MustBeValid(_hB); POS_M_MustBeValid(_hDest); POS_M_MustBeModifiable(_hDest); #endif M_CheckPointer(_hDest); M_CheckPointer(_hA); M_CheckPointer(_hB); if (_hA->ulType == POS_C_ulIdentityMatrixFlag ) { if ( _hB != _hDest ) { POS_fn_vCopyMatrix(_hDest, _hB); } return; } if ( _hB->ulType == POS_C_ulIdentityMatrixFlag ) { if ( _hA != _hDest ) { POS_fn_vCopyMatrix(_hDest, _hA); } return; } if ( (_hDest == _hA) || (_hDest == _hB) ) { p_stResult = &stTempMatrix; } else { p_stResult = _hDest; } ulResultType = max(_hA->ulType, _hB->ulType); /* multiply translation vector*/ MTH3D_M_vTransformVectorWithoutBuffer(&(p_stResult->stTranslationVector), &(_hA->stTransformMatrix), &(_hB->stTranslationVector), &(_hA->stTranslationVector)); /* multiply rotation matrices*/ MTH3D_M_vMulMatrixMatrixWithoutBuffer(&(p_stResult->stRotationMatrix), &(_hA->stRotationMatrix), &(_hB->stRotationMatrix)); /*if no source matrix has scale, the destination won't have either*/ if ( ulResultType <= POS_C_ulRotationMatrixFlag ) { MTH3D_M_vCopyMatrix( &(p_stResult->stTransformMatrix), &(p_stResult->stRotationMatrix) ); } else { MTH3D_M_vMulMatrixMatrixWithoutBuffer(&(p_stResult->stTransformMatrix), &(_hA->stTransformMatrix), &(_hB->stTransformMatrix) ); } if( _hDest != p_stResult ) POS_fn_vCopyMatrix(_hDest, p_stResult); _hDest->ulType = ulResultType; } /*---------------------------------------------------------------------------- // Description : POS_fn_vRotatePositionAroundAxis // Rotate a position around an axis passing by the origin with a given angle ------------------------------------------------------------------------------ // Method : create a quaternion, decompress it and multiply the matrices ------------------------------------------------------------------------------ // Input : _hPos : Position to be rotated // _p_stAxisVector : components of the axis // _xAngle : Angle of the rotation // WARNING : THE VECTOR (X,Y,Z) must be normed and the angle is defined with // the antitrigonometric sense // Output : ------------------------------------------------------------------------------ // Creation date : Jul 97 Author: Alain Robin ------------------------------------------------------------------------------ // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ void POS_fn_vRotatePositionAroundAxis( POS_tdxHandleToPosition _hPos, MTH3D_tdstVector* _p_stAxisVector, MTH_tdxReal _xAngle ) { MTH3D_tdstMatrix stMatrix; MTH3D_tdstVector stAxis ; MTH_tdxReal xSinAngle; #ifdef _DEBUG POS_M_MustBeValid(_hPos); POS_M_MustBeModifiable(_hPos); #endif /* Normalize the quaternion */ _xAngle = MTH_M_xMul(_xAngle,MTH_C_Inv2); xSinAngle = MTH_M_xSin(_xAngle); _xAngle = MTH_M_xCos(_xAngle); MTH3D_M_vMulScalarVector ( & stAxis , xSinAngle , _p_stAxisVector ) ; POS_fn_vQuatToMat ( & stMatrix , stAxis . xX , stAxis . xY , stAxis . xZ , _xAngle ) ; /* rotation matrix */ if ( _hPos->ulType <= POS_C_ulTranslationMatrixFlag ) /* no rotation*/ { MTH3D_M_vCopyMatrix(&(_hPos->stRotationMatrix), &stMatrix); } else { MTH3D_M_vMulMatrixMatrix(&(_hPos->stRotationMatrix), &(_hPos->stRotationMatrix), &stMatrix); } /* transform matrix */ if ( _hPos->ulType <= POS_C_ulRotationMatrixFlag ) /* no scale*/ { MTH3D_M_vCopyMatrix(&(_hPos->stTransformMatrix), &(_hPos->stRotationMatrix)); } else { MTH3D_M_vMulMatrixMatrix(&(_hPos->stTransformMatrix), &(_hPos->stTransformMatrix), &stMatrix); } /* translation */ MTH3D_M_vMulMatrixVector(&(_hPos->stTranslationVector), &stMatrix, &(_hPos->stTranslationVector)); _hPos->ulType = max(_hPos->ulType, POS_C_ulRotationMatrixFlag); } /*---------------------------------------------------------------------------- // Description : POS_fn_vRotatePositionAroundAxisNoTranslation // Rotate a position around an axis passing by the origin with a given angle ------------------------------------------------------------------------------ // Method : create a quaternion, decompress it and multiply the matrices ------------------------------------------------------------------------------ // Input : _hPos : Position to be rotated // _p_stAxisVector : components of the axis // _xAngle : Angle of the rotation // WARNING : THE VECTOR (X,Y,Z) must be normed and the angle is defined with // the antitrigonometric sense // Output : ------------------------------------------------------------------------------ // Creation date : Feb 98 Author: Benoit Germain ------------------------------------------------------------------------------ // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ void POS_fn_vRotatePositionAroundAxisNoTranslation( POS_tdxHandleToPosition _hPos, MTH3D_tdstVector* _p_stAxisVector, MTH_tdxReal _xAngle ) { MTH3D_tdstMatrix stMatrix; MTH3D_tdstVector stAxis ; MTH_tdxReal xSinAngle; #ifdef _DEBUG POS_M_MustBeValid(_hPos); POS_M_MustBeModifiable(_hPos); #endif /* Normalize the quaternion */ _xAngle = MTH_M_xMul(_xAngle,MTH_C_Inv2); xSinAngle = MTH_M_xSin(_xAngle); _xAngle = MTH_M_xCos(_xAngle); MTH3D_M_vMulScalarVector ( & stAxis , xSinAngle , _p_stAxisVector ) ; POS_fn_vQuatToMat ( & stMatrix , stAxis . xX , stAxis . xY , stAxis . xZ , _xAngle ) ; /* rotation matrix */ if ( _hPos->ulType <= POS_C_ulTranslationMatrixFlag ) /* no rotation*/ { /*rotation is identity: copy the new rotation immediately*/ MTH3D_M_vCopyMatrix(&(_hPos->stRotationMatrix), &stMatrix); } else /*rotation is not identity: multiply matrixes*/ { MTH3D_M_vMulMatrixMatrix(&(_hPos->stRotationMatrix), &(_hPos->stRotationMatrix), &stMatrix); } /* transform matrix */ if ( _hPos->ulType <= POS_C_ulRotationMatrixFlag ) /* no scale*/ { MTH3D_M_vCopyMatrix(&(_hPos->stTransformMatrix),&(_hPos->stRotationMatrix)); } else { MTH3D_M_vMulMatrixMatrix(&(_hPos->stTransformMatrix), &(_hPos->stTransformMatrix), &stMatrix); } _hPos->ulType = max(_hPos->ulType, POS_C_ulRotationMatrixFlag); } /*ANNECY BBB }*/ /****************************************************************************/ void POS_fn_vRotateX(POS_tdxHandleToPosition hMatrix, MTH_tdxReal xXAngle) { MTH3D_tdstVector stI; MTH3D_tdstVector stJ; MTH3D_tdstVector stK; MTH_tdxReal xSin = MTH_M_xSin(xXAngle); MTH_tdxReal xCos = MTH_M_xCos(xXAngle); /* POS_fn_vGetRotationMatrix(hMatrix, &stI, &stJ, &stK); //utility ??? AR9808*/ MTH3D_M_vSetVectorElements(&stI, MTH_C_ONE, MTH_C_ZERO, MTH_C_ZERO); MTH3D_M_vSetVectorElements(&stJ, MTH_C_ZERO, xCos, xSin); MTH3D_M_vSetVectorElements(&stK, MTH_C_ZERO, MTH_M_xNeg(xSin), xCos); POS_fn_vSetRotationMatrix(hMatrix, &stI, &stJ, &stK); } /****************************************************************************/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ void POS_fn_vRotateY(POS_tdxHandleToPosition hMatrix,MTH_tdxReal xYAngle) { MTH3D_tdstVector stI; MTH3D_tdstVector stJ; MTH3D_tdstVector stK; MTH_tdxReal xSin = MTH_M_xSin(xYAngle); MTH_tdxReal xCos = MTH_M_xCos(xYAngle); /* POS_fn_vGetRotationMatrix(hMatrix, &stI, &stJ, &stK); //utility ??? AR9808*/ MTH3D_M_vSetVectorElements(&stI, xCos, MTH_C_ZERO, MTH_M_xNeg(xSin)); MTH3D_M_vSetVectorElements(&stJ, MTH_C_ZERO, MTH_C_ONE, MTH_C_ZERO); MTH3D_M_vSetVectorElements(&stK, xSin, MTH_C_ZERO, xCos); POS_fn_vSetRotationMatrix(hMatrix, &stI, &stJ, &stK); } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /****************************************************************************/ void POS_fn_vRotateZ(POS_tdxHandleToPosition hMatrix,MTH_tdxReal xZAngle) { MTH3D_tdstVector stI; MTH3D_tdstVector stJ; MTH3D_tdstVector stK; MTH_tdxReal xSin = MTH_M_xSin(xZAngle); MTH_tdxReal xCos = MTH_M_xCos(xZAngle); /* POS_fn_vGetRotationMatrix(hMatrix, &stI, &stJ, &stK); //utility ??? AR9808*/ MTH3D_M_vSetVectorElements(&stI, xCos, xSin, MTH_C_ZERO); MTH3D_M_vSetVectorElements(&stJ, MTH_M_xNeg(xSin), xCos, MTH_C_ZERO); MTH3D_M_vSetVectorElements(&stK, MTH_C_ZERO, MTH_C_ZERO, MTH_C_ONE); POS_fn_vSetRotationMatrix(hMatrix, &stI, &stJ, &stK); } /****************************************************************************/ /* ACCESSORS */ /****************************************************************************/ /************* SETTING THE 3x3 ROTATION COMPONENT OF A MATRIX ***************/ void POS_fn_vSetRotationMatrix( POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stI, MTH3D_tdstVector *_p_stJ, MTH3D_tdstVector *_p_stK ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); POS_M_MustBeModifiable(_hMatrix); #endif switch(_hMatrix->ulType) { case POS_C_ulIdentityMatrixFlag: case POS_C_ulTranslationMatrixFlag: case POS_C_ulRotationMatrixFlag: MTH3D_M_vSetVectorsInMatrix( &(_hMatrix->stRotationMatrix), _p_stI, _p_stJ, _p_stK ); MTH3D_M_vCopyMatrix(&(_hMatrix->stTransformMatrix), &(_hMatrix->stRotationMatrix)); _hMatrix->ulType = POS_C_ulRotationMatrixFlag; break; default: /*matrix has a complex scale*/ { MTH3D_tdstMatrix stScaleMatrix; /* First, we must Get the scale component */ POS_fn_vGetScaleMatrix( _hMatrix, &(stScaleMatrix.stCol_0), &(stScaleMatrix.stCol_1), &(stScaleMatrix.stCol_2) ); /*apply the new rotation*/ MTH3D_M_vSetVectorsInMatrix( &(_hMatrix->stRotationMatrix), _p_stI, _p_stJ, _p_stK ); /* After that, we can compute the new transform matrix */ MTH3D_M_vMulMatrixMatrixWithoutBuffer(&(_hMatrix->stTransformMatrix), &(_hMatrix->stRotationMatrix), &stScaleMatrix); } break; } } /************* GETTING THE COLUMNS OF THE 3x3 ROTATION COMPONENT OF A MATRIX *************/ /* POS_fn_vGetRotationMatrixCol2(p_stCurrentMatrix, &stZ);*/ void POS_fn_vGetRotationMatrixCol2( POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stCol2 ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif MTH3D_M_vGetColumnInMatrix(_p_stCol2,&(_hMatrix->stRotationMatrix),2); } void POS_fn_vGetRotationMatrix( POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stI, MTH3D_tdstVector *_p_stJ, MTH3D_tdstVector *_p_stK ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif MTH3D_M_vGetVectorsInMatrix( _p_stI, _p_stJ, _p_stK, &(_hMatrix->stRotationMatrix) ); } void POS_fn_vGetRotationVector( POS_tdxHandleToPosition _hMatrix , MTH3D_tdstVector **_p_p_stI, MTH3D_tdstVector **_p_p_stJ, MTH3D_tdstVector **_p_p_stK ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif *_p_p_stI = &(_hMatrix->stRotationMatrix.stCol_0); *_p_p_stJ = &(_hMatrix->stRotationMatrix.stCol_1); *_p_p_stK = &(_hMatrix->stRotationMatrix.stCol_2); } /************* SETTING THE 3x3 SCALING COMPONENT OF A MATRIX *************/ void POS_fn_vSetScaleMatrix( POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stI, MTH3D_tdstVector *_p_stJ, MTH3D_tdstVector *_p_stK ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); POS_M_MustBeModifiable(_hMatrix); #endif if ( MTH_M_bEqualWithEpsilon(_p_stI->xX,MTH_C_ONE,MTH_M_xFloatToReal(0.01)) && MTH_M_bEqualWithEpsilon(_p_stJ->xY,MTH_C_ONE,MTH_M_xFloatToReal(0.01)) && MTH_M_bEqualWithEpsilon(_p_stK->xZ,MTH_C_ONE,MTH_M_xFloatToReal(0.01)) ) { /*the matrix looses its scale attribute*/ MTH3D_M_vCopyMatrix(&(_hMatrix->stTransformMatrix),&(_hMatrix->stRotationMatrix)); /*it is a simple rotation matrix*/ _hMatrix->ulType = POS_C_ulRotationMatrixFlag; return; } switch ( _hMatrix->ulType ) { case POS_C_ulIdentityMatrixFlag: case POS_C_ulTranslationMatrixFlag: MTH3D_M_vSetVectorsInMatrix( &(_hMatrix->stTransformMatrix), _p_stI, _p_stJ, _p_stK ); _hMatrix->ulType = POS_C_ulCompleteMatrixFlag; break; default: /*zoomed matrix*/ { MTH3D_tdstMatrix stScaleMatrix; MTH3D_M_vSetVectorsInMatrix( &stScaleMatrix, _p_stI, _p_stJ, _p_stK ); MTH3D_M_vMulMatrixMatrixWithoutBuffer( &(_hMatrix->stTransformMatrix), &(_hMatrix->stRotationMatrix), &stScaleMatrix); _hMatrix->ulType = POS_C_ulCompleteMatrixFlag; } break; } } /*---------------------------------------------------------------------------- // Description : POS_fn_xGetXScale // Get the X component of the scale matrix - derived from the transform matrix ----------------------------------------------------------------------------// ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the complete matrix // Output : returns the value of the X scaling component ----------------------------------------------------------------------------// // Creation date : Aug 98 Author: Steve McCalla ----------------------------------------------------------------------------*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */ MTH_tdxReal POS_fn_xGetXScale( POS_tdxHandleToPosition _hMatrix ) { MTH_tdxReal xScaleX = 1.0f; if ( _hMatrix->ulType > POS_C_ulRotationMatrixFlag ) { xScaleX = MTH_M_xSqrt((_hMatrix->stTransformMatrix.stCol_0.xX * _hMatrix->stTransformMatrix.stCol_0.xX) + (_hMatrix->stTransformMatrix.stCol_1.xX * _hMatrix->stTransformMatrix.stCol_1.xX) + (_hMatrix->stTransformMatrix.stCol_2.xX * _hMatrix->stTransformMatrix.stCol_2.xX)); } return xScaleX; } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */ /*---------------------------------------------------------------------------- // Description : POS_fn_xGetYScale // Get the Y component of the scale matrix - derived from the transform matrix ----------------------------------------------------------------------------// ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the complete matrix // Output : returns the value of the X scaling component ----------------------------------------------------------------------------// // Creation date : Aug 98 Author: Steve McCalla ----------------------------------------------------------------------------*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */ MTH_tdxReal POS_fn_xGetYScale( POS_tdxHandleToPosition _hMatrix ) { MTH_tdxReal xScaleY = 1.0f; if ( _hMatrix->ulType > POS_C_ulRotationMatrixFlag ) { xScaleY = MTH_M_xSqrt((_hMatrix->stTransformMatrix.stCol_0.xY * _hMatrix->stTransformMatrix.stCol_0.xY) + (_hMatrix->stTransformMatrix.stCol_1.xY * _hMatrix->stTransformMatrix.stCol_1.xY) + (_hMatrix->stTransformMatrix.stCol_2.xY * _hMatrix->stTransformMatrix.stCol_2.xY)); } return xScaleY; } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */ /*---------------------------------------------------------------------------- // Description : POS_fn_xGetZScale // Get the Z component of the scale matrix - derived from the transform matrix ----------------------------------------------------------------------------// ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the complete matrix // Output : returns the value of the Z scaling component ----------------------------------------------------------------------------// // Creation date : Aug 98 Author: Steve McCalla ----------------------------------------------------------------------------*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */ MTH_tdxReal POS_fn_xGetZScale( POS_tdxHandleToPosition _hMatrix ) { MTH_tdxReal xScaleZ = 1.0f; if ( _hMatrix->ulType > POS_C_ulRotationMatrixFlag ) { xScaleZ = MTH_M_xSqrt((_hMatrix->stTransformMatrix.stCol_0.xZ * _hMatrix->stTransformMatrix.stCol_0.xZ) + (_hMatrix->stTransformMatrix.stCol_1.xZ * _hMatrix->stTransformMatrix.stCol_1.xZ) + (_hMatrix->stTransformMatrix.stCol_2.xZ * _hMatrix->stTransformMatrix.stCol_2.xZ)); } return xScaleZ; } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */ /************* GETTING THE 3x3 SCALING COMPONENT OF A MATRIX *************/ /* Modif : Check if scal is used and return ID*/ void POS_fn_vGetScaleMatrix( POS_tdxHandleToPosition _hMatrix , MTH3D_tdstVector *_p_stI , MTH3D_tdstVector *_p_stJ , MTH3D_tdstVector *_p_stK ) { /* MTH_tdxReal xScaleX;*/ /* MTH_tdxReal xScaleY;*/ /* MTH_tdxReal xScaleZ;*/ #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif MTH3D_M_vSetBaseIVector(_p_stI); MTH3D_M_vSetBaseJVector(_p_stJ); MTH3D_M_vSetBaseKVector(_p_stK); if ( _hMatrix->ulType > POS_C_ulRotationMatrixFlag ) { /* */ /*#define NEW_CODE #ifdef NEW_CODE xScaleX = MTH_M_xSqrt((_hMatrix->stTransformMatrix.stCol_0.xX * _hMatrix->stTransformMatrix.stCol_0.xX) + (_hMatrix->stTransformMatrix.stCol_1.xX * _hMatrix->stTransformMatrix.stCol_1.xX) + (_hMatrix->stTransformMatrix.stCol_2.xX * _hMatrix->stTransformMatrix.stCol_2.xX)); xScaleY = MTH_M_xSqrt((_hMatrix->stTransformMatrix.stCol_0.xY * _hMatrix->stTransformMatrix.stCol_0.xY) + (_hMatrix->stTransformMatrix.stCol_1.xY * _hMatrix->stTransformMatrix.stCol_1.xY) + (_hMatrix->stTransformMatrix.stCol_2.xY * _hMatrix->stTransformMatrix.stCol_2.xY)); xScaleZ = MTH_M_xSqrt((_hMatrix->stTransformMatrix.stCol_0.xZ * _hMatrix->stTransformMatrix.stCol_0.xZ) + (_hMatrix->stTransformMatrix.stCol_1.xZ * _hMatrix->stTransformMatrix.stCol_1.xZ) + (_hMatrix->stTransformMatrix.stCol_2.xZ * _hMatrix->stTransformMatrix.stCol_2.xZ)); // non-diagonal members were already set to zero above _p_stI->xX = xScaleX; _p_stJ->xY = xScaleY; _p_stK->xZ = xScaleZ; #else */ MTH3D_tdstMatrix stScaleMatrix; MTH3D_M_vMulTranspMatrixMatrixWithoutBuffer(&stScaleMatrix, &(_hMatrix->stRotationMatrix), &(_hMatrix->stTransformMatrix)); MTH3D_M_vGetVectorsInMatrix(_p_stI,_p_stJ,_p_stK,&stScaleMatrix); /*#endif*/ } } /***************************************************************************/ void POS_fn_vSetZoomMatrix( POS_tdxHandleToPosition _hMatrix , MTH_tdxReal _xZoom) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); POS_M_MustBeModifiable(_hMatrix); #endif MTH3D_M_vMulScalarMatrix(&(_hMatrix->stTransformMatrix), _xZoom, &(_hMatrix->stRotationMatrix)); _hMatrix->ulType = POS_C_ulCompleteMatrixFlag; } /************* GETTING THE 3x3 TRANSFORM COMPONENT OF A MATRIX *************/ /*macros are faster, but kind of hard/impossible to debug*/ #ifndef USE_POS_MACROS /* // POS_fn_vGetTransformMatrixCol0 - returns the first column (column 0) of the transform matrix ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the complete matrix // _p_Vec : pointer to the Col 0 vector ----------------------------------------------------------------------------// // Creation date : Aug 98 Author: Steve McCalla ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ void POS_fn_vGetTransformMatrixCol0 ( POS_tdxHandleToPosition _hMatrix , MTH3D_tdstVector *_p_Vec) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif MTH3D_M_vGetColumn0InMatrix(_p_Vec, &(_hMatrix->stTransformMatrix)); } /* // POS_fn_vGetTransformMatrixCol1 - returns the second column (column 1) of the transform matrix ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the complete matrix // _p_Vec : pointer to the Col 1 vector // Output : ----------------------------------------------------------------------------// // Creation date : Aug 98 Author: Steve McCalla ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ void POS_fn_vGetTransformMatrixCol1 ( POS_tdxHandleToPosition _hMatrix , MTH3D_tdstVector *_p_Vec) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif MTH3D_M_vGetColumn1InMatrix(_p_Vec, &(_hMatrix->stTransformMatrix)); } /* // POS_fn_vGetTransformMatrixCol2 - returns the third column (column 2) of the transform matrix ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the complete matrix // _p_Vec : pointer to the Col 2 vector // Output : ----------------------------------------------------------------------------// // Creation date : Aug 98 Author: Steve McCalla ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ void POS_fn_vGetTransformMatrixCol2 ( POS_tdxHandleToPosition _hMatrix , MTH3D_tdstVector *_p_Vec) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif MTH3D_M_vGetColumn2InMatrix(_p_Vec, &(_hMatrix->stTransformMatrix)); } #endif /* USE_POS_MACROS*/ void POS_fn_vGetTransformMatrix ( POS_tdxHandleToPosition _hMatrix , MTH3D_tdstVector *_p_stI , MTH3D_tdstVector *_p_stJ , MTH3D_tdstVector *_p_stK ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif MTH3D_M_vGetVectorsInMatrix(_p_stI,_p_stJ,_p_stK,&(_hMatrix->stTransformMatrix)); } /*---------------------------------------------------------------------------- // Description : POS_fn_vSetTransformMatrix // Used to set the transform part (calculated matrix) of the complete matrix ----------------------------------------------------------------------------// // Method : nothing to say ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the complete matrix // _p_stI, _p_stJ, _p_stK : pointer to the transformation matrix // Output : ----------------------------------------------------------------------------// // Creation date : Mar 97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ void POS_fn_vSetTransformMatrix ( POS_tdxHandleToPosition _hMatrix , MTH3D_tdstVector *_p_stI , MTH3D_tdstVector *_p_stJ , MTH3D_tdstVector *_p_stK ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); POS_M_MustBeModifiable(_hMatrix); #endif /* assert that this function never does anything useful*/ MTH3D_M_vSetVectorsInMatrix(&(_hMatrix->stTransformMatrix),_p_stI,_p_stJ,_p_stK); _hMatrix->ulType = POS_C_ulCompleteMatrixFlag; } /**************** SETTING THE TRANSLATION VERTEX OF A MATRIX *************/ void POS_fn_vSetTranslationVector( POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stTrs ) { /* unsigned short uwType;*/ #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); POS_M_MustBeModifiable(_hMatrix); #endif MTH3D_M_vCopyVector( &(_hMatrix->stTranslationVector), _p_stTrs ); if ( _hMatrix->ulType == POS_C_ulIdentityMatrixFlag ) _hMatrix->ulType = POS_C_ulTranslationMatrixFlag; } /**************** GETTING THE TRANSLATION VERTEX OF A MATRIX *************/ void POS_fn_vGetTranslationVector( POS_tdxHandleToPosition _hMatrix, MTH3D_tdstVector *_p_stTrs ) { #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif MTH3D_M_vCopyVector( _p_stTrs, &(_hMatrix->stTranslationVector) ); } /**************** GETTING THE SCALE STATE ********************************/ /*---------------------------------------------------------------------------- // Description : POS_fn_vGetMaxScale // Used to get the maximum scale factor of the 3 axes ----------------------------------------------------------------------------// // Method : nothing to say ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the complete matrix // Output : the maximum scale factor ----------------------------------------------------------------------------// // Creation date : May 97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ MTH_tdxReal POS_fn_xGetMaxScale(POS_tdxHandleToPosition _hMatrix ) { /* MTH3D_tdstMatrix stScaleMatrix;*/ MTH_tdxReal xRet; MTH_tdxReal xL1,xL2,xL3; #define C_2DIV27 ((MTH_tdxReal) 0.07407407407407f) #ifdef _DEBUG POS_M_MustBeValid(_hMatrix); #endif if ( _hMatrix->ulType <= POS_C_ulRotationMatrixFlag ) return MTH_C_ONE; /* STM - from testing on several maps, it looks like scale matrix is always _nearly_ diagonal*/ #define DIAGONAL_SCALE_MATRIX #ifdef DIAGONAL_SCALE_MATRIX /* We suppose we have a diagonal matrix */ xL1 = MTH3D_M_xSqrVector(&_hMatrix->stTransformMatrix.stCol_0); xL2 = MTH3D_M_xSqrVector(&_hMatrix->stTransformMatrix.stCol_1); xL3 = MTH3D_M_xSqrVector(&_hMatrix->stTransformMatrix.stCol_2); xRet = MTH_M_xMax(xL1, xL2); xRet = MTH_M_xMax(xRet, xL3); return MTH_M_xSqrt(xRet); #else /* get the scale matrix*/ MTH3D_M_vMulTranspMatrixMatrixWithoutBuffer(&stScaleMatrix, &(_hMatrix->stRotationMatrix), &(_hMatrix->stTransformMatrix)); /* We test if we have a diagonal matrix */ if ( (!POS_M_bIsDeltaNull(stScaleMatrix.stCol_0.xY)) || (!POS_M_bIsDeltaNull(stScaleMatrix.stCol_0.xZ)) || (!POS_M_bIsDeltaNull(stScaleMatrix.stCol_1.xX)) || (!POS_M_bIsDeltaNull(stScaleMatrix.stCol_1.xZ)) || (!POS_M_bIsDeltaNull(stScaleMatrix.stCol_2.xX)) || (!POS_M_bIsDeltaNull(stScaleMatrix.stCol_2.xY)) ) { /*the matrix is not diagonal*/ MTH_tdxReal xA,xB,xC,xD,xE,xF,xM,xP,xQ,xR,xTeta,xCosTeta,xSinTeta,xCT,xP2; /* Here, we have a complex scale matrix */ /* We compute the eigen values of the matrix */ xC = MTH_M_xMul( stScaleMatrix.stCol_0.xX , stScaleMatrix.stCol_1.xY); xD = MTH_M_xMul( stScaleMatrix.stCol_2.xY , stScaleMatrix.stCol_1.xZ); xE = MTH_M_xMul( stScaleMatrix.stCol_1.xX , stScaleMatrix.stCol_0.xY); xF = MTH_M_xMul( stScaleMatrix.stCol_2.xX , stScaleMatrix.stCol_0.xZ); xP = MTH_M_xNeg( MTH_M_xAdd3( stScaleMatrix.stCol_0.xX , stScaleMatrix.stCol_1.xY , stScaleMatrix.stCol_2.xZ ) ); xP2= MTH_M_xSqr( xP ); /*xQ=xC+(stScaleMatrix.stCol_0.xX+stScaleMatrix.stCol_1.xY)*stScaleMatrix.stCol_2.xZ-xD-xE-xF;*/ xQ = MTH_M_xMul( MTH_M_xAdd( stScaleMatrix.stCol_0.xX , stScaleMatrix.stCol_1.xY ) , stScaleMatrix.stCol_2.xZ ); xQ = MTH_M_xAdd( xQ , xC ); xQ = MTH_M_xSub( xQ , MTH_M_xAdd3( xD , xE , xF ) ); /* xR=(xE-xC)*stScaleMatrix.stCol_2.xZ+xD*stScaleMatrix.stCol_0.xX-*/ /* 2*(stScaleMatrix.stCol_1.xX*stScaleMatrix.stCol_2.xY*stScaleMatrix.stCol_0.xZ)+*/ /* xF*stScaleMatrix.stCol_1.xY;*/ xR = MTH_M_xMul( MTH_M_xSub( xE , xC ) , stScaleMatrix.stCol_2.xZ ); xR = MTH_M_xAdd( xR , MTH_M_xMul( xD , stScaleMatrix.stCol_0.xX ) ); xR = MTH_M_xSub( xR , MTH_M_xMul( MTH_C_2 , MTH_M_xMul3( stScaleMatrix.stCol_1.xX , stScaleMatrix.stCol_2.xY , stScaleMatrix.stCol_0.xZ ) ) ); xR = MTH_M_xAdd( xR , MTH_M_xMul( xF , stScaleMatrix.stCol_1.xY ) ); /*xA=xQ-xP2*MTH_C_Inv3;*/ xA = MTH_M_xSub( xQ , MTH_M_xMul( xP2 , MTH_C_Inv3 ) ); /*xB=xP*xP2*C_2DIV27-(xP*xQ)*MTH_C_Inv3+xR;*/ xB = MTH_M_xNeg( MTH_M_xMul3( xP , xQ , MTH_C_Inv3 ) ); xB = MTH_M_xAdd3( MTH_M_xMul3( xP , xP2 , C_2DIV27 ) , xB , xR ); /*xM=2*MTH_M_xSqrt(-xA*MTH_C_Inv3);*/ xM = MTH_M_xNeg( MTH_M_xMul( xA , MTH_C_Inv3 ) ); xM = MTH_M_xMul( MTH_C_2 , MTH_M_xSqrt( xM ) ); /* xCT=(3*xB)/(xA*xM); if(xCT>1.0) xCT=1.0; if(xCT<(-1.0)) xCT=-1.0; */ xCT = MTH_M_xDiv( MTH_M_xMul( MTH_C_3 , xB ) , MTH_M_xMul( xA , xM ) ); if ( MTH_M_bGreater( xCT , MTH_C_ONE ) ) xCT = MTH_C_ONE; if ( MTH_M_bLess( xCT , MTH_C_MinusONE ) ) xCT = MTH_C_MinusONE; /*xTeta=MTH_C_Inv3*MTH_M_xACos(xCT);*/ xTeta = MTH_M_xMul( MTH_C_Inv3 , MTH_M_xACos( xCT ) ); xCosTeta = MTH_M_xCos( xTeta ); xSinTeta = MTH_M_xSin( xTeta ); /*xL1=xM*xCosTeta-(xP*MTH_C_Inv3);*/ xL1 = MTH_M_xMulSubMul( xM , xCosTeta , xP , MTH_C_Inv3 ); /*xL2=xM*((xCosTeta+MTH_C_Sqrt3*xSinTeta)*MTH_C_Inv2)-(xP*MTH_C_Inv3);*/ xL2 = MTH_M_xMul( MTH_M_xAdd( xCosTeta , MTH_M_xMul( MTH_C_Sqrt3 , xSinTeta ) ) , MTH_C_Inv2 ); xL2 = MTH_M_xMulSubMul( xM , xL2 , xP , MTH_C_Inv3 ); /*xL3=xM*((xCosTeta-MTH_C_Sqrt3*xSinTeta)*MTH_C_Inv2)-(xP*MTH_C_Inv3);*/ xL3 = xL2; /* ?????????*/ xRet = MTH_M_xAbs(xL1); xRet = MTH_M_xMax(xRet, MTH_M_xAbs(xL2)); xRet = MTH_M_xMax(xRet, MTH_M_xAbs(xL3)); } else { /* We suppose we have a diagonal matrix */ xRet = MTH_M_xAbs(stScaleMatrix.stCol_0.xX); xRet = MTH_M_xMax(xRet, MTH_M_xAbs(stScaleMatrix.stCol_1.xY)); xRet = MTH_M_xMax(xRet, MTH_M_xAbs(stScaleMatrix.stCol_2.xZ)); } return xRet; #endif } /*---------------------------------------------------------------------------- // Description : POS_fn_vPrintUsedStaticMemory // Display the information about the memory used ----------------------------------------------------------------------------// // Methods : ----------------------------------------------------------------------------// // Input : // Output : ----------------------------------------------------------------------------// // Creation date : Aug 97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ #ifndef RETAIL void POS_fn_vPrintUsedStaticMemory() { Mmg_M_PrintUsedStaticMemoryInModule(Pos); } #endif /* RETAIL */ #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /*---------------------------------------------------------------------------- // Description : POS_fn_vQuatToMat // Takes 4 reals transform them into a rotation matrix ----------------------------------------------------------------------------// // Methods : See Advanced animation & rendering techniques p363 ----------------------------------------------------------------------------// // Input : _xX : Axis X // _xY : Axis Y // _xZ : Axis Z // _xW : cos of the angle // Output : _p_stMatrix : pointer to the MTH matrix ----------------------------------------------------------------------------// // Creation date : Jul 97 Author: Alain Robin ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ void POS_fn_vQuatToMat(MTH3D_tdstMatrix* _p_stMatrix, MTH_tdxReal _xX, MTH_tdxReal _xY, MTH_tdxReal _xZ, MTH_tdxReal _xW) { /* it's now conform to MTH specs */ MTH_tdxReal xXs,xYs,xZs,xWx,xWy,xWz,xXx,xXy,xXz,xYy,xYz,xZz; /* it seems that all quaternions have norm 1 !!!!! */ xXs = MTH_M_xAdd(_xX,_xX); xYs = MTH_M_xAdd(_xY,_xY); xZs = MTH_M_xAdd(_xZ,_xZ); xWx = MTH_M_xMul(_xW,xXs); xWy = MTH_M_xMul(_xW,xYs); xWz = MTH_M_xMul(_xW,xZs); xXx = MTH_M_xMul(_xX,xXs); xXy = MTH_M_xMul(_xX,xYs); xXz = MTH_M_xMul(_xX,xZs); xYy = MTH_M_xMul(_xY,xYs); xYz = MTH_M_xMul(_xY,xZs); xZz = MTH_M_xMul(_xZ,xZs); (_p_stMatrix->stCol_0).xX =MTH_M_xSub(MTH_C_ONE,MTH_M_xAdd(xYy,xZz)); (_p_stMatrix->stCol_1).xX =MTH_M_xAdd(xXy,xWz); (_p_stMatrix->stCol_2).xX =MTH_M_xSub(xXz,xWy); (_p_stMatrix->stCol_0).xY =MTH_M_xSub(xXy,xWz); (_p_stMatrix->stCol_1).xY =MTH_M_xSub(MTH_C_ONE,MTH_M_xAdd(xXx,xZz)); (_p_stMatrix->stCol_2).xY =MTH_M_xAdd(xYz,xWx); (_p_stMatrix->stCol_0).xZ =MTH_M_xAdd(xXz,xWy); (_p_stMatrix->stCol_1).xZ =MTH_M_xSub(xYz,xWx); (_p_stMatrix->stCol_2).xZ =MTH_M_xSub(MTH_C_ONE,MTH_M_xAdd(xXx,xYy)); } /*---------------------------------------------------------------------------- // Description : POS_fn_vUpdateMatrixType // Recompute the real type of the matrix ----------------------------------------------------------------------------// // Input : _hMatrix : Handle to the matrix // Output : ----------------------------------------------------------------------------// // Creation date : Jul 98 Author: Marc Trabucato ----------------------------------------------------------------------------// // Modifications : // Modification date : Modification author : ----------------------------------------------------------------------------*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ void POS_fn_vUpdateMatrixType(POS_tdxHandleToPosition _hMatrix) { /* update type*/ if (_hMatrix->ulType != POS_C_ulIdentityMatrixFlag ) { if (!MTH3D_M_bMatchMatrix(&(_hMatrix->stRotationMatrix),&(_hMatrix->stTransformMatrix),POS_M_xEpsilonEqual)) { /* transform matrix differs from rotation matrix*/ _hMatrix->ulType = POS_C_ulCompleteMatrixFlag; } else if (!POS_M_bIsMatrixIdentity(&(_hMatrix->stRotationMatrix))) { /* rotation matrix is not identity*/ _hMatrix->ulType = POS_C_ulRotationMatrixFlag; } else if (!POS_M_bIsVectorNull(&(_hMatrix)->stTranslationVector)) { /* translation vector is not null*/ _hMatrix->ulType = POS_C_ulTranslationMatrixFlag; } else { _hMatrix->ulType = POS_C_ulIdentityMatrixFlag; } } /* clean values*/ switch(_hMatrix->ulType) { case POS_C_ulIdentityMatrixFlag: MTH3D_M_vNullVector(&(_hMatrix)->stTranslationVector); /* no break here !!!*/ case POS_C_ulTranslationMatrixFlag: MTH3D_M_vSetIdentityMatrix(&(_hMatrix->stRotationMatrix)); /* no break here !!!*/ case POS_C_ulRotationMatrixFlag: MTH3D_M_vCopyMatrix(&(_hMatrix->stTransformMatrix),&(_hMatrix->stRotationMatrix)); return; default: break; } } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /*---------------------------------------------------------------------------- ----------------------------------------------------------------------------*/ #ifdef __cplusplus } /*extern "C"*/ #endif