reman3/Rayman_X/cpa/tempgrp/POS/Position.c

1663 lines
59 KiB
C

/* (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