CmIndexData.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "CmIndexData.h"
  2. #include "CmHardwareBufferManager.h"
  3. #include "CmVertexBuffer.h"
  4. #include "CmIndexBuffer.h"
  5. #include "CmVector3.h"
  6. #include "CmAxisAlignedBox.h"
  7. #include "CmException.h"
  8. #include "CmRenderSystem.h"
  9. namespace CamelotEngine
  10. {
  11. IndexData::IndexData()
  12. {
  13. indexCount = 0;
  14. indexStart = 0;
  15. }
  16. IndexData::~IndexData()
  17. {
  18. }
  19. IndexData* IndexData::clone(bool copyData, HardwareBufferManager* mgr) const
  20. {
  21. HardwareBufferManager* pManager = mgr ? mgr : HardwareBufferManager::instancePtr();
  22. IndexData* dest = new IndexData();
  23. if (indexBuffer.get())
  24. {
  25. if (copyData)
  26. {
  27. dest->indexBuffer = pManager->createIndexBuffer(indexBuffer->getType(), indexBuffer->getNumIndexes(),
  28. indexBuffer->getUsage());
  29. dest->indexBuffer->copyData(*indexBuffer, 0, 0, indexBuffer->getSizeInBytes(), true);
  30. }
  31. else
  32. {
  33. dest->indexBuffer = indexBuffer;
  34. }
  35. }
  36. dest->indexCount = indexCount;
  37. dest->indexStart = indexStart;
  38. return dest;
  39. }
  40. // Local Utility class for vertex cache optimizer
  41. class Triangle
  42. {
  43. public:
  44. enum EdgeMatchType {
  45. AB, BC, CA, ANY, NONE
  46. };
  47. UINT32 a, b, c;
  48. inline Triangle()
  49. {
  50. }
  51. inline Triangle( UINT32 ta, UINT32 tb, UINT32 tc )
  52. : a( ta ), b( tb ), c( tc )
  53. {
  54. }
  55. inline Triangle( UINT32 t[3] )
  56. : a( t[0] ), b( t[1] ), c( t[2] )
  57. {
  58. }
  59. inline Triangle( const Triangle& t )
  60. : a( t.a ), b( t.b ), c( t.c )
  61. {
  62. }
  63. inline bool sharesEdge(const Triangle& t) const
  64. {
  65. return( a == t.a && b == t.c ||
  66. a == t.b && b == t.a ||
  67. a == t.c && b == t.b ||
  68. b == t.a && c == t.c ||
  69. b == t.b && c == t.a ||
  70. b == t.c && c == t.b ||
  71. c == t.a && a == t.c ||
  72. c == t.b && a == t.a ||
  73. c == t.c && a == t.b );
  74. }
  75. inline bool sharesEdge(const UINT32 ea, const UINT32 eb, const Triangle& t) const
  76. {
  77. return( ea == t.a && eb == t.c ||
  78. ea == t.b && eb == t.a ||
  79. ea == t.c && eb == t.b );
  80. }
  81. inline bool sharesEdge(const EdgeMatchType edge, const Triangle& t) const
  82. {
  83. if (edge == AB)
  84. return sharesEdge(a, b, t);
  85. else if (edge == BC)
  86. return sharesEdge(b, c, t);
  87. else if (edge == CA)
  88. return sharesEdge(c, a, t);
  89. else
  90. return (edge == ANY) == sharesEdge(t);
  91. }
  92. inline EdgeMatchType endoSharedEdge(const Triangle& t) const
  93. {
  94. if (sharesEdge(a, b, t)) return AB;
  95. if (sharesEdge(b, c, t)) return BC;
  96. if (sharesEdge(c, a, t)) return CA;
  97. return NONE;
  98. }
  99. inline EdgeMatchType exoSharedEdge(const Triangle& t) const
  100. {
  101. return t.endoSharedEdge(*this);
  102. }
  103. inline void shiftClockwise()
  104. {
  105. UINT32 t = a;
  106. a = c;
  107. c = b;
  108. b = t;
  109. }
  110. inline void shiftCounterClockwise()
  111. {
  112. UINT32 t = a;
  113. a = b;
  114. b = c;
  115. c = t;
  116. }
  117. };
  118. void IndexData::optimiseVertexCacheTriList(void)
  119. {
  120. if (indexBuffer->isLocked()) return;
  121. void *buffer = indexBuffer->lock(GBL_READ_WRITE);
  122. Triangle* triangles;
  123. UINT32 *dest;
  124. UINT32 nIndexes = indexCount;
  125. UINT32 nTriangles = nIndexes / 3;
  126. UINT32 i, j;
  127. UINT16 *source = 0;
  128. if (indexBuffer->getType() == IndexBuffer::IT_16BIT)
  129. {
  130. triangles = (Triangle*) malloc(sizeof(Triangle) * nTriangles);
  131. source = (UINT16 *)buffer;
  132. dest = (UINT32 *)triangles;
  133. for (i = 0; i < nIndexes; ++i) dest[i] = source[i];
  134. }
  135. else
  136. triangles = (Triangle*)buffer;
  137. // sort triangles based on shared edges
  138. UINT32 *destlist = (UINT32*)malloc(sizeof(UINT32) * nTriangles);
  139. unsigned char *visited = (unsigned char*)malloc(sizeof(unsigned char) * nTriangles);
  140. for (i = 0; i < nTriangles; ++i) visited[i] = 0;
  141. UINT32 start = 0, ti = 0, destcount = 0;
  142. bool found = false;
  143. for (i = 0; i < nTriangles; ++i)
  144. {
  145. if (found)
  146. found = false;
  147. else
  148. {
  149. while (visited[start++]);
  150. ti = start - 1;
  151. }
  152. destlist[destcount++] = ti;
  153. visited[ti] = 1;
  154. for (j = start; j < nTriangles; ++j)
  155. {
  156. if (visited[j]) continue;
  157. if (triangles[ti].sharesEdge(triangles[j]))
  158. {
  159. found = true;
  160. ti = static_cast<UINT32>(j);
  161. break;
  162. }
  163. }
  164. }
  165. if (indexBuffer->getType() == IndexBuffer::IT_16BIT)
  166. {
  167. // reorder the indexbuffer
  168. j = 0;
  169. for (i = 0; i < nTriangles; ++i)
  170. {
  171. Triangle *t = &triangles[destlist[i]];
  172. source[j++] = (UINT16)t->a;
  173. source[j++] = (UINT16)t->b;
  174. source[j++] = (UINT16)t->c;
  175. }
  176. free(triangles);
  177. }
  178. else
  179. {
  180. UINT32 *reflist = (UINT32*)malloc(sizeof(UINT32) * nTriangles);
  181. // fill the referencebuffer
  182. for (i = 0; i < nTriangles; ++i)
  183. reflist[destlist[i]] = static_cast<UINT32>(i);
  184. // reorder the indexbuffer
  185. for (i = 0; i < nTriangles; ++i)
  186. {
  187. j = destlist[i];
  188. if (i == j) continue; // do not move triangle
  189. // swap triangles
  190. Triangle t = triangles[i];
  191. triangles[i] = triangles[j];
  192. triangles[j] = t;
  193. // change reference
  194. destlist[reflist[i]] = static_cast<UINT32>(j);
  195. // destlist[i] = i; // not needed, it will not be used
  196. }
  197. free(reflist);
  198. }
  199. free(destlist);
  200. free(visited);
  201. indexBuffer->unlock();
  202. }
  203. }