1#include "MarchingCubesTables.h"
2#include "IsoSurfaces_internal.h"
5#include "Platform/Instrumentation.h"
6#include "Services/Features.h"
8#include "Foundation/Platform/Timer.h"
9#include "Foundation/Platform/Threads.h"
16 const uint8_t* axesTable;
18 const uint8_t* indexTable;
19 const int32_t* cellMap;
20 const uint8_t* activeCellCases;
21 const int32_t* activeCellVertexOffsets;
22 const int32_t* activeCellIndexOffsets;
23 const int32_t* activeCellIndices;
28 std::atomic<uint64_t>* elapsed_us;
29 Cogs::Core::IsoSurfaces::IndexEmitFunc emit;
33 CpuInstrumentationScope(SCOPE_ISOSURFACES,
"ExtIdx");
34 auto timer = Cogs::Timer::startNew();
37 uint32_t MxMy = M.x*M.y;
39#if !defined(EMSCRIPTEN) && !defined(__APPLE__)
40 if (context->
features->supported(Cogs::Core::CPUFeature::SSE42)) {
41 for (
int c = ca; c < cb; c++) {
42 const auto oc = activeCellIndexOffsets[c];
43 const auto on = activeCellIndexOffsets[c + 1];
44 if (oc == on)
continue;
48 auto ijk = activeCellIJK[c];
50 int cellIndex = activeCellIndices[c];
52 const auto code = activeCellCases[c];
56 for (uint32_t k = 0; k < n; k += 3) {
57 const auto axisShift0 = indexTable[16 * code + k + 0];
58 const auto axisShift1 = indexTable[16 * code + k + 1];
59 const auto axisShift2 = indexTable[16 * code + k + 2];
61 __m128i axisShift = _mm_set_epi32(0, axisShift2, axisShift1, axisShift0);
63 __m128i t0 = _mm_andnot_si128(_mm_cmpeq_epi32(_mm_and_si128(_mm_set1_epi32(8), axisShift), _mm_setzero_si128()), _mm_set1_epi32(1));
64 __m128i t1 = _mm_andnot_si128(_mm_cmpeq_epi32(_mm_and_si128(_mm_set1_epi32(16), axisShift), _mm_setzero_si128()), _mm_set1_epi32(Mx));
65 __m128i t2 = _mm_andnot_si128(_mm_cmpeq_epi32(_mm_and_si128(_mm_set1_epi32(32), axisShift), _mm_setzero_si128()), _mm_set1_epi32(MxMy));
67 __m128i cellOfVertex = _mm_add_epi32(_mm_add_epi32(_mm_set1_epi32(cellIndex), t0),
68 _mm_add_epi32(t1, t2));
70 uint32_t cellOfVertex0 = cellMap[cellOfVertex.m128i_i32[0]];
71 uint32_t cellOfVertex1 = cellMap[cellOfVertex.m128i_i32[1]];
72 uint32_t cellOfVertex2 = cellMap[cellOfVertex.m128i_i32[2]];
74 auto codeShifted0 = activeCellCases[cellOfVertex0];
75 auto codeShifted1 = activeCellCases[cellOfVertex1];
76 auto codeShifted2 = activeCellCases[cellOfVertex2];
77 __m128i axes = _mm_and_si128(_mm_set_epi32(0,
78 axesTable[codeShifted2],
79 axesTable[codeShifted1],
80 axesTable[codeShifted0]),
82 __m128i t3 = _mm_and_si128(_mm_srli_epi32(axes, 1), _mm_set1_epi32(1));
83 __m128i t4 = _mm_and_si128(_mm_srli_epi32(axes, 2), _mm_set1_epi32(1));
85 auto offsetShifted0 = activeCellVertexOffsets[cellOfVertex0];
86 auto offsetShifted1 = activeCellVertexOffsets[cellOfVertex1];
87 auto offsetShifted2 = activeCellVertexOffsets[cellOfVertex2];
88 __m128i offsetShifted = _mm_add_epi32(_mm_set_epi32(0, offsetShifted2, offsetShifted1, offsetShifted0),
89 _mm_add_epi32(t3, t4));
90 _mm_storeu_si128(
reinterpret_cast<__m128i*
>(indices + k), offsetShifted);
92 emit(index, glm::ivec3(ijk.i, ijk.j, ijk.k) + gridA, indices, n);
99 for (
int c = ca; c < cb; c++) {
100 const auto oc = activeCellIndexOffsets[c];
101 const auto on = activeCellIndexOffsets[c + 1];
102 if (oc == on)
continue;
106 auto ijk = activeCellIJK[c];
108 int cellIndex = activeCellIndices[c];
112 const auto code = activeCellCases[c];
115 uint32_t indices[16];
116 for (uint32_t k = 0; k < n; k++) {
117 const auto axisShift = indexTable[16 * code + k];
118 assert(axisShift != 255);
120 uint32_t cellOfVertex = cellMap[cellIndex +
121 ((axisShift & 8) ? 1 : 0) +
122 ((axisShift & 16) ? Mx : 0) +
123 ((axisShift & 32) ? MxMy : 0)];
124 assert(0 <= cellOfVertex);
126 auto codeShifted = activeCellCases[cellOfVertex];
127 auto offsetShifted = activeCellVertexOffsets[cellOfVertex];
128 auto axes = axesTable[codeShifted] & axisShift;
131 ((axes & 4) ? 1 : 0) +
132 ((axes & 2) ? 1 : 0);
134 indices[k] = offsetShifted;
136 emit(index, glm::ivec3(ijk.i, ijk.j, ijk.k) + gridA, indices, n);
139 if (elapsed_us !=
nullptr) {
140 elapsed_us->fetch_add(timer.elapsedMicroseconds());
149void Cogs::Core::IsoSurfaces::extractIndices(Context* context,
151 IndexEmitFunc& emitFunc,
152 const int32_t* cellMap,
153 const uint8_t* activeCellCases,
154 const int32_t* activeCellVertexOffsets,
155 const int32_t* activeCellIndexOffsets,
156 const int32_t* activeCellIndices,
157 const Scratch::ijk_t* activeCellIJK,
158 const int32_t activeCellCount,
159 const glm::ivec3 gridA,
160 const glm::ivec3 gridB,
161 std::atomic<uint64_t>* elapsed_us)
164 const auto & indexTable = MarchingCubes::indexTable();
165 const auto & axesTable = MarchingCubes::axesTable();
166 const glm::ivec3 M = gridB - gridA;
168 const auto Q =
static_cast<int>(Threads::hardwareConcurrency());
169 const auto taskSize = std::max(1024, (activeCellCount + Q - 1) / Q);
170 for (
int c = 0; c < activeCellCount; c += taskSize) {
173 task.context = context;
174 task.axesTable = axesTable.data();
176 task.indexTable = indexTable.data();
177 task.cellMap = cellMap;
178 task.activeCellCases = activeCellCases;
179 task.activeCellVertexOffsets = activeCellVertexOffsets;
180 task.activeCellIndexOffsets = activeCellIndexOffsets;
181 task.activeCellIndices = activeCellIndices;
182 task.activeCellIJK = activeCellIJK;
186 task.cb = std::min(c + taskSize, activeCellCount);
187 task.elapsed_us = elapsed_us;
188 task.emit = emitFunc;
190 context->taskManager->enqueueChild(group, task);
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class Features > features
Features service instance.
COGSCORE_DLL_API const std::vector< unsigned char > & indexCountTable()