|  | /****************************************************************************** | 
|  |  | 
|  | @File         PVRTMatrixX.cpp | 
|  |  | 
|  | @Title        PVRTMatrixX | 
|  |  | 
|  | @Version | 
|  |  | 
|  | @Copyright    Copyright (c) Imagination Technologies Limited. | 
|  |  | 
|  | @Platform     ANSI compatible | 
|  |  | 
|  | @Description  Set of mathematical functions involving matrices, vectors and | 
|  | quaternions. | 
|  | The general matrix format used is directly compatible with, for example, | 
|  | both DirectX and OpenGL. For the reasons why, read this: | 
|  | http://research.microsoft.com/~hollasch/cgindex/math/matrix/column-vec.html | 
|  |  | 
|  | ******************************************************************************/ | 
|  |  | 
|  | #include "PVRTContext.h" | 
|  | #include <math.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include "PVRTFixedPoint.h" | 
|  | #include "PVRTMatrix.h" | 
|  |  | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | ** Constants | 
|  | ****************************************************************************/ | 
|  | static const PVRTMATRIXx	c_mIdentity = { | 
|  | { | 
|  | PVRTF2X(1.0f), PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(0.0f), | 
|  | PVRTF2X(0.0f), PVRTF2X(1.0f), PVRTF2X(0.0f), PVRTF2X(0.0f), | 
|  | PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(1.0f), PVRTF2X(0.0f), | 
|  | PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(1.0f) | 
|  | } | 
|  | }; | 
|  |  | 
|  |  | 
|  | /**************************************************************************** | 
|  | ** Functions | 
|  | ****************************************************************************/ | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixIdentityX | 
|  | @Output			mOut	Set to identity | 
|  | @Description		Reset matrix to identity matrix. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixIdentityX(PVRTMATRIXx &mOut) | 
|  | { | 
|  | mOut.f[ 0]=PVRTF2X(1.0f);	mOut.f[ 4]=PVRTF2X(0.0f);	mOut.f[ 8]=PVRTF2X(0.0f);	mOut.f[12]=PVRTF2X(0.0f); | 
|  | mOut.f[ 1]=PVRTF2X(0.0f);	mOut.f[ 5]=PVRTF2X(1.0f);	mOut.f[ 9]=PVRTF2X(0.0f);	mOut.f[13]=PVRTF2X(0.0f); | 
|  | mOut.f[ 2]=PVRTF2X(0.0f);	mOut.f[ 6]=PVRTF2X(0.0f);	mOut.f[10]=PVRTF2X(1.0f);	mOut.f[14]=PVRTF2X(0.0f); | 
|  | mOut.f[ 3]=PVRTF2X(0.0f);	mOut.f[ 7]=PVRTF2X(0.0f);	mOut.f[11]=PVRTF2X(0.0f);	mOut.f[15]=PVRTF2X(1.0f); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixMultiplyX | 
|  | @Output			mOut	Result of mA x mB | 
|  | @Input				mA		First operand | 
|  | @Input				mB		Second operand | 
|  | @Description		Multiply mA by mB and assign the result to mOut | 
|  | (mOut = p1 * p2). A copy of the result matrix is done in | 
|  | the function because mOut can be a parameter mA or mB. | 
|  | The fixed-point shift could be performed after adding | 
|  | all four intermediate results together however this might | 
|  | cause some overflow issues. | 
|  | ****************************************************************************/ | 
|  | void PVRTMatrixMultiplyX( | 
|  | PVRTMATRIXx			&mOut, | 
|  | const PVRTMATRIXx	&mA, | 
|  | const PVRTMATRIXx	&mB) | 
|  | { | 
|  | PVRTMATRIXx mRet; | 
|  |  | 
|  | /* Perform calculation on a dummy matrix (mRet) */ | 
|  | mRet.f[ 0] = PVRTXMUL(mA.f[ 0], mB.f[ 0]) + PVRTXMUL(mA.f[ 1], mB.f[ 4]) + PVRTXMUL(mA.f[ 2], mB.f[ 8]) + PVRTXMUL(mA.f[ 3], mB.f[12]); | 
|  | mRet.f[ 1] = PVRTXMUL(mA.f[ 0], mB.f[ 1]) + PVRTXMUL(mA.f[ 1], mB.f[ 5]) + PVRTXMUL(mA.f[ 2], mB.f[ 9]) + PVRTXMUL(mA.f[ 3], mB.f[13]); | 
|  | mRet.f[ 2] = PVRTXMUL(mA.f[ 0], mB.f[ 2]) + PVRTXMUL(mA.f[ 1], mB.f[ 6]) + PVRTXMUL(mA.f[ 2], mB.f[10]) + PVRTXMUL(mA.f[ 3], mB.f[14]); | 
|  | mRet.f[ 3] = PVRTXMUL(mA.f[ 0], mB.f[ 3]) + PVRTXMUL(mA.f[ 1], mB.f[ 7]) + PVRTXMUL(mA.f[ 2], mB.f[11]) + PVRTXMUL(mA.f[ 3], mB.f[15]); | 
|  |  | 
|  | mRet.f[ 4] = PVRTXMUL(mA.f[ 4], mB.f[ 0]) + PVRTXMUL(mA.f[ 5], mB.f[ 4]) + PVRTXMUL(mA.f[ 6], mB.f[ 8]) + PVRTXMUL(mA.f[ 7], mB.f[12]); | 
|  | mRet.f[ 5] = PVRTXMUL(mA.f[ 4], mB.f[ 1]) + PVRTXMUL(mA.f[ 5], mB.f[ 5]) + PVRTXMUL(mA.f[ 6], mB.f[ 9]) + PVRTXMUL(mA.f[ 7], mB.f[13]); | 
|  | mRet.f[ 6] = PVRTXMUL(mA.f[ 4], mB.f[ 2]) + PVRTXMUL(mA.f[ 5], mB.f[ 6]) + PVRTXMUL(mA.f[ 6], mB.f[10]) + PVRTXMUL(mA.f[ 7], mB.f[14]); | 
|  | mRet.f[ 7] = PVRTXMUL(mA.f[ 4], mB.f[ 3]) + PVRTXMUL(mA.f[ 5], mB.f[ 7]) + PVRTXMUL(mA.f[ 6], mB.f[11]) + PVRTXMUL(mA.f[ 7], mB.f[15]); | 
|  |  | 
|  | mRet.f[ 8] = PVRTXMUL(mA.f[ 8], mB.f[ 0]) + PVRTXMUL(mA.f[ 9], mB.f[ 4]) + PVRTXMUL(mA.f[10], mB.f[ 8]) + PVRTXMUL(mA.f[11], mB.f[12]); | 
|  | mRet.f[ 9] = PVRTXMUL(mA.f[ 8], mB.f[ 1]) + PVRTXMUL(mA.f[ 9], mB.f[ 5]) + PVRTXMUL(mA.f[10], mB.f[ 9]) + PVRTXMUL(mA.f[11], mB.f[13]); | 
|  | mRet.f[10] = PVRTXMUL(mA.f[ 8], mB.f[ 2]) + PVRTXMUL(mA.f[ 9], mB.f[ 6]) + PVRTXMUL(mA.f[10], mB.f[10]) + PVRTXMUL(mA.f[11], mB.f[14]); | 
|  | mRet.f[11] = PVRTXMUL(mA.f[ 8], mB.f[ 3]) + PVRTXMUL(mA.f[ 9], mB.f[ 7]) + PVRTXMUL(mA.f[10], mB.f[11]) + PVRTXMUL(mA.f[11], mB.f[15]); | 
|  |  | 
|  | mRet.f[12] = PVRTXMUL(mA.f[12], mB.f[ 0]) + PVRTXMUL(mA.f[13], mB.f[ 4]) + PVRTXMUL(mA.f[14], mB.f[ 8]) + PVRTXMUL(mA.f[15], mB.f[12]); | 
|  | mRet.f[13] = PVRTXMUL(mA.f[12], mB.f[ 1]) + PVRTXMUL(mA.f[13], mB.f[ 5]) + PVRTXMUL(mA.f[14], mB.f[ 9]) + PVRTXMUL(mA.f[15], mB.f[13]); | 
|  | mRet.f[14] = PVRTXMUL(mA.f[12], mB.f[ 2]) + PVRTXMUL(mA.f[13], mB.f[ 6]) + PVRTXMUL(mA.f[14], mB.f[10]) + PVRTXMUL(mA.f[15], mB.f[14]); | 
|  | mRet.f[15] = PVRTXMUL(mA.f[12], mB.f[ 3]) + PVRTXMUL(mA.f[13], mB.f[ 7]) + PVRTXMUL(mA.f[14], mB.f[11]) + PVRTXMUL(mA.f[15], mB.f[15]); | 
|  |  | 
|  | /* Copy result in pResultMatrix */ | 
|  | mOut = mRet; | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function Name		PVRTMatrixTranslationX | 
|  | @Output			mOut	Translation matrix | 
|  | @Input				fX		X component of the translation | 
|  | @Input				fY		Y component of the translation | 
|  | @Input				fZ		Z component of the translation | 
|  | @Description		Build a transaltion matrix mOut using fX, fY and fZ. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixTranslationX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	fX, | 
|  | const int	fY, | 
|  | const int	fZ) | 
|  | { | 
|  | mOut.f[ 0]=PVRTF2X(1.0f);	mOut.f[ 4]=PVRTF2X(0.0f);	mOut.f[ 8]=PVRTF2X(0.0f);	mOut.f[12]=fX; | 
|  | mOut.f[ 1]=PVRTF2X(0.0f);	mOut.f[ 5]=PVRTF2X(1.0f);	mOut.f[ 9]=PVRTF2X(0.0f);	mOut.f[13]=fY; | 
|  | mOut.f[ 2]=PVRTF2X(0.0f);	mOut.f[ 6]=PVRTF2X(0.0f);	mOut.f[10]=PVRTF2X(1.0f);	mOut.f[14]=fZ; | 
|  | mOut.f[ 3]=PVRTF2X(0.0f);	mOut.f[ 7]=PVRTF2X(0.0f);	mOut.f[11]=PVRTF2X(0.0f);	mOut.f[15]=PVRTF2X(1.0f); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function Name		PVRTMatrixScalingX | 
|  | @Output			mOut	Scale matrix | 
|  | @Input				fX		X component of the scaling | 
|  | @Input				fY		Y component of the scaling | 
|  | @Input				fZ		Z component of the scaling | 
|  | @Description		Build a scale matrix mOut using fX, fY and fZ. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixScalingX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	fX, | 
|  | const int	fY, | 
|  | const int	fZ) | 
|  | { | 
|  | mOut.f[ 0]=fX;				mOut.f[ 4]=PVRTF2X(0.0f);	mOut.f[ 8]=PVRTF2X(0.0f);	mOut.f[12]=PVRTF2X(0.0f); | 
|  | mOut.f[ 1]=PVRTF2X(0.0f);	mOut.f[ 5]=fY;				mOut.f[ 9]=PVRTF2X(0.0f);	mOut.f[13]=PVRTF2X(0.0f); | 
|  | mOut.f[ 2]=PVRTF2X(0.0f);	mOut.f[ 6]=PVRTF2X(0.0f);	mOut.f[10]=fZ;				mOut.f[14]=PVRTF2X(0.0f); | 
|  | mOut.f[ 3]=PVRTF2X(0.0f);	mOut.f[ 7]=PVRTF2X(0.0f);	mOut.f[11]=PVRTF2X(0.0f);	mOut.f[15]=PVRTF2X(1.0f); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function Name		PVRTMatrixRotationXX | 
|  | @Output			mOut	Rotation matrix | 
|  | @Input				fAngle	Angle of the rotation | 
|  | @Description		Create an X rotation matrix mOut. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixRotationXX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	fAngle) | 
|  | { | 
|  | int		fCosine, fSine; | 
|  |  | 
|  | /* Precompute cos and sin */ | 
|  | #if defined(BUILD_DX11) | 
|  | fCosine	= PVRTXCOS(-fAngle); | 
|  | fSine	= PVRTXSIN(-fAngle); | 
|  | #else | 
|  | fCosine	= PVRTXCOS(fAngle); | 
|  | fSine	= PVRTXSIN(fAngle); | 
|  | #endif | 
|  |  | 
|  | /* Create the trigonometric matrix corresponding to X Rotation */ | 
|  | mOut.f[ 0]=PVRTF2X(1.0f);	mOut.f[ 4]=PVRTF2X(0.0f);		mOut.f[ 8]=PVRTF2X(0.0f);		mOut.f[12]=PVRTF2X(0.0f); | 
|  | mOut.f[ 1]=PVRTF2X(0.0f);	mOut.f[ 5]=fCosine;				mOut.f[ 9]=fSine;				mOut.f[13]=PVRTF2X(0.0f); | 
|  | mOut.f[ 2]=PVRTF2X(0.0f);	mOut.f[ 6]=-fSine;				mOut.f[10]=fCosine;				mOut.f[14]=PVRTF2X(0.0f); | 
|  | mOut.f[ 3]=PVRTF2X(0.0f);	mOut.f[ 7]=PVRTF2X(0.0f);		mOut.f[11]=PVRTF2X(0.0f);		mOut.f[15]=PVRTF2X(1.0f); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function Name		PVRTMatrixRotationYX | 
|  | @Output			mOut	Rotation matrix | 
|  | @Input				fAngle	Angle of the rotation | 
|  | @Description		Create an Y rotation matrix mOut. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixRotationYX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	fAngle) | 
|  | { | 
|  | int		fCosine, fSine; | 
|  |  | 
|  | /* Precompute cos and sin */ | 
|  | #if defined(BUILD_DX11) | 
|  | fCosine	= PVRTXCOS(-fAngle); | 
|  | fSine	= PVRTXSIN(-fAngle); | 
|  | #else | 
|  | fCosine	= PVRTXCOS(fAngle); | 
|  | fSine	= PVRTXSIN(fAngle); | 
|  | #endif | 
|  |  | 
|  | /* Create the trigonometric matrix corresponding to Y Rotation */ | 
|  | mOut.f[ 0]=fCosine;				mOut.f[ 4]=PVRTF2X(0.0f);	mOut.f[ 8]=-fSine;				mOut.f[12]=PVRTF2X(0.0f); | 
|  | mOut.f[ 1]=PVRTF2X(0.0f);		mOut.f[ 5]=PVRTF2X(1.0f);	mOut.f[ 9]=PVRTF2X(0.0f);		mOut.f[13]=PVRTF2X(0.0f); | 
|  | mOut.f[ 2]=fSine;				mOut.f[ 6]=PVRTF2X(0.0f);	mOut.f[10]=fCosine;				mOut.f[14]=PVRTF2X(0.0f); | 
|  | mOut.f[ 3]=PVRTF2X(0.0f);		mOut.f[ 7]=PVRTF2X(0.0f);	mOut.f[11]=PVRTF2X(0.0f);		mOut.f[15]=PVRTF2X(1.0f); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function Name		PVRTMatrixRotationZX | 
|  | @Output			mOut	Rotation matrix | 
|  | @Input				fAngle	Angle of the rotation | 
|  | @Description		Create an Z rotation matrix mOut. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixRotationZX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	fAngle) | 
|  | { | 
|  | int		fCosine, fSine; | 
|  |  | 
|  | /* Precompute cos and sin */ | 
|  | #if defined(BUILD_DX11) | 
|  | fCosine = PVRTXCOS(-fAngle); | 
|  | fSine   = PVRTXSIN(-fAngle); | 
|  | #else | 
|  | fCosine = PVRTXCOS(fAngle); | 
|  | fSine   = PVRTXSIN(fAngle); | 
|  | #endif | 
|  |  | 
|  | /* Create the trigonometric matrix corresponding to Z Rotation */ | 
|  | mOut.f[ 0]=fCosine;				mOut.f[ 4]=fSine;				mOut.f[ 8]=PVRTF2X(0.0f);	mOut.f[12]=PVRTF2X(0.0f); | 
|  | mOut.f[ 1]=-fSine;				mOut.f[ 5]=fCosine;				mOut.f[ 9]=PVRTF2X(0.0f);	mOut.f[13]=PVRTF2X(0.0f); | 
|  | mOut.f[ 2]=PVRTF2X(0.0f);		mOut.f[ 6]=PVRTF2X(0.0f);		mOut.f[10]=PVRTF2X(1.0f);	mOut.f[14]=PVRTF2X(0.0f); | 
|  | mOut.f[ 3]=PVRTF2X(0.0f);		mOut.f[ 7]=PVRTF2X(0.0f);		mOut.f[11]=PVRTF2X(0.0f);	mOut.f[15]=PVRTF2X(1.0f); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function Name		PVRTMatrixTransposeX | 
|  | @Output			mOut	Transposed matrix | 
|  | @Input				mIn		Original matrix | 
|  | @Description		Compute the transpose matrix of mIn. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixTransposeX( | 
|  | PVRTMATRIXx			&mOut, | 
|  | const PVRTMATRIXx	&mIn) | 
|  | { | 
|  | PVRTMATRIXx	mTmp; | 
|  |  | 
|  | mTmp.f[ 0]=mIn.f[ 0];	mTmp.f[ 4]=mIn.f[ 1];	mTmp.f[ 8]=mIn.f[ 2];	mTmp.f[12]=mIn.f[ 3]; | 
|  | mTmp.f[ 1]=mIn.f[ 4];	mTmp.f[ 5]=mIn.f[ 5];	mTmp.f[ 9]=mIn.f[ 6];	mTmp.f[13]=mIn.f[ 7]; | 
|  | mTmp.f[ 2]=mIn.f[ 8];	mTmp.f[ 6]=mIn.f[ 9];	mTmp.f[10]=mIn.f[10];	mTmp.f[14]=mIn.f[11]; | 
|  | mTmp.f[ 3]=mIn.f[12];	mTmp.f[ 7]=mIn.f[13];	mTmp.f[11]=mIn.f[14];	mTmp.f[15]=mIn.f[15]; | 
|  |  | 
|  | mOut = mTmp; | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixInverseX | 
|  | @Output			mOut	Inversed matrix | 
|  | @Input				mIn		Original matrix | 
|  | @Description		Compute the inverse matrix of mIn. | 
|  | The matrix must be of the form : | 
|  | A 0 | 
|  | C 1 | 
|  | Where A is a 3x3 matrix and C is a 1x3 matrix. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixInverseX( | 
|  | PVRTMATRIXx			&mOut, | 
|  | const PVRTMATRIXx	&mIn) | 
|  | { | 
|  | PVRTMATRIXx	mDummyMatrix; | 
|  | int			det_1; | 
|  | int			pos, neg, temp; | 
|  |  | 
|  | /* Calculate the determinant of submatrix A and determine if the | 
|  | the matrix is singular as limited by the double precision | 
|  | floating-point data representation. */ | 
|  | pos = neg = 0; | 
|  | temp =  PVRTXMUL(PVRTXMUL(mIn.f[ 0], mIn.f[ 5]), mIn.f[10]); | 
|  | if (temp >= 0) pos += temp; else neg += temp; | 
|  | temp =  PVRTXMUL(PVRTXMUL(mIn.f[ 4], mIn.f[ 9]), mIn.f[ 2]); | 
|  | if (temp >= 0) pos += temp; else neg += temp; | 
|  | temp =  PVRTXMUL(PVRTXMUL(mIn.f[ 8], mIn.f[ 1]), mIn.f[ 6]); | 
|  | if (temp >= 0) pos += temp; else neg += temp; | 
|  | temp =  PVRTXMUL(PVRTXMUL(-mIn.f[ 8], mIn.f[ 5]), mIn.f[ 2]); | 
|  | if (temp >= 0) pos += temp; else neg += temp; | 
|  | temp =  PVRTXMUL(PVRTXMUL(-mIn.f[ 4], mIn.f[ 1]), mIn.f[10]); | 
|  | if (temp >= 0) pos += temp; else neg += temp; | 
|  | temp =  PVRTXMUL(PVRTXMUL(-mIn.f[ 0], mIn.f[ 9]), mIn.f[ 6]); | 
|  | if (temp >= 0) pos += temp; else neg += temp; | 
|  | det_1 = pos + neg; | 
|  |  | 
|  | /* Is the submatrix A singular? */ | 
|  | if (det_1 == 0) | 
|  | { | 
|  | /* Matrix M has no inverse */ | 
|  | _RPT0(_CRT_WARN, "Matrix has no inverse : singular matrix\n"); | 
|  | return; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Calculate inverse(A) = adj(A) / det(A) */ | 
|  | //det_1 = 1.0 / det_1; | 
|  | det_1 = PVRTXDIV(PVRTF2X(1.0f), det_1); | 
|  | mDummyMatrix.f[ 0] =   PVRTXMUL(( PVRTXMUL(mIn.f[ 5], mIn.f[10]) - PVRTXMUL(mIn.f[ 9], mIn.f[ 6]) ), det_1); | 
|  | mDummyMatrix.f[ 1] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 1], mIn.f[10]) - PVRTXMUL(mIn.f[ 9], mIn.f[ 2]) ), det_1); | 
|  | mDummyMatrix.f[ 2] =   PVRTXMUL(( PVRTXMUL(mIn.f[ 1], mIn.f[ 6]) - PVRTXMUL(mIn.f[ 5], mIn.f[ 2]) ), det_1); | 
|  | mDummyMatrix.f[ 4] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 4], mIn.f[10]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 6]) ), det_1); | 
|  | mDummyMatrix.f[ 5] =   PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[10]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 2]) ), det_1); | 
|  | mDummyMatrix.f[ 6] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 6]) - PVRTXMUL(mIn.f[ 4], mIn.f[ 2]) ), det_1); | 
|  | mDummyMatrix.f[ 8] =   PVRTXMUL(( PVRTXMUL(mIn.f[ 4], mIn.f[ 9]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 5]) ), det_1); | 
|  | mDummyMatrix.f[ 9] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 9]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 1]) ), det_1); | 
|  | mDummyMatrix.f[10] =   PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 5]) - PVRTXMUL(mIn.f[ 4], mIn.f[ 1]) ), det_1); | 
|  |  | 
|  | /* Calculate -C * inverse(A) */ | 
|  | mDummyMatrix.f[12] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 0]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 4]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[ 8]) ); | 
|  | mDummyMatrix.f[13] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 1]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 5]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[ 9]) ); | 
|  | mDummyMatrix.f[14] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 2]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 6]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[10]) ); | 
|  |  | 
|  | /* Fill in last row */ | 
|  | mDummyMatrix.f[ 3] = PVRTF2X(0.0f); | 
|  | mDummyMatrix.f[ 7] = PVRTF2X(0.0f); | 
|  | mDummyMatrix.f[11] = PVRTF2X(0.0f); | 
|  | mDummyMatrix.f[15] = PVRTF2X(1.0f); | 
|  | } | 
|  |  | 
|  | /* Copy contents of dummy matrix in pfMatrix */ | 
|  | mOut = mDummyMatrix; | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixInverseExX | 
|  | @Output			mOut	Inversed matrix | 
|  | @Input				mIn		Original matrix | 
|  | @Description		Compute the inverse matrix of mIn. | 
|  | Uses a linear equation solver and the knowledge that M.M^-1=I. | 
|  | Use this fn to calculate the inverse of matrices that | 
|  | PVRTMatrixInverse() cannot. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixInverseExX( | 
|  | PVRTMATRIXx			&mOut, | 
|  | const PVRTMATRIXx	&mIn) | 
|  | { | 
|  | PVRTMATRIXx		mTmp; | 
|  | int				*ppfRows[4], pfRes[4], pfIn[20]; | 
|  | int				i, j; | 
|  |  | 
|  | for (i = 0; i < 4; ++i) | 
|  | { | 
|  | ppfRows[i] = &pfIn[i * 5]; | 
|  | } | 
|  |  | 
|  | /* Solve 4 sets of 4 linear equations */ | 
|  | for (i = 0; i < 4; ++i) | 
|  | { | 
|  | for (j = 0; j < 4; ++j) | 
|  | { | 
|  | ppfRows[j][0] = c_mIdentity.f[i + 4 * j]; | 
|  | memcpy(&ppfRows[j][1], &mIn.f[j * 4], 4 * sizeof(float)); | 
|  | } | 
|  |  | 
|  | PVRTMatrixLinearEqSolveX(pfRes, (int**)ppfRows, 4); | 
|  |  | 
|  | for(j = 0; j < 4; ++j) | 
|  | { | 
|  | mTmp.f[i + 4 * j] = pfRes[j]; | 
|  | } | 
|  | } | 
|  |  | 
|  | mOut = mTmp; | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixLookAtLHX | 
|  | @Output			mOut	Look-at view matrix | 
|  | @Input				vEye	Position of the camera | 
|  | @Input				vAt		Point the camera is looking at | 
|  | @Input				vUp		Up direction for the camera | 
|  | @Description		Create a look-at view matrix. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixLookAtLHX( | 
|  | PVRTMATRIXx			&mOut, | 
|  | const PVRTVECTOR3x	&vEye, | 
|  | const PVRTVECTOR3x	&vAt, | 
|  | const PVRTVECTOR3x	&vUp) | 
|  | { | 
|  | PVRTVECTOR3x	f, vUpActual, s, u; | 
|  | PVRTMATRIXx		t; | 
|  |  | 
|  | f.x = vEye.x - vAt.x; | 
|  | f.y = vEye.y - vAt.y; | 
|  | f.z = vEye.z - vAt.z; | 
|  |  | 
|  | PVRTMatrixVec3NormalizeX(f, f); | 
|  | PVRTMatrixVec3NormalizeX(vUpActual, vUp); | 
|  | PVRTMatrixVec3CrossProductX(s, f, vUpActual); | 
|  | PVRTMatrixVec3CrossProductX(u, s, f); | 
|  |  | 
|  | mOut.f[ 0] = s.x; | 
|  | mOut.f[ 1] = u.x; | 
|  | mOut.f[ 2] = -f.x; | 
|  | mOut.f[ 3] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 4] = s.y; | 
|  | mOut.f[ 5] = u.y; | 
|  | mOut.f[ 6] = -f.y; | 
|  | mOut.f[ 7] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 8] = s.z; | 
|  | mOut.f[ 9] = u.z; | 
|  | mOut.f[10] = -f.z; | 
|  | mOut.f[11] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[12] = PVRTF2X(0.0f); | 
|  | mOut.f[13] = PVRTF2X(0.0f); | 
|  | mOut.f[14] = PVRTF2X(0.0f); | 
|  | mOut.f[15] = PVRTF2X(1.0f); | 
|  |  | 
|  | PVRTMatrixTranslationX(t, -vEye.x, -vEye.y, -vEye.z); | 
|  | PVRTMatrixMultiplyX(mOut, t, mOut); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixLookAtRHX | 
|  | @Output			mOut	Look-at view matrix | 
|  | @Input				vEye	Position of the camera | 
|  | @Input				vAt		Point the camera is looking at | 
|  | @Input				vUp		Up direction for the camera | 
|  | @Description		Create a look-at view matrix. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixLookAtRHX( | 
|  | PVRTMATRIXx			&mOut, | 
|  | const PVRTVECTOR3x	&vEye, | 
|  | const PVRTVECTOR3x	&vAt, | 
|  | const PVRTVECTOR3x	&vUp) | 
|  | { | 
|  | PVRTVECTOR3x	f, vUpActual, s, u; | 
|  | PVRTMATRIXx		t; | 
|  |  | 
|  | f.x = vAt.x - vEye.x; | 
|  | f.y = vAt.y - vEye.y; | 
|  | f.z = vAt.z - vEye.z; | 
|  |  | 
|  | PVRTMatrixVec3NormalizeX(f, f); | 
|  | PVRTMatrixVec3NormalizeX(vUpActual, vUp); | 
|  | PVRTMatrixVec3CrossProductX(s, f, vUpActual); | 
|  | PVRTMatrixVec3CrossProductX(u, s, f); | 
|  |  | 
|  | mOut.f[ 0] = s.x; | 
|  | mOut.f[ 1] = u.x; | 
|  | mOut.f[ 2] = -f.x; | 
|  | mOut.f[ 3] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 4] = s.y; | 
|  | mOut.f[ 5] = u.y; | 
|  | mOut.f[ 6] = -f.y; | 
|  | mOut.f[ 7] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 8] = s.z; | 
|  | mOut.f[ 9] = u.z; | 
|  | mOut.f[10] = -f.z; | 
|  | mOut.f[11] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[12] = PVRTF2X(0.0f); | 
|  | mOut.f[13] = PVRTF2X(0.0f); | 
|  | mOut.f[14] = PVRTF2X(0.0f); | 
|  | mOut.f[15] = PVRTF2X(1.0f); | 
|  |  | 
|  | PVRTMatrixTranslationX(t, -vEye.x, -vEye.y, -vEye.z); | 
|  | PVRTMatrixMultiplyX(mOut, t, mOut); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function		PVRTMatrixPerspectiveFovLHX | 
|  | @Output		mOut		Perspective matrix | 
|  | @Input			fFOVy		Field of view | 
|  | @Input			fAspect		Aspect ratio | 
|  | @Input			fNear		Near clipping distance | 
|  | @Input			fFar		Far clipping distance | 
|  | @Input			bRotate		Should we rotate it ? (for upright screens) | 
|  | @Description	Create a perspective matrix. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixPerspectiveFovLHX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	fFOVy, | 
|  | const int	fAspect, | 
|  | const int	fNear, | 
|  | const int	fFar, | 
|  | const bool  bRotate) | 
|  | { | 
|  | int		f, fRealAspect; | 
|  |  | 
|  | if (bRotate) | 
|  | fRealAspect = PVRTXDIV(PVRTF2X(1.0f), fAspect); | 
|  | else | 
|  | fRealAspect = fAspect; | 
|  |  | 
|  | f = PVRTXDIV(PVRTF2X(1.0f), PVRTXTAN(PVRTXMUL(fFOVy, PVRTF2X(0.5f)))); | 
|  |  | 
|  | mOut.f[ 0] = PVRTXDIV(f, fRealAspect); | 
|  | mOut.f[ 1] = PVRTF2X(0.0f); | 
|  | mOut.f[ 2] = PVRTF2X(0.0f); | 
|  | mOut.f[ 3] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 4] = PVRTF2X(0.0f); | 
|  | mOut.f[ 5] = f; | 
|  | mOut.f[ 6] = PVRTF2X(0.0f); | 
|  | mOut.f[ 7] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 8] = PVRTF2X(0.0f); | 
|  | mOut.f[ 9] = PVRTF2X(0.0f); | 
|  | mOut.f[10] = PVRTXDIV(fFar, fFar - fNear); | 
|  | mOut.f[11] = PVRTF2X(1.0f); | 
|  |  | 
|  | mOut.f[12] = PVRTF2X(0.0f); | 
|  | mOut.f[13] = PVRTF2X(0.0f); | 
|  | mOut.f[14] = -PVRTXMUL(PVRTXDIV(fFar, fFar - fNear), fNear); | 
|  | mOut.f[15] = PVRTF2X(0.0f); | 
|  |  | 
|  | if (bRotate) | 
|  | { | 
|  | PVRTMATRIXx mRotation, mTemp = mOut; | 
|  | PVRTMatrixRotationZX(mRotation, PVRTF2X(90.0f*PVRT_PIf/180.0f)); | 
|  | PVRTMatrixMultiplyX(mOut, mTemp, mRotation); | 
|  | } | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function		PVRTMatrixPerspectiveFovRHX | 
|  | @Output		mOut		Perspective matrix | 
|  | @Input			fFOVy		Field of view | 
|  | @Input			fAspect		Aspect ratio | 
|  | @Input			fNear		Near clipping distance | 
|  | @Input			fFar		Far clipping distance | 
|  | @Input			bRotate		Should we rotate it ? (for upright screens) | 
|  | @Description	Create a perspective matrix. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixPerspectiveFovRHX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	fFOVy, | 
|  | const int	fAspect, | 
|  | const int	fNear, | 
|  | const int	fFar, | 
|  | const bool  bRotate) | 
|  | { | 
|  | int		f; | 
|  |  | 
|  | int fCorrectAspect = fAspect; | 
|  | if (bRotate) | 
|  | { | 
|  | fCorrectAspect = PVRTXDIV(PVRTF2X(1.0f), fAspect); | 
|  | } | 
|  | f = PVRTXDIV(PVRTF2X(1.0f), PVRTXTAN(PVRTXMUL(fFOVy, PVRTF2X(0.5f)))); | 
|  |  | 
|  | mOut.f[ 0] = PVRTXDIV(f, fCorrectAspect); | 
|  | mOut.f[ 1] = PVRTF2X(0.0f); | 
|  | mOut.f[ 2] = PVRTF2X(0.0f); | 
|  | mOut.f[ 3] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 4] = PVRTF2X(0.0f); | 
|  | mOut.f[ 5] = f; | 
|  | mOut.f[ 6] = PVRTF2X(0.0f); | 
|  | mOut.f[ 7] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 8] = PVRTF2X(0.0f); | 
|  | mOut.f[ 9] = PVRTF2X(0.0f); | 
|  | mOut.f[10] = PVRTXDIV(fFar + fNear, fNear - fFar); | 
|  | mOut.f[11] = PVRTF2X(-1.0f); | 
|  |  | 
|  | mOut.f[12] = PVRTF2X(0.0f); | 
|  | mOut.f[13] = PVRTF2X(0.0f); | 
|  | mOut.f[14] = PVRTXMUL(PVRTXDIV(fFar, fNear - fFar), fNear) << 1;	// Cheap 2x | 
|  | mOut.f[15] = PVRTF2X(0.0f); | 
|  |  | 
|  | if (bRotate) | 
|  | { | 
|  | PVRTMATRIXx mRotation, mTemp = mOut; | 
|  | PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f)); | 
|  | PVRTMatrixMultiplyX(mOut, mTemp, mRotation); | 
|  | } | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function		PVRTMatrixOrthoLHX | 
|  | @Output		mOut		Orthographic matrix | 
|  | @Input			w			Width of the screen | 
|  | @Input			h			Height of the screen | 
|  | @Input			zn			Near clipping distance | 
|  | @Input			zf			Far clipping distance | 
|  | @Input			bRotate		Should we rotate it ? (for upright screens) | 
|  | @Description	Create an orthographic matrix. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixOrthoLHX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	w, | 
|  | const int	h, | 
|  | const int	zn, | 
|  | const int	zf, | 
|  | const bool  bRotate) | 
|  | { | 
|  | int fCorrectW = w; | 
|  | int fCorrectH = h; | 
|  | if (bRotate) | 
|  | { | 
|  | fCorrectW = h; | 
|  | fCorrectH = w; | 
|  | } | 
|  | mOut.f[ 0] = PVRTXDIV(PVRTF2X(2.0f), fCorrectW); | 
|  | mOut.f[ 1] = PVRTF2X(0.0f); | 
|  | mOut.f[ 2] = PVRTF2X(0.0f); | 
|  | mOut.f[ 3] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 4] = PVRTF2X(0.0f); | 
|  | mOut.f[ 5] = PVRTXDIV(PVRTF2X(2.0f), fCorrectH); | 
|  | mOut.f[ 6] = PVRTF2X(0.0f); | 
|  | mOut.f[ 7] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 8] = PVRTF2X(0.0f); | 
|  | mOut.f[ 9] = PVRTF2X(0.0f); | 
|  | mOut.f[10] = PVRTXDIV(PVRTF2X(1.0f), zf - zn); | 
|  | mOut.f[11] = PVRTXDIV(zn, zn - zf); | 
|  |  | 
|  | mOut.f[12] = PVRTF2X(0.0f); | 
|  | mOut.f[13] = PVRTF2X(0.0f); | 
|  | mOut.f[14] = PVRTF2X(0.0f); | 
|  | mOut.f[15] = PVRTF2X(1.0f); | 
|  |  | 
|  | if (bRotate) | 
|  | { | 
|  | PVRTMATRIXx mRotation, mTemp = mOut; | 
|  | PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f)); | 
|  | PVRTMatrixMultiplyX(mOut, mRotation, mTemp); | 
|  | } | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function		PVRTMatrixOrthoRHX | 
|  | @Output		mOut		Orthographic matrix | 
|  | @Input			w			Width of the screen | 
|  | @Input			h			Height of the screen | 
|  | @Input			zn			Near clipping distance | 
|  | @Input			zf			Far clipping distance | 
|  | @Input			bRotate		Should we rotate it ? (for upright screens) | 
|  | @Description	Create an orthographic matrix. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixOrthoRHX( | 
|  | PVRTMATRIXx	&mOut, | 
|  | const int	w, | 
|  | const int	h, | 
|  | const int	zn, | 
|  | const int	zf, | 
|  | const bool  bRotate) | 
|  | { | 
|  | int fCorrectW = w; | 
|  | int fCorrectH = h; | 
|  | if (bRotate) | 
|  | { | 
|  | fCorrectW = h; | 
|  | fCorrectH = w; | 
|  | } | 
|  | mOut.f[ 0] = PVRTXDIV(PVRTF2X(2.0f), fCorrectW); | 
|  | mOut.f[ 1] = PVRTF2X(0.0f); | 
|  | mOut.f[ 2] = PVRTF2X(0.0f); | 
|  | mOut.f[ 3] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 4] = PVRTF2X(0.0f); | 
|  | mOut.f[ 5] = PVRTXDIV(PVRTF2X(2.0f), fCorrectH); | 
|  | mOut.f[ 6] = PVRTF2X(0.0f); | 
|  | mOut.f[ 7] = PVRTF2X(0.0f); | 
|  |  | 
|  | mOut.f[ 8] = PVRTF2X(0.0f); | 
|  | mOut.f[ 9] = PVRTF2X(0.0f); | 
|  | mOut.f[10] = PVRTXDIV(PVRTF2X(1.0f), zn - zf); | 
|  | mOut.f[11] = PVRTXDIV(zn, zn - zf); | 
|  |  | 
|  | mOut.f[12] = PVRTF2X(0.0f); | 
|  | mOut.f[13] = PVRTF2X(0.0f); | 
|  | mOut.f[14] = PVRTF2X(0.0f); | 
|  | mOut.f[15] = PVRTF2X(1.0f); | 
|  |  | 
|  | if (bRotate) | 
|  | { | 
|  | PVRTMATRIXx mRotation, mTemp = mOut; | 
|  | PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f)); | 
|  | PVRTMatrixMultiplyX(mOut, mRotation, mTemp); | 
|  | } | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixVec3LerpX | 
|  | @Output			vOut	Result of the interpolation | 
|  | @Input				v1		First vector to interpolate from | 
|  | @Input				v2		Second vector to interpolate form | 
|  | @Input				s		Coefficient of interpolation | 
|  | @Description		This function performs the linear interpolation based on | 
|  | the following formula: V1 + s(V2-V1). | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixVec3LerpX( | 
|  | PVRTVECTOR3x		&vOut, | 
|  | const PVRTVECTOR3x	&v1, | 
|  | const PVRTVECTOR3x	&v2, | 
|  | const int			s) | 
|  | { | 
|  | vOut.x = v1.x + PVRTXMUL(s, v2.x - v1.x); | 
|  | vOut.y = v1.y + PVRTXMUL(s, v2.y - v1.y); | 
|  | vOut.z = v1.z + PVRTXMUL(s, v2.z - v1.z); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixVec3DotProductX | 
|  | @Input				v1		First vector | 
|  | @Input				v2		Second vector | 
|  | @Return			Dot product of the two vectors. | 
|  | @Description		This function performs the dot product of the two | 
|  | supplied vectors. | 
|  | A single >> 16 shift could be applied to the final accumulated | 
|  | result however this runs the risk of overflow between the | 
|  | results of the intermediate additions. | 
|  | *****************************************************************************/ | 
|  | int PVRTMatrixVec3DotProductX( | 
|  | const PVRTVECTOR3x	&v1, | 
|  | const PVRTVECTOR3x	&v2) | 
|  | { | 
|  | return (PVRTXMUL(v1.x, v2.x) + PVRTXMUL(v1.y, v2.y) + PVRTXMUL(v1.z, v2.z)); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixVec3CrossProductX | 
|  | @Output			vOut	Cross product of the two vectors | 
|  | @Input				v1		First vector | 
|  | @Input				v2		Second vector | 
|  | @Description		This function performs the cross product of the two | 
|  | supplied vectors. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixVec3CrossProductX( | 
|  | PVRTVECTOR3x		&vOut, | 
|  | const PVRTVECTOR3x	&v1, | 
|  | const PVRTVECTOR3x	&v2) | 
|  | { | 
|  | PVRTVECTOR3x result; | 
|  |  | 
|  | /* Perform calculation on a dummy VECTOR (result) */ | 
|  | result.x = PVRTXMUL(v1.y, v2.z) - PVRTXMUL(v1.z, v2.y); | 
|  | result.y = PVRTXMUL(v1.z, v2.x) - PVRTXMUL(v1.x, v2.z); | 
|  | result.z = PVRTXMUL(v1.x, v2.y) - PVRTXMUL(v1.y, v2.x); | 
|  |  | 
|  | /* Copy result in pOut */ | 
|  | vOut = result; | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixVec3NormalizeX | 
|  | @Output			vOut	Normalized vector | 
|  | @Input				vIn		Vector to normalize | 
|  | @Description		Normalizes the supplied vector. | 
|  | The square root function is currently still performed | 
|  | in floating-point. | 
|  | Original vector is scaled down prior to be normalized in | 
|  | order to avoid overflow issues. | 
|  | ****************************************************************************/ | 
|  | void PVRTMatrixVec3NormalizeX( | 
|  | PVRTVECTOR3x		&vOut, | 
|  | const PVRTVECTOR3x	&vIn) | 
|  | { | 
|  | int				f, n; | 
|  | PVRTVECTOR3x	vTemp; | 
|  |  | 
|  | /* Scale vector by uniform value */ | 
|  | n = PVRTABS(vIn.x) + PVRTABS(vIn.y) + PVRTABS(vIn.z); | 
|  | vTemp.x = PVRTXDIV(vIn.x, n); | 
|  | vTemp.y = PVRTXDIV(vIn.y, n); | 
|  | vTemp.z = PVRTXDIV(vIn.z, n); | 
|  |  | 
|  | /* Calculate x2+y2+z2/sqrt(x2+y2+z2) */ | 
|  | f = PVRTMatrixVec3DotProductX(vTemp, vTemp); | 
|  | f = PVRTXDIV(PVRTF2X(1.0f), PVRTF2X(sqrt(PVRTX2F(f)))); | 
|  |  | 
|  | /* Multiply vector components by f */ | 
|  | vOut.x = PVRTXMUL(vTemp.x, f); | 
|  | vOut.y = PVRTXMUL(vTemp.y, f); | 
|  | vOut.z = PVRTXMUL(vTemp.z, f); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixVec3LengthX | 
|  | @Input				vIn		Vector to get the length of | 
|  | @Return			The length of the vector | 
|  | @Description		Gets the length of the supplied vector | 
|  | *****************************************************************************/ | 
|  | int PVRTMatrixVec3LengthX( | 
|  | const PVRTVECTOR3x	&vIn) | 
|  | { | 
|  | int temp; | 
|  |  | 
|  | temp = PVRTXMUL(vIn.x,vIn.x) + PVRTXMUL(vIn.y,vIn.y) + PVRTXMUL(vIn.z,vIn.z); | 
|  | return PVRTF2X(sqrt(PVRTX2F(temp))); | 
|  | } | 
|  |  | 
|  | /*!*************************************************************************** | 
|  | @Function			PVRTMatrixLinearEqSolveX | 
|  | @Input				pSrc	2D array of floats. 4 Eq linear problem is 5x4 | 
|  | matrix, constants in first column | 
|  | @Input				nCnt	Number of equations to solve | 
|  | @Output			pRes	Result | 
|  | @Description		Solves 'nCnt' simultaneous equations of 'nCnt' variables. | 
|  | pRes should be an array large enough to contain the | 
|  | results: the values of the 'nCnt' variables. | 
|  | This fn recursively uses Gaussian Elimination. | 
|  | *****************************************************************************/ | 
|  | void PVRTMatrixLinearEqSolveX( | 
|  | int			* const pRes, | 
|  | int			** const pSrc, | 
|  | const int	nCnt) | 
|  | { | 
|  | int		i, j, k; | 
|  | int		f; | 
|  |  | 
|  | if (nCnt == 1) | 
|  | { | 
|  | _ASSERT(pSrc[0][1] != 0); | 
|  | pRes[0] = PVRTXDIV(pSrc[0][0], pSrc[0][1]); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Loop backwards in an attempt avoid the need to swap rows | 
|  | i = nCnt; | 
|  | while(i) | 
|  | { | 
|  | --i; | 
|  |  | 
|  | if(pSrc[i][nCnt] != PVRTF2X(0.0f)) | 
|  | { | 
|  | // Row i can be used to zero the other rows; let's move it to the bottom | 
|  | if(i != (nCnt-1)) | 
|  | { | 
|  | for(j = 0; j <= nCnt; ++j) | 
|  | { | 
|  | // Swap the two values | 
|  | f = pSrc[nCnt-1][j]; | 
|  | pSrc[nCnt-1][j] = pSrc[i][j]; | 
|  | pSrc[i][j] = f; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Now zero the last columns of the top rows | 
|  | for(j = 0; j < (nCnt-1); ++j) | 
|  | { | 
|  | _ASSERT(pSrc[nCnt-1][nCnt] != PVRTF2X(0.0f)); | 
|  | f = PVRTXDIV(pSrc[j][nCnt], pSrc[nCnt-1][nCnt]); | 
|  |  | 
|  | // No need to actually calculate a zero for the final column | 
|  | for(k = 0; k < nCnt; ++k) | 
|  | { | 
|  | pSrc[j][k] -= PVRTXMUL(f, pSrc[nCnt-1][k]); | 
|  | } | 
|  | } | 
|  |  | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Solve the top-left sub matrix | 
|  | PVRTMatrixLinearEqSolveX(pRes, pSrc, nCnt - 1); | 
|  |  | 
|  | // Now calc the solution for the bottom row | 
|  | f = pSrc[nCnt-1][0]; | 
|  | for(k = 1; k < nCnt; ++k) | 
|  | { | 
|  | f -= PVRTXMUL(pSrc[nCnt-1][k], pRes[k-1]); | 
|  | } | 
|  | _ASSERT(pSrc[nCnt-1][nCnt] != PVRTF2X(0)); | 
|  | f = PVRTXDIV(f, pSrc[nCnt-1][nCnt]); | 
|  | pRes[nCnt-1] = f; | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | End of file (PVRTMatrixX.cpp) | 
|  | *****************************************************************************/ | 
|  |  |