topology.cpp 5.4 KB

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