Home | History | Annotate | Download | only in Tools
      1 /******************************************************************************
      2 
      3  @File         PVRTMatrixF.cpp
      4 
      5  @Title        PVRTMatrixF
      6 
      7  @Version
      8 
      9  @Copyright    Copyright (c) Imagination Technologies Limited.
     10 
     11  @Platform     ANSI compatible
     12 
     13  @Description  Set of mathematical functions involving matrices, vectors and
     14                quaternions. The general matrix format used is directly compatible
     15                with, for example, both DirectX and OpenGL. For the reasons why,
     16                read this:
     17                http://research.microsoft.com/~hollasch/cgindex/math/matrix/column-vec.html
     18 
     19 ******************************************************************************/
     20 #include "PVRTGlobal.h"
     21 #include <math.h>
     22 #include <string.h>
     23 #include "PVRTFixedPoint.h"		// Only needed for trig function float lookups
     24 #include "PVRTMatrix.h"
     25 
     26 
     27 /****************************************************************************
     28 ** Constants
     29 ****************************************************************************/
     30 static const PVRTMATRIXf	c_mIdentity = {
     31 	{
     32 	1, 0, 0, 0,
     33 	0, 1, 0, 0,
     34 	0, 0, 1, 0,
     35 	0, 0, 0, 1
     36 	}
     37 };
     38 
     39 /****************************************************************************
     40 ** Functions
     41 ****************************************************************************/
     42 
     43 /*!***************************************************************************
     44  @Function			PVRTMatrixIdentityF
     45  @Output			mOut	Set to identity
     46  @Description		Reset matrix to identity matrix.
     47 *****************************************************************************/
     48 void PVRTMatrixIdentityF(PVRTMATRIXf &mOut)
     49 {
     50 	mOut.f[ 0]=1.0f;	mOut.f[ 4]=0.0f;	mOut.f[ 8]=0.0f;	mOut.f[12]=0.0f;
     51 	mOut.f[ 1]=0.0f;	mOut.f[ 5]=1.0f;	mOut.f[ 9]=0.0f;	mOut.f[13]=0.0f;
     52 	mOut.f[ 2]=0.0f;	mOut.f[ 6]=0.0f;	mOut.f[10]=1.0f;	mOut.f[14]=0.0f;
     53 	mOut.f[ 3]=0.0f;	mOut.f[ 7]=0.0f;	mOut.f[11]=0.0f;	mOut.f[15]=1.0f;
     54 }
     55 
     56 
     57 /*!***************************************************************************
     58  @Function			PVRTMatrixMultiplyF
     59  @Output			mOut	Result of mA x mB
     60  @Input				mA		First operand
     61  @Input				mB		Second operand
     62  @Description		Multiply mA by mB and assign the result to mOut
     63 					(mOut = p1 * p2). A copy of the result matrix is done in
     64 					the function because mOut can be a parameter mA or mB.
     65 *****************************************************************************/
     66 void PVRTMatrixMultiplyF(
     67 	PVRTMATRIXf			&mOut,
     68 	const PVRTMATRIXf	&mA,
     69 	const PVRTMATRIXf	&mB)
     70 {
     71 	PVRTMATRIXf mRet;
     72 
     73 	/* Perform calculation on a dummy matrix (mRet) */
     74 	mRet.f[ 0] = mA.f[ 0]*mB.f[ 0] + mA.f[ 1]*mB.f[ 4] + mA.f[ 2]*mB.f[ 8] + mA.f[ 3]*mB.f[12];
     75 	mRet.f[ 1] = mA.f[ 0]*mB.f[ 1] + mA.f[ 1]*mB.f[ 5] + mA.f[ 2]*mB.f[ 9] + mA.f[ 3]*mB.f[13];
     76 	mRet.f[ 2] = mA.f[ 0]*mB.f[ 2] + mA.f[ 1]*mB.f[ 6] + mA.f[ 2]*mB.f[10] + mA.f[ 3]*mB.f[14];
     77 	mRet.f[ 3] = mA.f[ 0]*mB.f[ 3] + mA.f[ 1]*mB.f[ 7] + mA.f[ 2]*mB.f[11] + mA.f[ 3]*mB.f[15];
     78 
     79 	mRet.f[ 4] = mA.f[ 4]*mB.f[ 0] + mA.f[ 5]*mB.f[ 4] + mA.f[ 6]*mB.f[ 8] + mA.f[ 7]*mB.f[12];
     80 	mRet.f[ 5] = mA.f[ 4]*mB.f[ 1] + mA.f[ 5]*mB.f[ 5] + mA.f[ 6]*mB.f[ 9] + mA.f[ 7]*mB.f[13];
     81 	mRet.f[ 6] = mA.f[ 4]*mB.f[ 2] + mA.f[ 5]*mB.f[ 6] + mA.f[ 6]*mB.f[10] + mA.f[ 7]*mB.f[14];
     82 	mRet.f[ 7] = mA.f[ 4]*mB.f[ 3] + mA.f[ 5]*mB.f[ 7] + mA.f[ 6]*mB.f[11] + mA.f[ 7]*mB.f[15];
     83 
     84 	mRet.f[ 8] = mA.f[ 8]*mB.f[ 0] + mA.f[ 9]*mB.f[ 4] + mA.f[10]*mB.f[ 8] + mA.f[11]*mB.f[12];
     85 	mRet.f[ 9] = mA.f[ 8]*mB.f[ 1] + mA.f[ 9]*mB.f[ 5] + mA.f[10]*mB.f[ 9] + mA.f[11]*mB.f[13];
     86 	mRet.f[10] = mA.f[ 8]*mB.f[ 2] + mA.f[ 9]*mB.f[ 6] + mA.f[10]*mB.f[10] + mA.f[11]*mB.f[14];
     87 	mRet.f[11] = mA.f[ 8]*mB.f[ 3] + mA.f[ 9]*mB.f[ 7] + mA.f[10]*mB.f[11] + mA.f[11]*mB.f[15];
     88 
     89 	mRet.f[12] = mA.f[12]*mB.f[ 0] + mA.f[13]*mB.f[ 4] + mA.f[14]*mB.f[ 8] + mA.f[15]*mB.f[12];
     90 	mRet.f[13] = mA.f[12]*mB.f[ 1] + mA.f[13]*mB.f[ 5] + mA.f[14]*mB.f[ 9] + mA.f[15]*mB.f[13];
     91 	mRet.f[14] = mA.f[12]*mB.f[ 2] + mA.f[13]*mB.f[ 6] + mA.f[14]*mB.f[10] + mA.f[15]*mB.f[14];
     92 	mRet.f[15] = mA.f[12]*mB.f[ 3] + mA.f[13]*mB.f[ 7] + mA.f[14]*mB.f[11] + mA.f[15]*mB.f[15];
     93 
     94 	/* Copy result to mOut */
     95 	mOut = mRet;
     96 }
     97 
     98 
     99 /*!***************************************************************************
    100  @Function Name		PVRTMatrixTranslationF
    101  @Output			mOut	Translation matrix
    102  @Input				fX		X component of the translation
    103  @Input				fY		Y component of the translation
    104  @Input				fZ		Z component of the translation
    105  @Description		Build a transaltion matrix mOut using fX, fY and fZ.
    106 *****************************************************************************/
    107 void PVRTMatrixTranslationF(
    108 	PVRTMATRIXf	&mOut,
    109 	const float fX,
    110 	const float fY,
    111 	const float fZ)
    112 {
    113 	mOut.f[ 0]=1.0f;	mOut.f[ 4]=0.0f;	mOut.f[ 8]=0.0f;	mOut.f[12]=fX;
    114 	mOut.f[ 1]=0.0f;	mOut.f[ 5]=1.0f;	mOut.f[ 9]=0.0f;	mOut.f[13]=fY;
    115 	mOut.f[ 2]=0.0f;	mOut.f[ 6]=0.0f;	mOut.f[10]=1.0f;	mOut.f[14]=fZ;
    116 	mOut.f[ 3]=0.0f;	mOut.f[ 7]=0.0f;	mOut.f[11]=0.0f;	mOut.f[15]=1.0f;
    117 }
    118 
    119 /*!***************************************************************************
    120  @Function Name		PVRTMatrixScalingF
    121  @Output			mOut	Scale matrix
    122  @Input				fX		X component of the scaling
    123  @Input				fY		Y component of the scaling
    124  @Input				fZ		Z component of the scaling
    125  @Description		Build a scale matrix mOut using fX, fY and fZ.
    126 *****************************************************************************/
    127 void PVRTMatrixScalingF(
    128 	PVRTMATRIXf	&mOut,
    129 	const float fX,
    130 	const float fY,
    131 	const float fZ)
    132 {
    133 	mOut.f[ 0]=fX;		mOut.f[ 4]=0.0f;	mOut.f[ 8]=0.0f;	mOut.f[12]=0.0f;
    134 	mOut.f[ 1]=0.0f;	mOut.f[ 5]=fY;		mOut.f[ 9]=0.0f;	mOut.f[13]=0.0f;
    135 	mOut.f[ 2]=0.0f;	mOut.f[ 6]=0.0f;	mOut.f[10]=fZ;		mOut.f[14]=0.0f;
    136 	mOut.f[ 3]=0.0f;	mOut.f[ 7]=0.0f;	mOut.f[11]=0.0f;	mOut.f[15]=1.0f;
    137 }
    138 
    139 /*!***************************************************************************
    140  @Function Name		PVRTMatrixRotationXF
    141  @Output			mOut	Rotation matrix
    142  @Input				fAngle	Angle of the rotation
    143  @Description		Create an X rotation matrix mOut.
    144 *****************************************************************************/
    145 void PVRTMatrixRotationXF(
    146 	PVRTMATRIXf	&mOut,
    147 	const float fAngle)
    148 {
    149 	float		fCosine, fSine;
    150 
    151     /* Precompute cos and sin */
    152 #if defined(BUILD_DX11)
    153 	fCosine	= (float)PVRTFCOS(-fAngle);
    154     fSine	= (float)PVRTFSIN(-fAngle);
    155 #else
    156 	fCosine	= (float)PVRTFCOS(fAngle);
    157     fSine	= (float)PVRTFSIN(fAngle);
    158 #endif
    159 
    160 	/* Create the trigonometric matrix corresponding to X Rotation */
    161 	mOut.f[ 0]=1.0f;	mOut.f[ 4]=0.0f;	mOut.f[ 8]=0.0f;	mOut.f[12]=0.0f;
    162 	mOut.f[ 1]=0.0f;	mOut.f[ 5]=fCosine;	mOut.f[ 9]=fSine;	mOut.f[13]=0.0f;
    163 	mOut.f[ 2]=0.0f;	mOut.f[ 6]=-fSine;	mOut.f[10]=fCosine;	mOut.f[14]=0.0f;
    164 	mOut.f[ 3]=0.0f;	mOut.f[ 7]=0.0f;	mOut.f[11]=0.0f;	mOut.f[15]=1.0f;
    165 }
    166 
    167 /*!***************************************************************************
    168  @Function Name		PVRTMatrixRotationYF
    169  @Output			mOut	Rotation matrix
    170  @Input				fAngle	Angle of the rotation
    171  @Description		Create an Y rotation matrix mOut.
    172 *****************************************************************************/
    173 void PVRTMatrixRotationYF(
    174 	PVRTMATRIXf	&mOut,
    175 	const float fAngle)
    176 {
    177 	float		fCosine, fSine;
    178 
    179 	/* Precompute cos and sin */
    180 #if defined(BUILD_DX11)
    181 	fCosine	= (float)PVRTFCOS(-fAngle);
    182     fSine	= (float)PVRTFSIN(-fAngle);
    183 #else
    184 	fCosine	= (float)PVRTFCOS(fAngle);
    185     fSine	= (float)PVRTFSIN(fAngle);
    186 #endif
    187 
    188 	/* Create the trigonometric matrix corresponding to Y Rotation */
    189 	mOut.f[ 0]=fCosine;		mOut.f[ 4]=0.0f;	mOut.f[ 8]=-fSine;		mOut.f[12]=0.0f;
    190 	mOut.f[ 1]=0.0f;		mOut.f[ 5]=1.0f;	mOut.f[ 9]=0.0f;		mOut.f[13]=0.0f;
    191 	mOut.f[ 2]=fSine;		mOut.f[ 6]=0.0f;	mOut.f[10]=fCosine;		mOut.f[14]=0.0f;
    192 	mOut.f[ 3]=0.0f;		mOut.f[ 7]=0.0f;	mOut.f[11]=0.0f;		mOut.f[15]=1.0f;
    193 }
    194 
    195 /*!***************************************************************************
    196  @Function Name		PVRTMatrixRotationZF
    197  @Output			mOut	Rotation matrix
    198  @Input				fAngle	Angle of the rotation
    199  @Description		Create an Z rotation matrix mOut.
    200 *****************************************************************************/
    201 void PVRTMatrixRotationZF(
    202 	PVRTMATRIXf	&mOut,
    203 	const float fAngle)
    204 {
    205 	float		fCosine, fSine;
    206 
    207 	/* Precompute cos and sin */
    208 #if defined(BUILD_DX11)
    209 	fCosine =	(float)PVRTFCOS(-fAngle);
    210     fSine =		(float)PVRTFSIN(-fAngle);
    211 #else
    212 	fCosine =	(float)PVRTFCOS(fAngle);
    213     fSine =		(float)PVRTFSIN(fAngle);
    214 #endif
    215 
    216 	/* Create the trigonometric matrix corresponding to Z Rotation */
    217 	mOut.f[ 0]=fCosine;		mOut.f[ 4]=fSine;	mOut.f[ 8]=0.0f;	mOut.f[12]=0.0f;
    218 	mOut.f[ 1]=-fSine;		mOut.f[ 5]=fCosine;	mOut.f[ 9]=0.0f;	mOut.f[13]=0.0f;
    219 	mOut.f[ 2]=0.0f;		mOut.f[ 6]=0.0f;	mOut.f[10]=1.0f;	mOut.f[14]=0.0f;
    220 	mOut.f[ 3]=0.0f;		mOut.f[ 7]=0.0f;	mOut.f[11]=0.0f;	mOut.f[15]=1.0f;
    221 }
    222 
    223 /*!***************************************************************************
    224  @Function Name		PVRTMatrixTransposeF
    225  @Output			mOut	Transposed matrix
    226  @Input				mIn		Original matrix
    227  @Description		Compute the transpose matrix of mIn.
    228 *****************************************************************************/
    229 void PVRTMatrixTransposeF(
    230 	PVRTMATRIXf			&mOut,
    231 	const PVRTMATRIXf	&mIn)
    232 {
    233 	PVRTMATRIXf	mTmp;
    234 
    235 	mTmp.f[ 0]=mIn.f[ 0];	mTmp.f[ 4]=mIn.f[ 1];	mTmp.f[ 8]=mIn.f[ 2];	mTmp.f[12]=mIn.f[ 3];
    236 	mTmp.f[ 1]=mIn.f[ 4];	mTmp.f[ 5]=mIn.f[ 5];	mTmp.f[ 9]=mIn.f[ 6];	mTmp.f[13]=mIn.f[ 7];
    237 	mTmp.f[ 2]=mIn.f[ 8];	mTmp.f[ 6]=mIn.f[ 9];	mTmp.f[10]=mIn.f[10];	mTmp.f[14]=mIn.f[11];
    238 	mTmp.f[ 3]=mIn.f[12];	mTmp.f[ 7]=mIn.f[13];	mTmp.f[11]=mIn.f[14];	mTmp.f[15]=mIn.f[15];
    239 
    240 	mOut = mTmp;
    241 }
    242 
    243 /*!***************************************************************************
    244  @Function			PVRTMatrixInverseF
    245  @Output			mOut	Inversed matrix
    246  @Input				mIn		Original matrix
    247  @Description		Compute the inverse matrix of mIn.
    248 					The matrix must be of the form :
    249 					A 0
    250 					C 1
    251 					Where A is a 3x3 matrix and C is a 1x3 matrix.
    252 *****************************************************************************/
    253 void PVRTMatrixInverseF(
    254 	PVRTMATRIXf			&mOut,
    255 	const PVRTMATRIXf	&mIn)
    256 {
    257 	PVRTMATRIXf	mDummyMatrix;
    258 	double		det_1;
    259 	double		pos, neg, temp;
    260 
    261     /* Calculate the determinant of submatrix A and determine if the
    262        the matrix is singular as limited by the double precision
    263        floating-point data representation. */
    264     pos = neg = 0.0;
    265     temp =  mIn.f[ 0] * mIn.f[ 5] * mIn.f[10];
    266     if (temp >= 0.0) pos += temp; else neg += temp;
    267     temp =  mIn.f[ 4] * mIn.f[ 9] * mIn.f[ 2];
    268     if (temp >= 0.0) pos += temp; else neg += temp;
    269     temp =  mIn.f[ 8] * mIn.f[ 1] * mIn.f[ 6];
    270     if (temp >= 0.0) pos += temp; else neg += temp;
    271     temp = -mIn.f[ 8] * mIn.f[ 5] * mIn.f[ 2];
    272     if (temp >= 0.0) pos += temp; else neg += temp;
    273     temp = -mIn.f[ 4] * mIn.f[ 1] * mIn.f[10];
    274     if (temp >= 0.0) pos += temp; else neg += temp;
    275     temp = -mIn.f[ 0] * mIn.f[ 9] * mIn.f[ 6];
    276     if (temp >= 0.0) pos += temp; else neg += temp;
    277     det_1 = pos + neg;
    278 
    279     /* Is the submatrix A singular? */
    280     if ((det_1 == 0.0) || (PVRTABS(det_1 / (pos - neg)) < 1.0e-15))
    281 	{
    282         /* Matrix M has no inverse */
    283         _RPT0(_CRT_WARN, "Matrix has no inverse : singular matrix\n");
    284         return;
    285     }
    286     else
    287 	{
    288         /* Calculate inverse(A) = adj(A) / det(A) */
    289         det_1 = 1.0 / det_1;
    290         mDummyMatrix.f[ 0] =   ( mIn.f[ 5] * mIn.f[10] - mIn.f[ 9] * mIn.f[ 6] ) * (float)det_1;
    291         mDummyMatrix.f[ 1] = - ( mIn.f[ 1] * mIn.f[10] - mIn.f[ 9] * mIn.f[ 2] ) * (float)det_1;
    292         mDummyMatrix.f[ 2] =   ( mIn.f[ 1] * mIn.f[ 6] - mIn.f[ 5] * mIn.f[ 2] ) * (float)det_1;
    293         mDummyMatrix.f[ 4] = - ( mIn.f[ 4] * mIn.f[10] - mIn.f[ 8] * mIn.f[ 6] ) * (float)det_1;
    294         mDummyMatrix.f[ 5] =   ( mIn.f[ 0] * mIn.f[10] - mIn.f[ 8] * mIn.f[ 2] ) * (float)det_1;
    295         mDummyMatrix.f[ 6] = - ( mIn.f[ 0] * mIn.f[ 6] - mIn.f[ 4] * mIn.f[ 2] ) * (float)det_1;
    296         mDummyMatrix.f[ 8] =   ( mIn.f[ 4] * mIn.f[ 9] - mIn.f[ 8] * mIn.f[ 5] ) * (float)det_1;
    297         mDummyMatrix.f[ 9] = - ( mIn.f[ 0] * mIn.f[ 9] - mIn.f[ 8] * mIn.f[ 1] ) * (float)det_1;
    298         mDummyMatrix.f[10] =   ( mIn.f[ 0] * mIn.f[ 5] - mIn.f[ 4] * mIn.f[ 1] ) * (float)det_1;
    299 
    300         /* Calculate -C * inverse(A) */
    301         mDummyMatrix.f[12] = - ( mIn.f[12] * mDummyMatrix.f[ 0] + mIn.f[13] * mDummyMatrix.f[ 4] + mIn.f[14] * mDummyMatrix.f[ 8] );
    302         mDummyMatrix.f[13] = - ( mIn.f[12] * mDummyMatrix.f[ 1] + mIn.f[13] * mDummyMatrix.f[ 5] + mIn.f[14] * mDummyMatrix.f[ 9] );
    303         mDummyMatrix.f[14] = - ( mIn.f[12] * mDummyMatrix.f[ 2] + mIn.f[13] * mDummyMatrix.f[ 6] + mIn.f[14] * mDummyMatrix.f[10] );
    304 
    305         /* Fill in last row */
    306         mDummyMatrix.f[ 3] = 0.0f;
    307 		mDummyMatrix.f[ 7] = 0.0f;
    308 		mDummyMatrix.f[11] = 0.0f;
    309         mDummyMatrix.f[15] = 1.0f;
    310 	}
    311 
    312    	/* Copy contents of dummy matrix in pfMatrix */
    313 	mOut = mDummyMatrix;
    314 }
    315 
    316 /*!***************************************************************************
    317  @Function			PVRTMatrixInverseExF
    318  @Output			mOut	Inversed matrix
    319  @Input				mIn		Original matrix
    320  @Description		Compute the inverse matrix of mIn.
    321 					Uses a linear equation solver and the knowledge that M.M^-1=I.
    322 					Use this fn to calculate the inverse of matrices that
    323 					PVRTMatrixInverse() cannot.
    324 *****************************************************************************/
    325 void PVRTMatrixInverseExF(
    326 	PVRTMATRIXf			&mOut,
    327 	const PVRTMATRIXf	&mIn)
    328 {
    329 	PVRTMATRIXf		mTmp = {0};
    330 	float 			*ppfRows[4];
    331 	float 			pfRes[4];
    332 	float 			pfIn[20];
    333 	int				i, j;
    334 
    335 	for(i = 0; i < 4; ++i)
    336 		ppfRows[i] = &pfIn[i * 5];
    337 
    338 	/* Solve 4 sets of 4 linear equations */
    339 	for(i = 0; i < 4; ++i)
    340 	{
    341 		for(j = 0; j < 4; ++j)
    342 		{
    343 			ppfRows[j][0] = c_mIdentity.f[i + 4 * j];
    344 			memcpy(&ppfRows[j][1], &mIn.f[j * 4], 4 * sizeof(float));
    345 		}
    346 
    347 		PVRTMatrixLinearEqSolveF(pfRes, (float**)ppfRows, 4);
    348 
    349 		for(j = 0; j < 4; ++j)
    350 		{
    351 			mTmp.f[i + 4 * j] = pfRes[j];
    352 		}
    353 	}
    354 
    355 	mOut = mTmp;
    356 }
    357 
    358 /*!***************************************************************************
    359  @Function			PVRTMatrixLookAtLHF
    360  @Output			mOut	Look-at view matrix
    361  @Input				vEye	Position of the camera
    362  @Input				vAt		Point the camera is looking at
    363  @Input				vUp		Up direction for the camera
    364  @Description		Create a look-at view matrix.
    365 *****************************************************************************/
    366 void PVRTMatrixLookAtLHF(
    367 	PVRTMATRIXf			&mOut,
    368 	const PVRTVECTOR3f	&vEye,
    369 	const PVRTVECTOR3f	&vAt,
    370 	const PVRTVECTOR3f	&vUp)
    371 {
    372 	PVRTVECTOR3f f, s, u;
    373 	PVRTMATRIXf	t;
    374 
    375 	f.x = vEye.x - vAt.x;
    376 	f.y = vEye.y - vAt.y;
    377 	f.z = vEye.z - vAt.z;
    378 
    379 	PVRTMatrixVec3NormalizeF(f, f);
    380 	PVRTMatrixVec3CrossProductF(s, f, vUp);
    381 	PVRTMatrixVec3NormalizeF(s, s);
    382 	PVRTMatrixVec3CrossProductF(u, s, f);
    383 	PVRTMatrixVec3NormalizeF(u, u);
    384 
    385 	mOut.f[ 0] = s.x;
    386 	mOut.f[ 1] = u.x;
    387 	mOut.f[ 2] = -f.x;
    388 	mOut.f[ 3] = 0;
    389 
    390 	mOut.f[ 4] = s.y;
    391 	mOut.f[ 5] = u.y;
    392 	mOut.f[ 6] = -f.y;
    393 	mOut.f[ 7] = 0;
    394 
    395 	mOut.f[ 8] = s.z;
    396 	mOut.f[ 9] = u.z;
    397 	mOut.f[10] = -f.z;
    398 	mOut.f[11] = 0;
    399 
    400 	mOut.f[12] = 0;
    401 	mOut.f[13] = 0;
    402 	mOut.f[14] = 0;
    403 	mOut.f[15] = 1;
    404 
    405 	PVRTMatrixTranslationF(t, -vEye.x, -vEye.y, -vEye.z);
    406 	PVRTMatrixMultiplyF(mOut, t, mOut);
    407 }
    408 
    409 /*!***************************************************************************
    410  @Function			PVRTMatrixLookAtRHF
    411  @Output			mOut	Look-at view matrix
    412  @Input				vEye	Position of the camera
    413  @Input				vAt		Point the camera is looking at
    414  @Input				vUp		Up direction for the camera
    415  @Description		Create a look-at view matrix.
    416 *****************************************************************************/
    417 void PVRTMatrixLookAtRHF(
    418 	PVRTMATRIXf			&mOut,
    419 	const PVRTVECTOR3f	&vEye,
    420 	const PVRTVECTOR3f	&vAt,
    421 	const PVRTVECTOR3f	&vUp)
    422 {
    423 	PVRTVECTOR3f f, s, u;
    424 	PVRTMATRIXf	t;
    425 
    426 	f.x = vAt.x - vEye.x;
    427 	f.y = vAt.y - vEye.y;
    428 	f.z = vAt.z - vEye.z;
    429 
    430 	PVRTMatrixVec3NormalizeF(f, f);
    431 	PVRTMatrixVec3CrossProductF(s, f, vUp);
    432 	PVRTMatrixVec3NormalizeF(s, s);
    433 	PVRTMatrixVec3CrossProductF(u, s, f);
    434 	PVRTMatrixVec3NormalizeF(u, u);
    435 
    436 	mOut.f[ 0] = s.x;
    437 	mOut.f[ 1] = u.x;
    438 	mOut.f[ 2] = -f.x;
    439 	mOut.f[ 3] = 0;
    440 
    441 	mOut.f[ 4] = s.y;
    442 	mOut.f[ 5] = u.y;
    443 	mOut.f[ 6] = -f.y;
    444 	mOut.f[ 7] = 0;
    445 
    446 	mOut.f[ 8] = s.z;
    447 	mOut.f[ 9] = u.z;
    448 	mOut.f[10] = -f.z;
    449 	mOut.f[11] = 0;
    450 
    451 	mOut.f[12] = 0;
    452 	mOut.f[13] = 0;
    453 	mOut.f[14] = 0;
    454 	mOut.f[15] = 1;
    455 
    456 	PVRTMatrixTranslationF(t, -vEye.x, -vEye.y, -vEye.z);
    457 	PVRTMatrixMultiplyF(mOut, t, mOut);
    458 }
    459 
    460 /*!***************************************************************************
    461  @Function		PVRTMatrixPerspectiveFovLHF
    462  @Output		mOut		Perspective matrix
    463  @Input			fFOVy		Field of view
    464  @Input			fAspect		Aspect ratio
    465  @Input			fNear		Near clipping distance
    466  @Input			fFar		Far clipping distance
    467  @Input			bRotate		Should we rotate it ? (for upright screens)
    468  @Description	Create a perspective matrix.
    469 *****************************************************************************/
    470 void PVRTMatrixPerspectiveFovLHF(
    471 	PVRTMATRIXf	&mOut,
    472 	const float	fFOVy,
    473 	const float	fAspect,
    474 	const float	fNear,
    475 	const float	fFar,
    476 	const bool  bRotate)
    477 {
    478 	float f, n, fRealAspect;
    479 
    480 	if (bRotate)
    481 		fRealAspect = 1.0f / fAspect;
    482 	else
    483 		fRealAspect = fAspect;
    484 
    485 	// cotangent(a) == 1.0f / tan(a);
    486 	f = 1.0f / (float)PVRTFTAN(fFOVy * 0.5f);
    487 	n = 1.0f / (fFar - fNear);
    488 
    489 	mOut.f[ 0] = f / fRealAspect;
    490 	mOut.f[ 1] = 0;
    491 	mOut.f[ 2] = 0;
    492 	mOut.f[ 3] = 0;
    493 
    494 	mOut.f[ 4] = 0;
    495 	mOut.f[ 5] = f;
    496 	mOut.f[ 6] = 0;
    497 	mOut.f[ 7] = 0;
    498 
    499 	mOut.f[ 8] = 0;
    500 	mOut.f[ 9] = 0;
    501 	mOut.f[10] = fFar * n;
    502 	mOut.f[11] = 1;
    503 
    504 	mOut.f[12] = 0;
    505 	mOut.f[13] = 0;
    506 	mOut.f[14] = -fFar * fNear * n;
    507 	mOut.f[15] = 0;
    508 
    509 	if (bRotate)
    510 	{
    511 		PVRTMATRIXf mRotation, mTemp = mOut;
    512 		PVRTMatrixRotationZF(mRotation, 90.0f*PVRT_PIf/180.0f);
    513 		PVRTMatrixMultiplyF(mOut, mTemp, mRotation);
    514 	}
    515 }
    516 
    517 /*!***************************************************************************
    518  @Function		PVRTMatrixPerspectiveFovRHF
    519  @Output		mOut		Perspective matrix
    520  @Input			fFOVy		Field of view
    521  @Input			fAspect		Aspect ratio
    522  @Input			fNear		Near clipping distance
    523  @Input			fFar		Far clipping distance
    524  @Input			bRotate		Should we rotate it ? (for upright screens)
    525  @Description	Create a perspective matrix.
    526 *****************************************************************************/
    527 void PVRTMatrixPerspectiveFovRHF(
    528 	PVRTMATRIXf	&mOut,
    529 	const float	fFOVy,
    530 	const float	fAspect,
    531 	const float	fNear,
    532 	const float	fFar,
    533 	const bool  bRotate)
    534 {
    535 	float f, n, fRealAspect;
    536 
    537 	if (bRotate)
    538 		fRealAspect = 1.0f / fAspect;
    539 	else
    540 		fRealAspect = fAspect;
    541 
    542 	// cotangent(a) == 1.0f / tan(a);
    543 	f = 1.0f / (float)PVRTFTAN(fFOVy * 0.5f);
    544 	n = 1.0f / (fNear - fFar);
    545 
    546 	mOut.f[ 0] = f / fRealAspect;
    547 	mOut.f[ 1] = 0;
    548 	mOut.f[ 2] = 0;
    549 	mOut.f[ 3] = 0;
    550 
    551 	mOut.f[ 4] = 0;
    552 	mOut.f[ 5] = f;
    553 	mOut.f[ 6] = 0;
    554 	mOut.f[ 7] = 0;
    555 
    556 	mOut.f[ 8] = 0;
    557 	mOut.f[ 9] = 0;
    558 	mOut.f[10] = (fFar + fNear) * n;
    559 	mOut.f[11] = -1;
    560 
    561 	mOut.f[12] = 0;
    562 	mOut.f[13] = 0;
    563 	mOut.f[14] = (2 * fFar * fNear) * n;
    564 	mOut.f[15] = 0;
    565 
    566 	if (bRotate)
    567 	{
    568 		PVRTMATRIXf mRotation, mTemp = mOut;
    569 		PVRTMatrixRotationZF(mRotation, -90.0f*PVRT_PIf/180.0f);
    570 		PVRTMatrixMultiplyF(mOut, mTemp, mRotation);
    571 	}
    572 }
    573 
    574 /*!***************************************************************************
    575  @Function		PVRTMatrixOrthoLHF
    576  @Output		mOut		Orthographic matrix
    577  @Input			w			Width of the screen
    578  @Input			h			Height of the screen
    579  @Input			zn			Near clipping distance
    580  @Input			zf			Far clipping distance
    581  @Input			bRotate		Should we rotate it ? (for upright screens)
    582  @Description	Create an orthographic matrix.
    583 *****************************************************************************/
    584 void PVRTMatrixOrthoLHF(
    585 	PVRTMATRIXf	&mOut,
    586 	const float w,
    587 	const float h,
    588 	const float zn,
    589 	const float zf,
    590 	const bool  bRotate)
    591 {
    592 	mOut.f[ 0] = 2 / w;
    593 	mOut.f[ 1] = 0;
    594 	mOut.f[ 2] = 0;
    595 	mOut.f[ 3] = 0;
    596 
    597 	mOut.f[ 4] = 0;
    598 	mOut.f[ 5] = 2 / h;
    599 	mOut.f[ 6] = 0;
    600 	mOut.f[ 7] = 0;
    601 
    602 	mOut.f[ 8] = 0;
    603 	mOut.f[ 9] = 0;
    604 	mOut.f[10] = 1 / (zf - zn);
    605 	mOut.f[11] = zn / (zn - zf);
    606 
    607 	mOut.f[12] = 0;
    608 	mOut.f[13] = 0;
    609 	mOut.f[14] = 0;
    610 	mOut.f[15] = 1;
    611 
    612 	if (bRotate)
    613 	{
    614 		PVRTMATRIXf mRotation, mTemp = mOut;
    615 		PVRTMatrixRotationZF(mRotation, -90.0f*PVRT_PIf/180.0f);
    616 		PVRTMatrixMultiplyF(mOut, mRotation, mTemp);
    617 	}
    618 }
    619 
    620 /*!***************************************************************************
    621  @Function		PVRTMatrixOrthoRHF
    622  @Output		mOut		Orthographic matrix
    623  @Input			w			Width of the screen
    624  @Input			h			Height of the screen
    625  @Input			zn			Near clipping distance
    626  @Input			zf			Far clipping distance
    627  @Input			bRotate		Should we rotate it ? (for upright screens)
    628  @Description	Create an orthographic matrix.
    629 *****************************************************************************/
    630 void PVRTMatrixOrthoRHF(
    631 	PVRTMATRIXf	&mOut,
    632 	const float w,
    633 	const float h,
    634 	const float zn,
    635 	const float zf,
    636 	const bool  bRotate)
    637 {
    638 	mOut.f[ 0] = 2 / w;
    639 	mOut.f[ 1] = 0;
    640 	mOut.f[ 2] = 0;
    641 	mOut.f[ 3] = 0;
    642 
    643 	mOut.f[ 4] = 0;
    644 	mOut.f[ 5] = 2 / h;
    645 	mOut.f[ 6] = 0;
    646 	mOut.f[ 7] = 0;
    647 
    648 	mOut.f[ 8] = 0;
    649 	mOut.f[ 9] = 0;
    650 	mOut.f[10] = 1 / (zn - zf);
    651 	mOut.f[11] = zn / (zn - zf);
    652 
    653 	mOut.f[12] = 0;
    654 	mOut.f[13] = 0;
    655 	mOut.f[14] = 0;
    656 	mOut.f[15] = 1;
    657 
    658 	if (bRotate)
    659 	{
    660 		PVRTMATRIXf mRotation, mTemp = mOut;
    661 		PVRTMatrixRotationZF(mRotation, -90.0f*PVRT_PIf/180.0f);
    662 		PVRTMatrixMultiplyF(mOut, mRotation, mTemp);
    663 	}
    664 }
    665 
    666 /*!***************************************************************************
    667  @Function			PVRTMatrixVec3LerpF
    668  @Output			vOut	Result of the interpolation
    669  @Input				v1		First vector to interpolate from
    670  @Input				v2		Second vector to interpolate form
    671  @Input				s		Coefficient of interpolation
    672  @Description		This function performs the linear interpolation based on
    673 					the following formula: V1 + s(V2-V1).
    674 *****************************************************************************/
    675 void PVRTMatrixVec3LerpF(
    676 	PVRTVECTOR3f		&vOut,
    677 	const PVRTVECTOR3f	&v1,
    678 	const PVRTVECTOR3f	&v2,
    679 	const float	s)
    680 {
    681 	vOut.x = v1.x + s * (v2.x - v1.x);
    682 	vOut.y = v1.y + s * (v2.y - v1.y);
    683 	vOut.z = v1.z + s * (v2.z - v1.z);
    684 }
    685 
    686 /*!***************************************************************************
    687  @Function			PVRTMatrixVec3DotProductF
    688  @Input				v1		First vector
    689  @Input				v2		Second vector
    690  @Return			Dot product of the two vectors.
    691  @Description		This function performs the dot product of the two
    692 					supplied vectors.
    693 *****************************************************************************/
    694 float PVRTMatrixVec3DotProductF(
    695 	const PVRTVECTOR3f	&v1,
    696 	const PVRTVECTOR3f	&v2)
    697 {
    698 	return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
    699 }
    700 
    701 /*!***************************************************************************
    702  @Function			PVRTMatrixVec3CrossProductF
    703  @Output			vOut	Cross product of the two vectors
    704  @Input				v1		First vector
    705  @Input				v2		Second vector
    706  @Description		This function performs the cross product of the two
    707 					supplied vectors.
    708 *****************************************************************************/
    709 void PVRTMatrixVec3CrossProductF(
    710 	PVRTVECTOR3f		&vOut,
    711 	const PVRTVECTOR3f	&v1,
    712 	const PVRTVECTOR3f	&v2)
    713 {
    714     PVRTVECTOR3f result;
    715 
    716 	/* Perform calculation on a dummy VECTOR (result) */
    717     result.x = v1.y * v2.z - v1.z * v2.y;
    718     result.y = v1.z * v2.x - v1.x * v2.z;
    719     result.z = v1.x * v2.y - v1.y * v2.x;
    720 
    721 	/* Copy result in pOut */
    722 	vOut = result;
    723 }
    724 
    725 /*!***************************************************************************
    726  @Function			PVRTMatrixVec3NormalizeF
    727  @Output			vOut	Normalized vector
    728  @Input				vIn		Vector to normalize
    729  @Description		Normalizes the supplied vector.
    730 *****************************************************************************/
    731 void PVRTMatrixVec3NormalizeF(
    732 	PVRTVECTOR3f		&vOut,
    733 	const PVRTVECTOR3f	&vIn)
    734 {
    735 	float	f;
    736 	double temp;
    737 
    738 	temp = (double)(vIn.x * vIn.x + vIn.y * vIn.y + vIn.z * vIn.z);
    739 	temp = 1.0 / sqrt(temp);
    740 	f = (float)temp;
    741 
    742 	vOut.x = vIn.x * f;
    743 	vOut.y = vIn.y * f;
    744 	vOut.z = vIn.z * f;
    745 }
    746 
    747 /*!***************************************************************************
    748  @Function			PVRTMatrixVec3LengthF
    749  @Input				vIn		Vector to get the length of
    750  @Return			The length of the vector
    751   @Description		Gets the length of the supplied vector.
    752 *****************************************************************************/
    753 float PVRTMatrixVec3LengthF(
    754 	const PVRTVECTOR3f	&vIn)
    755 {
    756 	double temp;
    757 
    758 	temp = (double)(vIn.x * vIn.x + vIn.y * vIn.y + vIn.z * vIn.z);
    759 	return (float) sqrt(temp);
    760 }
    761 
    762 /*!***************************************************************************
    763  @Function			PVRTMatrixLinearEqSolveF
    764  @Input				pSrc	2D array of floats. 4 Eq linear problem is 5x4
    765 							matrix, constants in first column
    766  @Input				nCnt	Number of equations to solve
    767  @Output			pRes	Result
    768  @Description		Solves 'nCnt' simultaneous equations of 'nCnt' variables.
    769 					pRes should be an array large enough to contain the
    770 					results: the values of the 'nCnt' variables.
    771 					This fn recursively uses Gaussian Elimination.
    772 *****************************************************************************/
    773 void PVRTMatrixLinearEqSolveF(
    774 	float		* const pRes,
    775 	float		** const pSrc,	// 2D array of floats. 4 Eq linear problem is 5x4 matrix, constants in first column.
    776 	const int	nCnt)
    777 {
    778 	int		i, j, k;
    779 	float	f;
    780 
    781 #if 0
    782 	/*
    783 		Show the matrix in debug output
    784 	*/
    785 	_RPT1(_CRT_WARN, "LinearEqSolve(%d)\n", nCnt);
    786 	for(i = 0; i < nCnt; ++i)
    787 	{
    788 		_RPT1(_CRT_WARN, "%.8f |", pSrc[i][0]);
    789 		for(j = 1; j <= nCnt; ++j)
    790 			_RPT1(_CRT_WARN, " %.8f", pSrc[i][j]);
    791 		_RPT0(_CRT_WARN, "\n");
    792 	}
    793 #endif
    794 
    795 	if(nCnt == 1)
    796 	{
    797 		_ASSERT(pSrc[0][1] != 0);
    798 		pRes[0] = pSrc[0][0] / pSrc[0][1];
    799 		return;
    800 	}
    801 
    802 	// Loop backwards in an attempt avoid the need to swap rows
    803 	i = nCnt;
    804 	while(i)
    805 	{
    806 		--i;
    807 
    808 		if(pSrc[i][nCnt] != 0)
    809 		{
    810 			// Row i can be used to zero the other rows; let's move it to the bottom
    811 			if(i != (nCnt-1))
    812 			{
    813 				for(j = 0; j <= nCnt; ++j)
    814 				{
    815 					// Swap the two values
    816 					f = pSrc[nCnt-1][j];
    817 					pSrc[nCnt-1][j] = pSrc[i][j];
    818 					pSrc[i][j] = f;
    819 				}
    820 			}
    821 
    822 			// Now zero the last columns of the top rows
    823 			for(j = 0; j < (nCnt-1); ++j)
    824 			{
    825 				_ASSERT(pSrc[nCnt-1][nCnt] != 0);
    826 				f = pSrc[j][nCnt] / pSrc[nCnt-1][nCnt];
    827 
    828 				// No need to actually calculate a zero for the final column
    829 				for(k = 0; k < nCnt; ++k)
    830 				{
    831 					pSrc[j][k] -= f * pSrc[nCnt-1][k];
    832 				}
    833 			}
    834 
    835 			break;
    836 		}
    837 	}
    838 
    839 	// Solve the top-left sub matrix
    840 	PVRTMatrixLinearEqSolveF(pRes, pSrc, nCnt - 1);
    841 
    842 	// Now calc the solution for the bottom row
    843 	f = pSrc[nCnt-1][0];
    844 	for(k = 1; k < nCnt; ++k)
    845 	{
    846 		f -= pSrc[nCnt-1][k] * pRes[k-1];
    847 	}
    848 	_ASSERT(pSrc[nCnt-1][nCnt] != 0);
    849 	f /= pSrc[nCnt-1][nCnt];
    850 	pRes[nCnt-1] = f;
    851 
    852 #if 0
    853 	{
    854 		float fCnt;
    855 
    856 		/*
    857 			Verify that the result is correct
    858 		*/
    859 		fCnt = 0;
    860 		for(i = 1; i <= nCnt; ++i)
    861 			fCnt += pSrc[nCnt-1][i] * pRes[i-1];
    862 
    863 		_ASSERT(abs(fCnt - pSrc[nCnt-1][0]) < 1e-3);
    864 	}
    865 #endif
    866 }
    867 
    868 /*****************************************************************************
    869  End of file (PVRTMatrixF.cpp)
    870 *****************************************************************************/
    871 
    872