PVRTTrans.cpp 15 KB

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