Home | History | Annotate | Download | only in Tools
      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