topology.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include <bx/debug.h>
  6. #include <bx/radixsort.h>
  7. #include "config.h"
  8. #include "topology.h"
  9. namespace bgfx
  10. {
  11. template<typename IndexT>
  12. static uint32_t topologyConvertTriListFlipWinding(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices)
  13. {
  14. if (NULL == _dst)
  15. {
  16. return _numIndices;
  17. }
  18. IndexT* dst = (IndexT*)_dst;
  19. IndexT* end = &dst[_dstSize/sizeof(IndexT)];
  20. for (uint32_t ii = 0; ii < _numIndices && dst < end; ii += 3, dst += 3)
  21. {
  22. const IndexT* tri = &_indices[ii];
  23. IndexT i0 = tri[0], i1 = tri[1], i2 = tri[2];
  24. dst[0] = i0;
  25. dst[1] = i2;
  26. dst[2] = i1;
  27. }
  28. return _numIndices;
  29. }
  30. template<typename IndexT, typename SortT>
  31. static uint32_t topologyConvertTriListToLineList(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices, IndexT* _temp, SortT* _tempSort)
  32. {
  33. // Create all line pairs and sort indices.
  34. IndexT* dst = _temp;
  35. for (uint32_t ii = 0; ii < _numIndices; ii += 3)
  36. {
  37. const IndexT* tri = &_indices[ii];
  38. IndexT i0 = tri[0], i1 = tri[1], i2 = tri[2];
  39. if (i0 > i1) { bx::xchg(i0, i1); }
  40. if (i1 > i2) { bx::xchg(i1, i2); }
  41. if (i0 > i1) { bx::xchg(i0, i1); }
  42. BX_CHECK(i0 < i1 < i2, "");
  43. dst[0] = i0; dst[1] = i1;
  44. dst[2] = i1; dst[3] = i2;
  45. dst[4] = i0; dst[5] = i2;
  46. dst += 6;
  47. }
  48. // Sort all line pairs.
  49. SortT* sorted = (SortT*)_temp;
  50. bx::radixSort(sorted, _tempSort, _numIndices);
  51. uint32_t num = 0;
  52. // Remove all line pair duplicates.
  53. if (NULL == _dst)
  54. {
  55. SortT last = sorted[0];
  56. for (uint32_t ii = 1; ii < _numIndices; ++ii)
  57. {
  58. if (last != sorted[ii])
  59. {
  60. num += 2;
  61. last = sorted[ii];
  62. }
  63. }
  64. num += 2;
  65. }
  66. else
  67. {
  68. dst = (IndexT*)_dst;
  69. IndexT* end = &dst[_dstSize/sizeof(IndexT)];
  70. SortT last = sorted[0];
  71. for (uint32_t ii = 1; ii < _numIndices && dst < end; ++ii)
  72. {
  73. if (last != sorted[ii])
  74. {
  75. union Un { SortT key; struct { IndexT i0; IndexT i1; } u16; } un = { last };
  76. dst[0] = un.u16.i0;
  77. dst[1] = un.u16.i1;
  78. dst += 2;
  79. last = sorted[ii];
  80. }
  81. }
  82. if (dst < end)
  83. {
  84. union Un { SortT key; struct { IndexT i0; IndexT i1; } u16; } un = { last };
  85. dst[0] = un.u16.i0;
  86. dst[1] = un.u16.i1;
  87. dst += 2;
  88. }
  89. num = uint32_t(dst - (IndexT*)_dst);
  90. }
  91. return num;
  92. }
  93. template<typename IndexT, typename SortT>
  94. static uint32_t topologyConvertTriListToLineList(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices, bx::AllocatorI* _allocator)
  95. {
  96. IndexT* temp = (IndexT*)BX_ALLOC(_allocator, _numIndices*2*sizeof(IndexT)*2);
  97. SortT* tempSort = (SortT*)&temp[_numIndices*2];
  98. uint32_t num = topologyConvertTriListToLineList(_dst, _dstSize, _indices, _numIndices, temp, tempSort);
  99. BX_FREE(_allocator, temp);
  100. return num;
  101. }
  102. template<typename IndexT>
  103. static uint32_t topologyConvertTriStripToTriList(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices)
  104. {
  105. IndexT* dst = (IndexT*)_dst;
  106. IndexT* end = &dst[_dstSize/sizeof(IndexT)];
  107. for (uint32_t ii = 0, num = _numIndices-2; ii < num && dst < end; ++ii)
  108. {
  109. IndexT i0 = _indices[ii+0];
  110. IndexT i1 = _indices[ii+1];
  111. IndexT i2 = _indices[ii+2];
  112. if (i0 != i1
  113. && i1 != i2)
  114. {
  115. dst[0] = i0;
  116. dst[1] = i1;
  117. dst[2] = i2;
  118. dst += 3;
  119. }
  120. }
  121. return uint32_t(dst - (IndexT*)_dst);
  122. }
  123. template<typename IndexT>
  124. static uint32_t topologyConvertLineStripToLineList(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices)
  125. {
  126. IndexT* dst = (IndexT*)_dst;
  127. IndexT* end = &dst[_dstSize/sizeof(IndexT)];
  128. IndexT i0 = _indices[0];
  129. for (uint32_t ii = 1; ii < _numIndices && dst < end; ++ii)
  130. {
  131. IndexT i1 = _indices[ii];
  132. if (i0 != i1)
  133. {
  134. dst[0] = i0;
  135. dst[1] = i1;
  136. dst += 2;
  137. i0 = i1;
  138. }
  139. }
  140. return uint32_t(dst - (IndexT*)_dst);
  141. }
  142. uint32_t topologyConvert(TopologyConvert::Enum _conversion, void* _dst, uint32_t _dstSize, const void* _indices, uint32_t _numIndices, bool _index32, bx::AllocatorI* _allocator)
  143. {
  144. switch (_conversion)
  145. {
  146. case TopologyConvert::TriStripToTriList:
  147. if (_index32)
  148. {
  149. return topologyConvertTriStripToTriList(_dst, _dstSize, (const uint32_t*)_indices, _numIndices);
  150. }
  151. return topologyConvertTriStripToTriList(_dst, _dstSize, (const uint16_t*)_indices, _numIndices);
  152. case TopologyConvert::TriListFlipWinding:
  153. if (_index32)
  154. {
  155. return topologyConvertTriListFlipWinding(_dst, _dstSize, (const uint32_t*)_indices, _numIndices);
  156. }
  157. return topologyConvertTriListFlipWinding(_dst, _dstSize, (const uint16_t*)_indices, _numIndices);
  158. case TopologyConvert::TriListToLineList:
  159. if (NULL == _allocator)
  160. {
  161. return 0;
  162. }
  163. if (_index32)
  164. {
  165. return topologyConvertTriListToLineList<uint32_t, uint64_t>(_dst, _dstSize, (const uint32_t*)_indices, _numIndices, _allocator);
  166. }
  167. return topologyConvertTriListToLineList<uint16_t, uint32_t>(_dst, _dstSize, (const uint16_t*)_indices, _numIndices, _allocator);
  168. case TopologyConvert::LineStripToLineList:
  169. if (_index32)
  170. {
  171. return topologyConvertLineStripToLineList(_dst, _dstSize, (const uint32_t*)_indices, _numIndices);
  172. }
  173. return topologyConvertLineStripToLineList(_dst, _dstSize, (const uint16_t*)_indices, _numIndices);
  174. default:
  175. break;
  176. }
  177. return 0;
  178. }
  179. } //namespace bgfx