• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *****************************************************************************/
PVRTMatrixIdentityF(PVRTMATRIXf & mOut)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 *****************************************************************************/
PVRTMatrixMultiplyF(PVRTMATRIXf & mOut,const PVRTMATRIXf & mA,const PVRTMATRIXf & mB)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 *****************************************************************************/
PVRTMatrixTranslationF(PVRTMATRIXf & mOut,const float fX,const float fY,const float fZ)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 *****************************************************************************/
PVRTMatrixScalingF(PVRTMATRIXf & mOut,const float fX,const float fY,const float fZ)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 *****************************************************************************/
PVRTMatrixRotationXF(PVRTMATRIXf & mOut,const float fAngle)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 *****************************************************************************/
PVRTMatrixRotationYF(PVRTMATRIXf & mOut,const float fAngle)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 *****************************************************************************/
PVRTMatrixRotationZF(PVRTMATRIXf & mOut,const float fAngle)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 *****************************************************************************/
PVRTMatrixTransposeF(PVRTMATRIXf & mOut,const PVRTMATRIXf & mIn)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 *****************************************************************************/
PVRTMatrixInverseF(PVRTMATRIXf & mOut,const PVRTMATRIXf & mIn)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 *****************************************************************************/
PVRTMatrixInverseExF(PVRTMATRIXf & mOut,const PVRTMATRIXf & mIn)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 *****************************************************************************/
PVRTMatrixLookAtLHF(PVRTMATRIXf & mOut,const PVRTVECTOR3f & vEye,const PVRTVECTOR3f & vAt,const PVRTVECTOR3f & vUp)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 *****************************************************************************/
PVRTMatrixLookAtRHF(PVRTMATRIXf & mOut,const PVRTVECTOR3f & vEye,const PVRTVECTOR3f & vAt,const PVRTVECTOR3f & vUp)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 *****************************************************************************/
PVRTMatrixPerspectiveFovLHF(PVRTMATRIXf & mOut,const float fFOVy,const float fAspect,const float fNear,const float fFar,const bool bRotate)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 *****************************************************************************/
PVRTMatrixPerspectiveFovRHF(PVRTMATRIXf & mOut,const float fFOVy,const float fAspect,const float fNear,const float fFar,const bool bRotate)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 *****************************************************************************/
PVRTMatrixOrthoLHF(PVRTMATRIXf & mOut,const float w,const float h,const float zn,const float zf,const bool bRotate)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 *****************************************************************************/
PVRTMatrixOrthoRHF(PVRTMATRIXf & mOut,const float w,const float h,const float zn,const float zf,const bool bRotate)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 *****************************************************************************/
PVRTMatrixVec3LerpF(PVRTVECTOR3f & vOut,const PVRTVECTOR3f & v1,const PVRTVECTOR3f & v2,const float s)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 *****************************************************************************/
PVRTMatrixVec3DotProductF(const PVRTVECTOR3f & v1,const PVRTVECTOR3f & v2)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 *****************************************************************************/
PVRTMatrixVec3CrossProductF(PVRTVECTOR3f & vOut,const PVRTVECTOR3f & v1,const PVRTVECTOR3f & v2)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 *****************************************************************************/
PVRTMatrixVec3NormalizeF(PVRTVECTOR3f & vOut,const PVRTVECTOR3f & vIn)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 *****************************************************************************/
PVRTMatrixVec3LengthF(const PVRTVECTOR3f & vIn)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 *****************************************************************************/
PVRTMatrixLinearEqSolveF(float * const pRes,float ** const pSrc,const int nCnt)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