• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *****************************************************************************/
PVRTBoundingBoxCompute(PVRTBOUNDINGBOX * const pBoundingBox,const PVRTVECTOR3 * const pV,const int nNumberOfVertices)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 *****************************************************************************/
PVRTBoundingBoxComputeInterleaved(PVRTBOUNDINGBOX * const pBoundingBox,const unsigned char * const pV,const int nNumberOfVertices,const int i32Offset,const int i32Stride)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 *****************************************************************************/
PVRTBoundingBoxIsVisible(const PVRTBOUNDINGBOX * const pBoundingBox,const PVRTMATRIX * const pMatrix,bool * const pNeedsZClipping)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 *****************************************************************************/
PVRTTransformVec3Array(PVRTVECTOR4 * const pOut,const int nOutStride,const PVRTVECTOR3 * const pV,const int nInStride,const PVRTMATRIX * const pMatrix,const int nNumberOfVertices)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 *****************************************************************************/
PVRTTransformArray(PVRTVECTOR3 * const pTransformedVertex,const PVRTVECTOR3 * const pV,const int nNumberOfVertices,const PVRTMATRIX * const pMatrix,const VERTTYPE fW)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 *****************************************************************************/
PVRTTransformArrayBack(PVRTVECTOR3 * const pTransformedVertex,const PVRTVECTOR3 * const pVertex,const int nNumberOfVertices,const PVRTMATRIX * const pMatrix)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 *****************************************************************************/
PVRTTransformBack(PVRTVECTOR4 * const pOut,const PVRTVECTOR4 * const pV,const PVRTMATRIX * const pM)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 *****************************************************************************/
PVRTTransform(PVRTVECTOR4 * const pOut,const PVRTVECTOR4 * const pV,const PVRTMATRIX * const pM)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