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