CmIndexData.cpp 4.5 KB

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