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