PVRTVertex.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /******************************************************************************
  2. @File PVRTVertex.cpp
  3. @Title PVRTVertex
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform ANSI compatible
  7. @Description Utility functions which process vertices.
  8. ******************************************************************************/
  9. /****************************************************************************
  10. ** Includes
  11. ****************************************************************************/
  12. #include "PVRTGlobal.h"
  13. #include "PVRTContext.h"
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "PVRTFixedPoint.h"
  17. #include "PVRTMatrix.h"
  18. #include "PVRTVertex.h"
  19. /****************************************************************************
  20. ** Defines
  21. ****************************************************************************/
  22. /****************************************************************************
  23. ** Macros
  24. ****************************************************************************/
  25. #define MAX_VERTEX_OUT (3*nVtxNum)
  26. /****************************************************************************
  27. ** Structures
  28. ****************************************************************************/
  29. /****************************************************************************
  30. ** Constants
  31. ****************************************************************************/
  32. /****************************************************************************
  33. ** Local function definitions
  34. ****************************************************************************/
  35. /*****************************************************************************
  36. ** Functions
  37. *****************************************************************************/
  38. /*!***************************************************************************
  39. @Function PVRTVertexRead
  40. @Output pV
  41. @Input pData
  42. @Input eType
  43. @Input nCnt
  44. @Description Read a vector
  45. *****************************************************************************/
  46. void PVRTVertexRead(
  47. PVRTVECTOR4f * const pV,
  48. const void * const pData,
  49. const EPVRTDataType eType,
  50. const int nCnt)
  51. {
  52. int i;
  53. float *pOut = (float*)pV;
  54. pV->x = 0;
  55. pV->y = 0;
  56. pV->z = 0;
  57. pV->w = 1;
  58. switch(eType)
  59. {
  60. default:
  61. _ASSERT(false);
  62. break;
  63. case EPODDataFloat:
  64. for(i = 0; i < nCnt; ++i)
  65. pOut[i] = ((float*)pData)[i];
  66. break;
  67. case EPODDataFixed16_16:
  68. for(i = 0; i < nCnt; ++i)
  69. pOut[i] = ((int*)pData)[i] * 1.0f / (float)(1 << 16);
  70. break;
  71. case EPODDataInt:
  72. for(i = 0; i < nCnt; ++i)
  73. pOut[i] = (float)((int*)pData)[i];
  74. break;
  75. case EPODDataUnsignedInt:
  76. for(i = 0; i < nCnt; ++i)
  77. pOut[i] = (float)((unsigned int*)pData)[i];
  78. break;
  79. case EPODDataByte:
  80. for(i = 0; i < nCnt; ++i)
  81. pOut[i] = (float)((char*)pData)[i];
  82. break;
  83. case EPODDataByteNorm:
  84. for(i = 0; i < nCnt; ++i)
  85. pOut[i] = (float)((char*)pData)[i] / (float)((1 << 7)-1);
  86. break;
  87. case EPODDataUnsignedByte:
  88. for(i = 0; i < nCnt; ++i)
  89. pOut[i] = (float)((unsigned char*)pData)[i];
  90. break;
  91. case EPODDataUnsignedByteNorm:
  92. for(i = 0; i < nCnt; ++i)
  93. pOut[i] = (float)((unsigned char*)pData)[i] / (float)((1 << 8)-1);
  94. break;
  95. case EPODDataShort:
  96. for(i = 0; i < nCnt; ++i)
  97. pOut[i] = (float)((short*)pData)[i];
  98. break;
  99. case EPODDataShortNorm:
  100. for(i = 0; i < nCnt; ++i)
  101. pOut[i] = (float)((short*)pData)[i] / (float)((1 << 15)-1);
  102. break;
  103. case EPODDataUnsignedShort:
  104. for(i = 0; i < nCnt; ++i)
  105. pOut[i] = (float)((unsigned short*)pData)[i];
  106. break;
  107. case EPODDataUnsignedShortNorm:
  108. for(i = 0; i < nCnt; ++i)
  109. pOut[i] = (float)((unsigned short*)pData)[i] / (float)((1 << 16)-1);
  110. break;
  111. case EPODDataRGBA:
  112. {
  113. unsigned int dwVal = *(unsigned int*)pData;
  114. unsigned char v[4];
  115. v[0] = (unsigned char) (dwVal >> 24);
  116. v[1] = (unsigned char) (dwVal >> 16);
  117. v[2] = (unsigned char) (dwVal >> 8);
  118. v[3] = (unsigned char) (dwVal >> 0);
  119. for(i = 0; i < 4; ++i)
  120. pOut[i] = 1.0f / 255.0f * (float)v[i];
  121. }
  122. break;
  123. case EPODDataARGB:
  124. case EPODDataD3DCOLOR:
  125. {
  126. unsigned int dwVal = *(unsigned int*)pData;
  127. unsigned char v[4];
  128. v[0] = (unsigned char) (dwVal >> 16);
  129. v[1] = (unsigned char) (dwVal >> 8);
  130. v[2] = (unsigned char) (dwVal >> 0);
  131. v[3] = (unsigned char) (dwVal >> 24);
  132. for(i = 0; i < 4; ++i)
  133. pOut[i] = 1.0f / 255.0f * (float)v[i];
  134. }
  135. break;
  136. case EPODDataUBYTE4:
  137. {
  138. unsigned int dwVal = *(unsigned int*)pData;
  139. unsigned char v[4];
  140. v[0] = (unsigned char) (dwVal >> 0);
  141. v[1] = (unsigned char) (dwVal >> 8);
  142. v[2] = (unsigned char) (dwVal >> 16);
  143. v[3] = (unsigned char) (dwVal >> 24);
  144. for(i = 0; i < 4; ++i)
  145. pOut[i] = v[i];
  146. }
  147. break;
  148. case EPODDataDEC3N:
  149. {
  150. int dwVal = *(int*)pData;
  151. int v[4];
  152. v[0] = (dwVal << 22) >> 22;
  153. v[1] = (dwVal << 12) >> 22;
  154. v[2] = (dwVal << 2) >> 22;
  155. v[3] = 0;
  156. for(i = 0; i < 3; ++i)
  157. pOut[i] = (float)v[i] * (1.0f / 511.0f);
  158. }
  159. break;
  160. }
  161. }
  162. /*!***************************************************************************
  163. @Function PVRTVertexRead
  164. @Output pV
  165. @Input pData
  166. @Input eType
  167. @Description Read an int
  168. *****************************************************************************/
  169. void PVRTVertexRead(
  170. unsigned int * const pV,
  171. const void * const pData,
  172. const EPVRTDataType eType)
  173. {
  174. switch(eType)
  175. {
  176. default:
  177. _ASSERT(false);
  178. break;
  179. case EPODDataUnsignedShort:
  180. *pV = *(unsigned short*)pData;
  181. break;
  182. case EPODDataUnsignedInt:
  183. *pV = *(unsigned int*)pData;
  184. break;
  185. }
  186. }
  187. /*!***************************************************************************
  188. @Function PVRTVertexWrite
  189. @Output pOut
  190. @Input eType
  191. @Input nCnt
  192. @Input pV
  193. @Description Write a vector
  194. *****************************************************************************/
  195. void PVRTVertexWrite(
  196. void * const pOut,
  197. const EPVRTDataType eType,
  198. const int nCnt,
  199. const PVRTVECTOR4f * const pV)
  200. {
  201. int i;
  202. float *pData = (float*)pV;
  203. switch(eType)
  204. {
  205. default:
  206. _ASSERT(false);
  207. break;
  208. case EPODDataDEC3N:
  209. {
  210. int v[3];
  211. for(i = 0; i < nCnt; ++i)
  212. {
  213. v[i] = (int)(pData[i] * 511.0f);
  214. v[i] = PVRT_CLAMP(v[i], -511, 511);
  215. v[i] &= 0x000003ff;
  216. }
  217. for(; i < 3; ++i)
  218. {
  219. v[i] = 0;
  220. }
  221. *(unsigned int*)pOut = (v[0] << 0) | (v[1] << 10) | (v[2] << 20);
  222. }
  223. break;
  224. case EPODDataARGB:
  225. case EPODDataD3DCOLOR:
  226. {
  227. unsigned char v[4];
  228. for(i = 0; i < nCnt; ++i)
  229. v[i] = (unsigned char)PVRT_CLAMP(pData[i] * 255.0f, 0.0f, 255.0f);
  230. for(; i < 4; ++i)
  231. v[i] = 0;
  232. *(unsigned int*)pOut = (v[3] << 24) | (v[0] << 16) | (v[1] << 8) | v[2];
  233. }
  234. break;
  235. case EPODDataRGBA:
  236. {
  237. unsigned char v[4];
  238. for(i = 0; i < nCnt; ++i)
  239. v[i] = (unsigned char)PVRT_CLAMP(pData[i] * 255.0f, 0.0f, 255.0f);
  240. for(; i < 4; ++i)
  241. v[i] = 0;
  242. *(unsigned int*)pOut = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
  243. }
  244. break;
  245. case EPODDataUBYTE4:
  246. {
  247. unsigned char v[4];
  248. for(i = 0; i < nCnt; ++i)
  249. v[i] = (unsigned char)PVRT_CLAMP(pData[i], 0.0f, 255.0f);
  250. for(; i < 4; ++i)
  251. v[i] = 0;
  252. *(unsigned int*)pOut = (v[3] << 24) | (v[2] << 16) | (v[1] << 8) | v[0];
  253. }
  254. break;
  255. case EPODDataFloat:
  256. for(i = 0; i < nCnt; ++i)
  257. ((float*)pOut)[i] = pData[i];
  258. break;
  259. case EPODDataFixed16_16:
  260. for(i = 0; i < nCnt; ++i)
  261. ((int*)pOut)[i] = (int)(pData[i] * (float)(1 << 16));
  262. break;
  263. case EPODDataInt:
  264. for(i = 0; i < nCnt; ++i)
  265. ((int*)pOut)[i] = (int)pData[i];
  266. break;
  267. case EPODDataUnsignedInt:
  268. for(i = 0; i < nCnt; ++i)
  269. ((unsigned int*)pOut)[i] = (unsigned int)pData[i];
  270. break;
  271. case EPODDataByte:
  272. for(i = 0; i < nCnt; ++i)
  273. ((char*)pOut)[i] = (char)pData[i];
  274. break;
  275. case EPODDataByteNorm:
  276. for(i = 0; i < nCnt; ++i)
  277. ((char*)pOut)[i] = (char)(pData[i] * (float)((1 << 7)-1));
  278. break;
  279. case EPODDataUnsignedByte:
  280. for(i = 0; i < nCnt; ++i)
  281. ((unsigned char*)pOut)[i] = (unsigned char)pData[i];
  282. break;
  283. case EPODDataUnsignedByteNorm:
  284. for(i = 0; i < nCnt; ++i)
  285. ((char*)pOut)[i] = (unsigned char)(pData[i] * (float)((1 << 8)-1));
  286. break;
  287. case EPODDataShort:
  288. for(i = 0; i < nCnt; ++i)
  289. ((short*)pOut)[i] = (short)pData[i];
  290. break;
  291. case EPODDataShortNorm:
  292. for(i = 0; i < nCnt; ++i)
  293. ((short*)pOut)[i] = (short)(pData[i] * (float)((1 << 15)-1));
  294. break;
  295. case EPODDataUnsignedShort:
  296. for(i = 0; i < nCnt; ++i)
  297. ((unsigned short*)pOut)[i] = (unsigned short)pData[i];
  298. break;
  299. case EPODDataUnsignedShortNorm:
  300. for(i = 0; i < nCnt; ++i)
  301. ((unsigned short*)pOut)[i] = (unsigned short)(pData[i] * (float)((1 << 16)-1));
  302. break;
  303. }
  304. }
  305. /*!***************************************************************************
  306. @Function PVRTVertexWrite
  307. @Output pOut
  308. @Input eType
  309. @Input V
  310. @Description Write an int
  311. *****************************************************************************/
  312. void PVRTVertexWrite(
  313. void * const pOut,
  314. const EPVRTDataType eType,
  315. const unsigned int V)
  316. {
  317. switch(eType)
  318. {
  319. default:
  320. _ASSERT(false);
  321. break;
  322. case EPODDataUnsignedShort:
  323. *(unsigned short*)pOut = (unsigned short) V;
  324. break;
  325. case EPODDataUnsignedInt:
  326. *(unsigned int*)pOut = V;
  327. break;
  328. }
  329. }
  330. /*!***************************************************************************
  331. @Function PVRTVertexTangentBitangent
  332. @Output pvTan
  333. @Output pvBin
  334. @Input pvNor
  335. @Input pfPosA
  336. @Input pfPosB
  337. @Input pfPosC
  338. @Input pfTexA
  339. @Input pfTexB
  340. @Input pfTexC
  341. @Description Calculates the tangent and bitangent vectors for
  342. vertex 'A' of the triangle defined by the 3 supplied
  343. 3D position coordinates (pfPosA) and 2D texture
  344. coordinates (pfTexA).
  345. *****************************************************************************/
  346. void PVRTVertexTangentBitangent(
  347. PVRTVECTOR3f * const pvTan,
  348. PVRTVECTOR3f * const pvBin,
  349. const PVRTVECTOR3f * const pvNor,
  350. const float * const pfPosA,
  351. const float * const pfPosB,
  352. const float * const pfPosC,
  353. const float * const pfTexA,
  354. const float * const pfTexB,
  355. const float * const pfTexC)
  356. {
  357. PVRTVECTOR3f BaseVector1, BaseVector2, AlignedVector;
  358. if(PVRTMatrixVec3DotProductF(*pvNor, *pvNor) == 0)
  359. {
  360. pvTan->x = 0;
  361. pvTan->y = 0;
  362. pvTan->z = 0;
  363. pvBin->x = 0;
  364. pvBin->y = 0;
  365. pvBin->z = 0;
  366. return;
  367. }
  368. /* BaseVectors are A-B and A-C. */
  369. BaseVector1.x = pfPosB[0] - pfPosA[0];
  370. BaseVector1.y = pfPosB[1] - pfPosA[1];
  371. BaseVector1.z = pfPosB[2] - pfPosA[2];
  372. BaseVector2.x = pfPosC[0] - pfPosA[0];
  373. BaseVector2.y = pfPosC[1] - pfPosA[1];
  374. BaseVector2.z = pfPosC[2] - pfPosA[2];
  375. if (pfTexB[0]==pfTexA[0] && pfTexC[0]==pfTexA[0])
  376. {
  377. // Degenerate tri
  378. // _ASSERT(0);
  379. pvTan->x = 0;
  380. pvTan->y = 0;
  381. pvTan->z = 0;
  382. pvBin->x = 0;
  383. pvBin->y = 0;
  384. pvBin->z = 0;
  385. }
  386. else
  387. {
  388. /* Calc the vector that follows the V direction (it is not the tangent vector)*/
  389. if(pfTexB[0]==pfTexA[0]) {
  390. AlignedVector = BaseVector1;
  391. if((pfTexB[1] - pfTexA[1]) < 0) {
  392. AlignedVector.x = -AlignedVector.x;
  393. AlignedVector.y = -AlignedVector.y;
  394. AlignedVector.z = -AlignedVector.z;
  395. }
  396. } else if(pfTexC[0]==pfTexA[0]) {
  397. AlignedVector = BaseVector2;
  398. if((pfTexC[1] - pfTexA[1]) < 0) {
  399. AlignedVector.x = -AlignedVector.x;
  400. AlignedVector.y = -AlignedVector.y;
  401. AlignedVector.z = -AlignedVector.z;
  402. }
  403. } else {
  404. float fFac;
  405. fFac = -(pfTexB[0] - pfTexA[0]) / (pfTexC[0] - pfTexA[0]);
  406. /* This is the vector that follows the V direction (it is not the tangent vector)*/
  407. AlignedVector.x = BaseVector1.x + BaseVector2.x * fFac;
  408. AlignedVector.y = BaseVector1.y + BaseVector2.y * fFac;
  409. AlignedVector.z = BaseVector1.z + BaseVector2.z * fFac;
  410. if(((pfTexB[1] - pfTexA[1]) + (pfTexC[1] - pfTexA[1]) * fFac) < 0) {
  411. AlignedVector.x = -AlignedVector.x;
  412. AlignedVector.y = -AlignedVector.y;
  413. AlignedVector.z = -AlignedVector.z;
  414. }
  415. }
  416. PVRTMatrixVec3NormalizeF(AlignedVector, AlignedVector);
  417. /* The Tangent vector is perpendicular to the plane defined by vAlignedVector and the Normal. */
  418. PVRTMatrixVec3CrossProductF(*pvTan, *pvNor, AlignedVector);
  419. /* The Bitangent vector is the vector perpendicular to the Normal and Tangent (and
  420. that follows the vAlignedVector direction) */
  421. PVRTMatrixVec3CrossProductF(*pvBin, *pvTan, *pvNor);
  422. _ASSERT(PVRTMatrixVec3DotProductF(*pvBin, AlignedVector) > 0.0f);
  423. // Worry about wrapping; this is esentially a 2D cross product on texture coords
  424. if((pfTexC[0]-pfTexA[0])*(pfTexB[1]-pfTexA[1]) < (pfTexC[1]-pfTexA[1])*(pfTexB[0]-pfTexA[0])) {
  425. pvTan->x = -pvTan->x;
  426. pvTan->y = -pvTan->y;
  427. pvTan->z = -pvTan->z;
  428. }
  429. /* Normalize results */
  430. PVRTMatrixVec3NormalizeF(*pvTan, *pvTan);
  431. PVRTMatrixVec3NormalizeF(*pvBin, *pvBin);
  432. _ASSERT(PVRTMatrixVec3DotProductF(*pvNor, *pvNor) > 0.9f);
  433. _ASSERT(PVRTMatrixVec3DotProductF(*pvTan, *pvTan) > 0.9f);
  434. _ASSERT(PVRTMatrixVec3DotProductF(*pvBin, *pvBin) > 0.9f);
  435. }
  436. }
  437. /*!***************************************************************************
  438. @Function PVRTVertexGenerateTangentSpace
  439. @Output pnVtxNumOut Output vertex count
  440. @Output pVtxOut Output vertices (program must free() this)
  441. @Modified pui32Idx input AND output; index array for triangle list
  442. @Input nVtxNum Input vertex count
  443. @Input pVtx Input vertices
  444. @Input nStride Size of a vertex (in bytes)
  445. @Input nOffsetPos Offset in bytes to the vertex position
  446. @Input eTypePos Data type of the position
  447. @Input nOffsetNor Offset in bytes to the vertex normal
  448. @Input eTypeNor Data type of the normal
  449. @Input nOffsetTex Offset in bytes to the vertex texture coordinate to use
  450. @Input eTypeTex Data type of the texture coordinate
  451. @Input nOffsetTan Offset in bytes to the vertex tangent
  452. @Input eTypeTan Data type of the tangent
  453. @Input nOffsetBin Offset in bytes to the vertex bitangent
  454. @Input eTypeBin Data type of the bitangent
  455. @Input nTriNum Number of triangles
  456. @Input fSplitDifference Split a vertex if the DP3 of tangents/bitangents are below this (range -1..1)
  457. @Return PVR_FAIL if there was a problem.
  458. @Description Calculates the tangent space for all supplied vertices.
  459. Writes tangent and bitangent vectors to the output
  460. vertices, copies all other elements from input vertices.
  461. Will split vertices if necessary - i.e. if two triangles
  462. sharing a vertex want to assign it different
  463. tangent-space matrices. The decision whether to split
  464. uses fSplitDifference - of the DP3 of two desired
  465. tangents or two desired bitangents is higher than this,
  466. the vertex will be split.
  467. *****************************************************************************/
  468. EPVRTError PVRTVertexGenerateTangentSpace(
  469. unsigned int * const pnVtxNumOut,
  470. char ** const pVtxOut,
  471. unsigned int * const pui32Idx,
  472. const unsigned int nVtxNum,
  473. const char * const pVtx,
  474. const unsigned int nStride,
  475. const unsigned int nOffsetPos,
  476. EPVRTDataType eTypePos,
  477. const unsigned int nOffsetNor,
  478. EPVRTDataType eTypeNor,
  479. const unsigned int nOffsetTex,
  480. EPVRTDataType eTypeTex,
  481. const unsigned int nOffsetTan,
  482. EPVRTDataType eTypeTan,
  483. const unsigned int nOffsetBin,
  484. EPVRTDataType eTypeBin,
  485. const unsigned int nTriNum,
  486. const float fSplitDifference)
  487. {
  488. const int cnMaxSharedVtx = 32;
  489. struct SVtxData
  490. {
  491. int n; // Number of items in following arrays, AKA number of tris using this vtx
  492. PVRTVECTOR3f pvTan[cnMaxSharedVtx]; // Tangent (one per triangle referencing this vtx)
  493. PVRTVECTOR3f pvBin[cnMaxSharedVtx]; // Bitangent (one per triangle referencing this vtx)
  494. int pnTri[cnMaxSharedVtx]; // Triangle index (one per triangle referencing this vtx)
  495. };
  496. SVtxData *psVtxData; // Array of desired tangent spaces per vertex
  497. SVtxData *psTSpass; // Array of *different* tangent spaces desired for current vertex
  498. unsigned int nTSpassLen;
  499. SVtxData *psVtx, *psCmp;
  500. unsigned int nVert, nCurr, i, j; // Loop counters
  501. unsigned int nIdx0, nIdx1, nIdx2;
  502. float pfPos0[4], pfPos1[4], pfPos2[4];
  503. float pfTex0[4], pfTex1[4], pfTex2[4];
  504. float pfNor0[4], pfNor1[4], pfNor2[4];
  505. unsigned int *pui32IdxNew; // New index array, this will be copied over the input array
  506. // Initialise the outputs
  507. *pnVtxNumOut = 0;
  508. *pVtxOut = (char*)malloc(MAX_VERTEX_OUT * nStride);
  509. if(!*pVtxOut)
  510. {
  511. return PVR_FAIL;
  512. }
  513. // Allocate some work space
  514. pui32IdxNew = (unsigned int*)malloc(nTriNum * 3 * sizeof(*pui32IdxNew));
  515. _ASSERT(pui32IdxNew);
  516. psVtxData = (SVtxData*)calloc(nVtxNum, sizeof(*psVtxData));
  517. _ASSERT(psVtxData);
  518. psTSpass = (SVtxData*)calloc(cnMaxSharedVtx, sizeof(*psTSpass));
  519. _ASSERT(psTSpass);
  520. if(!pui32IdxNew || !psVtxData || !psTSpass)
  521. {
  522. return PVR_FAIL;
  523. }
  524. for(nCurr = 0; nCurr < nTriNum; ++nCurr) {
  525. nIdx0 = pui32Idx[3*nCurr+0];
  526. nIdx1 = pui32Idx[3*nCurr+1];
  527. nIdx2 = pui32Idx[3*nCurr+2];
  528. _ASSERT(nIdx0 < nVtxNum);
  529. _ASSERT(nIdx1 < nVtxNum);
  530. _ASSERT(nIdx2 < nVtxNum);
  531. if(nIdx0 == nIdx1 || nIdx1 == nIdx2 || nIdx0 == nIdx2) {
  532. _RPT0(_CRT_WARN,"GenerateTangentSpace(): Degenerate triangle found.\n");
  533. return PVR_FAIL;
  534. }
  535. if(
  536. psVtxData[nIdx0].n >= cnMaxSharedVtx ||
  537. psVtxData[nIdx1].n >= cnMaxSharedVtx ||
  538. psVtxData[nIdx2].n >= cnMaxSharedVtx)
  539. {
  540. _RPT0(_CRT_WARN,"GenerateTangentSpace(): Too many tris sharing a vtx.\n");
  541. return PVR_FAIL;
  542. }
  543. PVRTVertexRead((PVRTVECTOR4f*) &pfPos0[0], (char*)&pVtx[nIdx0 * nStride] + nOffsetPos, eTypePos, 3);
  544. PVRTVertexRead((PVRTVECTOR4f*) &pfPos1[0], (char*)&pVtx[nIdx1 * nStride] + nOffsetPos, eTypePos, 3);
  545. PVRTVertexRead((PVRTVECTOR4f*) &pfPos2[0], (char*)&pVtx[nIdx2 * nStride] + nOffsetPos, eTypePos, 3);
  546. PVRTVertexRead((PVRTVECTOR4f*) &pfNor0[0], (char*)&pVtx[nIdx0 * nStride] + nOffsetNor, eTypeNor, 3);
  547. PVRTVertexRead((PVRTVECTOR4f*) &pfNor1[0], (char*)&pVtx[nIdx1 * nStride] + nOffsetNor, eTypeNor, 3);
  548. PVRTVertexRead((PVRTVECTOR4f*) &pfNor2[0], (char*)&pVtx[nIdx2 * nStride] + nOffsetNor, eTypeNor, 3);
  549. PVRTVertexRead((PVRTVECTOR4f*) &pfTex0[0], (char*)&pVtx[nIdx0 * nStride] + nOffsetTex, eTypeTex, 3);
  550. PVRTVertexRead((PVRTVECTOR4f*) &pfTex1[0], (char*)&pVtx[nIdx1 * nStride] + nOffsetTex, eTypeTex, 3);
  551. PVRTVertexRead((PVRTVECTOR4f*) &pfTex2[0], (char*)&pVtx[nIdx2 * nStride] + nOffsetTex, eTypeTex, 3);
  552. PVRTVertexTangentBitangent(
  553. &psVtxData[nIdx0].pvTan[psVtxData[nIdx0].n],
  554. &psVtxData[nIdx0].pvBin[psVtxData[nIdx0].n],
  555. (PVRTVECTOR3f*) &pfNor0[0],
  556. pfPos0, pfPos1, pfPos2,
  557. pfTex0, pfTex1, pfTex2);
  558. PVRTVertexTangentBitangent(
  559. &psVtxData[nIdx1].pvTan[psVtxData[nIdx1].n],
  560. &psVtxData[nIdx1].pvBin[psVtxData[nIdx1].n],
  561. (PVRTVECTOR3f*) &pfNor1[0],
  562. pfPos1, pfPos2, pfPos0,
  563. pfTex1, pfTex2, pfTex0);
  564. PVRTVertexTangentBitangent(
  565. &psVtxData[nIdx2].pvTan[psVtxData[nIdx2].n],
  566. &psVtxData[nIdx2].pvBin[psVtxData[nIdx2].n],
  567. (PVRTVECTOR3f*) &pfNor2[0],
  568. pfPos2, pfPos0, pfPos1,
  569. pfTex2, pfTex0, pfTex1);
  570. psVtxData[nIdx0].pnTri[psVtxData[nIdx0].n] = nCurr;
  571. psVtxData[nIdx1].pnTri[psVtxData[nIdx1].n] = nCurr;
  572. psVtxData[nIdx2].pnTri[psVtxData[nIdx2].n] = nCurr;
  573. ++psVtxData[nIdx0].n;
  574. ++psVtxData[nIdx1].n;
  575. ++psVtxData[nIdx2].n;
  576. }
  577. // Now let's go through the vertices calculating avg tangent-spaces; create new vertices if necessary
  578. for(nVert = 0; nVert < nVtxNum; ++nVert) {
  579. psVtx = &psVtxData[nVert];
  580. // Start out with no output vertices required for this input vertex
  581. nTSpassLen = 0;
  582. // Run through each desired tangent space for this vertex
  583. for(nCurr = 0; nCurr < (unsigned int) psVtx->n; ++nCurr) {
  584. // Run through the possible vertices we can share with to see if we match
  585. for(i = 0; i < nTSpassLen; ++i) {
  586. psCmp = &psTSpass[i];
  587. // Check all the shared vertices which match
  588. for(j = 0; j < (unsigned int) psCmp->n; ++j) {
  589. if(PVRTMatrixVec3DotProductF(psVtx->pvTan[nCurr], psCmp->pvTan[j]) < fSplitDifference)
  590. break;
  591. if(PVRTMatrixVec3DotProductF(psVtx->pvBin[nCurr], psCmp->pvBin[j]) < fSplitDifference)
  592. break;
  593. }
  594. // Did all the existing vertices match?
  595. if(j == (unsigned int) psCmp->n) {
  596. // Yes, so add to list
  597. _ASSERT(psCmp->n < cnMaxSharedVtx);
  598. psCmp->pvTan[psCmp->n] = psVtx->pvTan[nCurr];
  599. psCmp->pvBin[psCmp->n] = psVtx->pvBin[nCurr];
  600. psCmp->pnTri[psCmp->n] = psVtx->pnTri[nCurr];
  601. ++psCmp->n;
  602. break;
  603. }
  604. }
  605. if(i == nTSpassLen) {
  606. // We never found another matching matrix, so let's add this as a different one
  607. _ASSERT(nTSpassLen < cnMaxSharedVtx);
  608. psTSpass[nTSpassLen].pvTan[0] = psVtx->pvTan[nCurr];
  609. psTSpass[nTSpassLen].pvBin[0] = psVtx->pvBin[nCurr];
  610. psTSpass[nTSpassLen].pnTri[0] = psVtx->pnTri[nCurr];
  611. psTSpass[nTSpassLen].n = 1;
  612. ++nTSpassLen;
  613. }
  614. }
  615. // OK, now we have 'nTSpassLen' different desired matrices, so we need to add that many to output
  616. _ASSERT(nTSpassLen >= 1);
  617. for(nCurr = 0; nCurr < nTSpassLen; ++nCurr) {
  618. psVtx = &psTSpass[nCurr];
  619. memset(&pfPos0, 0, sizeof(pfPos0));
  620. memset(&pfPos1, 0, sizeof(pfPos1));
  621. for(i = 0; i < (unsigned int) psVtx->n; ++i) {
  622. // Sum the tangent & bitangents, so we can average them
  623. pfPos0[0] += psVtx->pvTan[i].x;
  624. pfPos0[1] += psVtx->pvTan[i].y;
  625. pfPos0[2] += psVtx->pvTan[i].z;
  626. pfPos1[0] += psVtx->pvBin[i].x;
  627. pfPos1[1] += psVtx->pvBin[i].y;
  628. pfPos1[2] += psVtx->pvBin[i].z;
  629. // Update triangle indices to use this vtx
  630. if(pui32Idx[3 * psVtx->pnTri[i] + 0] == nVert) {
  631. pui32IdxNew[3 * psVtx->pnTri[i] + 0] = *pnVtxNumOut;
  632. } else if(pui32Idx[3 * psVtx->pnTri[i] + 1] == nVert) {
  633. pui32IdxNew[3 * psVtx->pnTri[i] + 1] = *pnVtxNumOut;
  634. } else if(pui32Idx[3 * psVtx->pnTri[i] + 2] == nVert) {
  635. pui32IdxNew[3 * psVtx->pnTri[i] + 2] = *pnVtxNumOut;
  636. } else {
  637. _ASSERT(0);
  638. }
  639. }
  640. PVRTMatrixVec3NormalizeF(*(PVRTVECTOR3f*) &pfPos0[0], *(PVRTVECTOR3f*) &pfPos0[0]);
  641. PVRTMatrixVec3NormalizeF(*(PVRTVECTOR3f*) &pfPos1[0], *(PVRTVECTOR3f*) &pfPos1[0]);
  642. if(*pnVtxNumOut >= MAX_VERTEX_OUT) {
  643. _RPT0(_CRT_WARN,"PVRTVertexGenerateTangentSpace() ran out of working space! (Too many split vertices)\n");
  644. return PVR_FAIL;
  645. }
  646. memcpy(&(*pVtxOut)[(*pnVtxNumOut) * nStride], &pVtx[nVert*nStride], nStride);
  647. PVRTVertexWrite((char*)&(*pVtxOut)[(*pnVtxNumOut) * nStride] + nOffsetTan, eTypeTan, 3, (PVRTVECTOR4f*) &pfPos0[0]);
  648. PVRTVertexWrite((char*)&(*pVtxOut)[(*pnVtxNumOut) * nStride] + nOffsetBin, eTypeBin, 3, (PVRTVECTOR4f*) &pfPos1[0]);
  649. ++*pnVtxNumOut;
  650. }
  651. }
  652. FREE(psTSpass);
  653. FREE(psVtxData);
  654. *pVtxOut = (char*)realloc(*pVtxOut, *pnVtxNumOut * nStride);
  655. _ASSERT(*pVtxOut);
  656. memcpy(pui32Idx, pui32IdxNew, nTriNum * 3 * sizeof(*pui32IdxNew));
  657. FREE(pui32IdxNew);
  658. _RPT3(_CRT_WARN, "GenerateTangentSpace(): %d tris, %d vtx in, %d vtx out\n", nTriNum, nVtxNum, *pnVtxNumOut);
  659. _ASSERT(*pnVtxNumOut >= nVtxNum);
  660. return PVR_SUCCESS;
  661. }
  662. /*****************************************************************************
  663. End of file (PVRTVertex.cpp)
  664. *****************************************************************************/