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