1 /****************************************************************************** 2 3 @File PVRTTrans.cpp 4 5 @Title PVRTTrans 6 7 @Version 8 9 @Copyright Copyright (c) Imagination Technologies Limited. 10 11 @Platform ANSI compatible 12 13 @Description Set of functions used for 3D transformations and projections. 14 15 ******************************************************************************/ 16 #include <string.h> 17 18 #include "PVRTGlobal.h" 19 #include "PVRTFixedPoint.h" 20 #include "PVRTMatrix.h" 21 #include "PVRTTrans.h" 22 23 /**************************************************************************** 24 ** Functions 25 ****************************************************************************/ 26 27 /*!*************************************************************************** 28 @Function PVRTBoundingBoxCompute 29 @Output pBoundingBox 30 @Input pV 31 @Input nNumberOfVertices 32 @Description Calculate the eight vertices that surround an object. 33 This "bounding box" is used later to determine whether 34 the object is visible or not. 35 This function should only be called once to determine the 36 object's bounding box. 37 *****************************************************************************/ 38 void PVRTBoundingBoxCompute( 39 PVRTBOUNDINGBOX * const pBoundingBox, 40 const PVRTVECTOR3 * const pV, 41 const int nNumberOfVertices) 42 { 43 int i; 44 VERTTYPE MinX, MaxX, MinY, MaxY, MinZ, MaxZ; 45 46 /* Inialise values to first vertex */ 47 MinX=pV->x; MaxX=pV->x; 48 MinY=pV->y; MaxY=pV->y; 49 MinZ=pV->z; MaxZ=pV->z; 50 51 /* Loop through all vertices to find extremas */ 52 for (i=1; i<nNumberOfVertices; i++) 53 { 54 /* Minimum and Maximum X */ 55 if (pV[i].x < MinX) MinX = pV[i].x; 56 if (pV[i].x > MaxX) MaxX = pV[i].x; 57 58 /* Minimum and Maximum Y */ 59 if (pV[i].y < MinY) MinY = pV[i].y; 60 if (pV[i].y > MaxY) MaxY = pV[i].y; 61 62 /* Minimum and Maximum Z */ 63 if (pV[i].z < MinZ) MinZ = pV[i].z; 64 if (pV[i].z > MaxZ) MaxZ = pV[i].z; 65 } 66 67 /* Assign the resulting extremas to the bounding box structure */ 68 /* Point 0 */ 69 pBoundingBox->Point[0].x=MinX; 70 pBoundingBox->Point[0].y=MinY; 71 pBoundingBox->Point[0].z=MinZ; 72 73 /* Point 1 */ 74 pBoundingBox->Point[1].x=MinX; 75 pBoundingBox->Point[1].y=MinY; 76 pBoundingBox->Point[1].z=MaxZ; 77 78 /* Point 2 */ 79 pBoundingBox->Point[2].x=MinX; 80 pBoundingBox->Point[2].y=MaxY; 81 pBoundingBox->Point[2].z=MinZ; 82 83 /* Point 3 */ 84 pBoundingBox->Point[3].x=MinX; 85 pBoundingBox->Point[3].y=MaxY; 86 pBoundingBox->Point[3].z=MaxZ; 87 88 /* Point 4 */ 89 pBoundingBox->Point[4].x=MaxX; 90 pBoundingBox->Point[4].y=MinY; 91 pBoundingBox->Point[4].z=MinZ; 92 93 /* Point 5 */ 94 pBoundingBox->Point[5].x=MaxX; 95 pBoundingBox->Point[5].y=MinY; 96 pBoundingBox->Point[5].z=MaxZ; 97 98 /* Point 6 */ 99 pBoundingBox->Point[6].x=MaxX; 100 pBoundingBox->Point[6].y=MaxY; 101 pBoundingBox->Point[6].z=MinZ; 102 103 /* Point 7 */ 104 pBoundingBox->Point[7].x=MaxX; 105 pBoundingBox->Point[7].y=MaxY; 106 pBoundingBox->Point[7].z=MaxZ; 107 } 108 109 /*!*************************************************************************** 110 @Function PVRTBoundingBoxComputeInterleaved 111 @Output pBoundingBox 112 @Input pV 113 @Input nNumberOfVertices 114 @Input i32Offset 115 @Input i32Stride 116 @Description Calculate the eight vertices that surround an object. 117 This "bounding box" is used later to determine whether 118 the object is visible or not. 119 This function should only be called once to determine the 120 object's bounding box. 121 Takes interleaved data using the first vertex's offset 122 and the stride to the next vertex thereafter 123 *****************************************************************************/ 124 void PVRTBoundingBoxComputeInterleaved( 125 PVRTBOUNDINGBOX * const pBoundingBox, 126 const unsigned char * const pV, 127 const int nNumberOfVertices, 128 const int i32Offset, 129 const int i32Stride) 130 { 131 int i; 132 VERTTYPE MinX, MaxX, MinY, MaxY, MinZ, MaxZ; 133 134 // point ot first vertex 135 PVRTVECTOR3 *pVertex =(PVRTVECTOR3*)(pV+i32Offset); 136 137 /* Inialise values to first vertex */ 138 MinX=pVertex->x; MaxX=pVertex->x; 139 MinY=pVertex->y; MaxY=pVertex->y; 140 MinZ=pVertex->z; MaxZ=pVertex->z; 141 142 /* Loop through all vertices to find extremas */ 143 for (i=1; i<nNumberOfVertices; i++) 144 { 145 pVertex = (PVRTVECTOR3*)( (unsigned char*)(pVertex)+i32Stride); 146 147 /* Minimum and Maximum X */ 148 if (pVertex->x < MinX) MinX = pVertex->x; 149 if (pVertex->x > MaxX) MaxX = pVertex->x; 150 151 /* Minimum and Maximum Y */ 152 if (pVertex->y < MinY) MinY = pVertex->y; 153 if (pVertex->y > MaxY) MaxY = pVertex->y; 154 155 /* Minimum and Maximum Z */ 156 if (pVertex->z < MinZ) MinZ = pVertex->z; 157 if (pVertex->z > MaxZ) MaxZ = pVertex->z; 158 } 159 160 /* Assign the resulting extremas to the bounding box structure */ 161 /* Point 0 */ 162 pBoundingBox->Point[0].x=MinX; 163 pBoundingBox->Point[0].y=MinY; 164 pBoundingBox->Point[0].z=MinZ; 165 166 /* Point 1 */ 167 pBoundingBox->Point[1].x=MinX; 168 pBoundingBox->Point[1].y=MinY; 169 pBoundingBox->Point[1].z=MaxZ; 170 171 /* Point 2 */ 172 pBoundingBox->Point[2].x=MinX; 173 pBoundingBox->Point[2].y=MaxY; 174 pBoundingBox->Point[2].z=MinZ; 175 176 /* Point 3 */ 177 pBoundingBox->Point[3].x=MinX; 178 pBoundingBox->Point[3].y=MaxY; 179 pBoundingBox->Point[3].z=MaxZ; 180 181 /* Point 4 */ 182 pBoundingBox->Point[4].x=MaxX; 183 pBoundingBox->Point[4].y=MinY; 184 pBoundingBox->Point[4].z=MinZ; 185 186 /* Point 5 */ 187 pBoundingBox->Point[5].x=MaxX; 188 pBoundingBox->Point[5].y=MinY; 189 pBoundingBox->Point[5].z=MaxZ; 190 191 /* Point 6 */ 192 pBoundingBox->Point[6].x=MaxX; 193 pBoundingBox->Point[6].y=MaxY; 194 pBoundingBox->Point[6].z=MinZ; 195 196 /* Point 7 */ 197 pBoundingBox->Point[7].x=MaxX; 198 pBoundingBox->Point[7].y=MaxY; 199 pBoundingBox->Point[7].z=MaxZ; 200 } 201 202 /*!****************************************************************************** 203 @Function PVRTBoundingBoxIsVisible 204 @Output pNeedsZClipping 205 @Input pBoundingBox 206 @Input pMatrix 207 @Return TRUE if the object is visible, FALSE if not. 208 @Description Determine if a bounding box is "visible" or not along the 209 Z axis. 210 If the function returns TRUE, the object is visible and should 211 be displayed (check bNeedsZClipping to know if Z Clipping needs 212 to be done). 213 If the function returns FALSE, the object is not visible and thus 214 does not require to be displayed. 215 bNeedsZClipping indicates whether the object needs Z Clipping 216 (i.e. the object is partially visible). 217 - *pBoundingBox is a pointer to the bounding box structure. 218 - *pMatrix is the World, View & Projection matrices combined. 219 - *bNeedsZClipping is TRUE if Z clipping is required. 220 *****************************************************************************/ 221 bool PVRTBoundingBoxIsVisible( 222 const PVRTBOUNDINGBOX * const pBoundingBox, 223 const PVRTMATRIX * const pMatrix, 224 bool * const pNeedsZClipping) 225 { 226 VERTTYPE fX, fY, fZ, fW; 227 int i, nX0, nX1, nY0, nY1, nZ; 228 229 nX0 = 8; 230 nX1 = 8; 231 nY0 = 8; 232 nY1 = 8; 233 nZ = 8; 234 235 /* Transform the eight bounding box vertices */ 236 i = 8; 237 while(i) 238 { 239 i--; 240 fX = pMatrix->f[ 0]*pBoundingBox->Point[i].x + 241 pMatrix->f[ 4]*pBoundingBox->Point[i].y + 242 pMatrix->f[ 8]*pBoundingBox->Point[i].z + 243 pMatrix->f[12]; 244 fY = pMatrix->f[ 1]*pBoundingBox->Point[i].x + 245 pMatrix->f[ 5]*pBoundingBox->Point[i].y + 246 pMatrix->f[ 9]*pBoundingBox->Point[i].z + 247 pMatrix->f[13]; 248 fZ = pMatrix->f[ 2]*pBoundingBox->Point[i].x + 249 pMatrix->f[ 6]*pBoundingBox->Point[i].y + 250 pMatrix->f[10]*pBoundingBox->Point[i].z + 251 pMatrix->f[14]; 252 fW = pMatrix->f[ 3]*pBoundingBox->Point[i].x + 253 pMatrix->f[ 7]*pBoundingBox->Point[i].y + 254 pMatrix->f[11]*pBoundingBox->Point[i].z + 255 pMatrix->f[15]; 256 257 if(fX < -fW) 258 nX0--; 259 else if(fX > fW) 260 nX1--; 261 262 if(fY < -fW) 263 nY0--; 264 else if(fY > fW) 265 nY1--; 266 267 if(fZ < 0) 268 nZ--; 269 } 270 271 if(nZ) 272 { 273 if(!(nX0 * nX1 * nY0 * nY1)) 274 { 275 *pNeedsZClipping = false; 276 return false; 277 } 278 279 if(nZ == 8) 280 { 281 *pNeedsZClipping = false; 282 return true; 283 } 284 285 *pNeedsZClipping = true; 286 return true; 287 } 288 else 289 { 290 *pNeedsZClipping = false; 291 return false; 292 } 293 } 294 295 /*!*************************************************************************** 296 @Function Name PVRTTransformVec3Array 297 @Output pOut Destination for transformed vectors 298 @Input nOutStride Stride between vectors in pOut array 299 @Input pV Input vector array 300 @Input nInStride Stride between vectors in pV array 301 @Input pMatrix Matrix to transform the vectors 302 @Input nNumberOfVertices Number of vectors to transform 303 @Description Transform all vertices [X Y Z 1] in pV by pMatrix and 304 store them in pOut. 305 *****************************************************************************/ 306 void PVRTTransformVec3Array( 307 PVRTVECTOR4 * const pOut, 308 const int nOutStride, 309 const PVRTVECTOR3 * const pV, 310 const int nInStride, 311 const PVRTMATRIX * const pMatrix, 312 const int nNumberOfVertices) 313 { 314 const PVRTVECTOR3 *pSrc; 315 PVRTVECTOR4 *pDst; 316 int i; 317 318 pSrc = pV; 319 pDst = pOut; 320 321 /* Transform all vertices with *pMatrix */ 322 for (i=0; i<nNumberOfVertices; ++i) 323 { 324 pDst->x = VERTTYPEMUL(pMatrix->f[ 0], pSrc->x) + 325 VERTTYPEMUL(pMatrix->f[ 4], pSrc->y) + 326 VERTTYPEMUL(pMatrix->f[ 8], pSrc->z) + 327 pMatrix->f[12]; 328 pDst->y = VERTTYPEMUL(pMatrix->f[ 1], pSrc->x) + 329 VERTTYPEMUL(pMatrix->f[ 5], pSrc->y) + 330 VERTTYPEMUL(pMatrix->f[ 9], pSrc->z) + 331 pMatrix->f[13]; 332 pDst->z = VERTTYPEMUL(pMatrix->f[ 2], pSrc->x) + 333 VERTTYPEMUL(pMatrix->f[ 6], pSrc->y) + 334 VERTTYPEMUL(pMatrix->f[10], pSrc->z) + 335 pMatrix->f[14]; 336 pDst->w = VERTTYPEMUL(pMatrix->f[ 3], pSrc->x) + 337 VERTTYPEMUL(pMatrix->f[ 7], pSrc->y) + 338 VERTTYPEMUL(pMatrix->f[11], pSrc->z) + 339 pMatrix->f[15]; 340 341 pDst = (PVRTVECTOR4*)((char*)pDst + nOutStride); 342 pSrc = (PVRTVECTOR3*)((char*)pSrc + nInStride); 343 } 344 } 345 346 /*!*************************************************************************** 347 @Function PVRTTransformArray 348 @Output pTransformedVertex Destination for transformed vectors 349 @Input pV Input vector array 350 @Input nNumberOfVertices Number of vectors to transform 351 @Input pMatrix Matrix to transform the vectors 352 @Input fW W coordinate of input vector (e.g. use 1 for position, 0 for normal) 353 @Description Transform all vertices in pVertex by pMatrix and store them in 354 pTransformedVertex 355 - pTransformedVertex is the pointer that will receive transformed vertices. 356 - pVertex is the pointer to untransformed object vertices. 357 - nNumberOfVertices is the number of vertices of the object. 358 - pMatrix is the matrix used to transform the object. 359 *****************************************************************************/ 360 void PVRTTransformArray( 361 PVRTVECTOR3 * const pTransformedVertex, 362 const PVRTVECTOR3 * const pV, 363 const int nNumberOfVertices, 364 const PVRTMATRIX * const pMatrix, 365 const VERTTYPE fW) 366 { 367 int i; 368 369 /* Transform all vertices with *pMatrix */ 370 for (i=0; i<nNumberOfVertices; ++i) 371 { 372 pTransformedVertex[i].x = VERTTYPEMUL(pMatrix->f[ 0], pV[i].x) + 373 VERTTYPEMUL(pMatrix->f[ 4], pV[i].y) + 374 VERTTYPEMUL(pMatrix->f[ 8], pV[i].z) + 375 VERTTYPEMUL(pMatrix->f[12], fW); 376 pTransformedVertex[i].y = VERTTYPEMUL(pMatrix->f[ 1], pV[i].x) + 377 VERTTYPEMUL(pMatrix->f[ 5], pV[i].y) + 378 VERTTYPEMUL(pMatrix->f[ 9], pV[i].z) + 379 VERTTYPEMUL(pMatrix->f[13], fW); 380 pTransformedVertex[i].z = VERTTYPEMUL(pMatrix->f[ 2], pV[i].x) + 381 VERTTYPEMUL(pMatrix->f[ 6], pV[i].y) + 382 VERTTYPEMUL(pMatrix->f[10], pV[i].z) + 383 VERTTYPEMUL(pMatrix->f[14], fW); 384 } 385 } 386 387 /*!*************************************************************************** 388 @Function PVRTTransformArrayBack 389 @Output pTransformedVertex 390 @Input pVertex 391 @Input nNumberOfVertices 392 @Input pMatrix 393 @Description Transform all vertices in pVertex by the inverse of pMatrix 394 and store them in pTransformedVertex. 395 - pTransformedVertex is the pointer that will receive transformed vertices. 396 - pVertex is the pointer to untransformed object vertices. 397 - nNumberOfVertices is the number of vertices of the object. 398 - pMatrix is the matrix used to transform the object. 399 *****************************************************************************/ 400 void PVRTTransformArrayBack( 401 PVRTVECTOR3 * const pTransformedVertex, 402 const PVRTVECTOR3 * const pVertex, 403 const int nNumberOfVertices, 404 const PVRTMATRIX * const pMatrix) 405 { 406 PVRTMATRIX mBack; 407 408 PVRTMatrixInverse(mBack, *pMatrix); 409 PVRTTransformArray(pTransformedVertex, pVertex, nNumberOfVertices, &mBack); 410 } 411 412 /*!*************************************************************************** 413 @Function PVRTTransformBack 414 @Output pOut 415 @Input pV 416 @Input pM 417 @Description Transform vertex pV by the inverse of pMatrix 418 and store in pOut. 419 *****************************************************************************/ 420 void PVRTTransformBack( 421 PVRTVECTOR4 * const pOut, 422 const PVRTVECTOR4 * const pV, 423 const PVRTMATRIX * const pM) 424 { 425 VERTTYPE *ppfRows[4]; 426 VERTTYPE pfIn[20]; 427 int i; 428 const PVRTMATRIX *pMa; 429 430 #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3) 431 PVRTMATRIX mT; 432 PVRTMatrixTranspose(mT, *pM); 433 pMa = &mT; 434 #else 435 pMa = pM; 436 #endif 437 438 for(i = 0; i < 4; ++i) 439 { 440 /* 441 Set up the array of pointers to matrix coefficients 442 */ 443 ppfRows[i] = &pfIn[i * 5]; 444 445 /* 446 Copy the 4x4 matrix into RHS of the 5x4 matrix 447 */ 448 memcpy(&ppfRows[i][1], &pMa->f[i * 4], 4 * sizeof(float)); 449 } 450 451 /* 452 Copy the "result" vector into the first column of the 5x4 matrix 453 */ 454 ppfRows[0][0] = pV->x; 455 ppfRows[1][0] = pV->y; 456 ppfRows[2][0] = pV->z; 457 ppfRows[3][0] = pV->w; 458 459 /* 460 Solve a set of 4 linear equations 461 */ 462 PVRTMatrixLinearEqSolve(&pOut->x, ppfRows, 4); 463 } 464 465 /*!*************************************************************************** 466 @Function PVRTTransform 467 @Output pOut 468 @Input pV 469 @Input pM 470 @Description Transform vertex pV by pMatrix and store in pOut. 471 *****************************************************************************/ 472 void PVRTTransform( 473 PVRTVECTOR4 * const pOut, 474 const PVRTVECTOR4 * const pV, 475 const PVRTMATRIX * const pM) 476 { 477 pOut->x = VERTTYPEMUL(pM->f[0], pV->x) + VERTTYPEMUL(pM->f[4], pV->y) + VERTTYPEMUL(pM->f[8], pV->z) + VERTTYPEMUL(pM->f[12], pV->w); 478 pOut->y = VERTTYPEMUL(pM->f[1], pV->x) + VERTTYPEMUL(pM->f[5], pV->y) + VERTTYPEMUL(pM->f[9], pV->z) + VERTTYPEMUL(pM->f[13], pV->w); 479 pOut->z = VERTTYPEMUL(pM->f[2], pV->x) + VERTTYPEMUL(pM->f[6], pV->y) + VERTTYPEMUL(pM->f[10], pV->z) + VERTTYPEMUL(pM->f[14], pV->w); 480 pOut->w = VERTTYPEMUL(pM->f[3], pV->x) + VERTTYPEMUL(pM->f[7], pV->y) + VERTTYPEMUL(pM->f[11], pV->z) + VERTTYPEMUL(pM->f[15], pV->w); 481 } 482 483 /***************************************************************************** 484 End of file (PVRTTrans.cpp) 485 *****************************************************************************/ 486 487