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