1#include "Resources/MeshManager.h"
2#include "Platform/Instrumentation.h"
3#include "Resources/VertexFormats.h"
6#include "../Extensions/GeometryProcessing/GeometryProcessing.h"
7#include "../Extensions/IsoSurfaces/IsoSurfaces.h"
9#include "../Components/DataSetComponent.h"
10#include "../Components/PingIsoComponent.h"
11#include "../Components/BeamGroupComponent.h"
12#include "../Systems/PingIsoSystem.h"
13#include "../Systems/DataSetSystem.h"
14#include "../BeamUtils.h"
15#include "../BoundingBox.h"
16#include "dBToLinearTask.h"
17#include "DepthResampleTask.h"
18#include "BeamResampleTask.h"
19#include "SinglePingIsoSurfacesTasks.h"
21#include "Foundation/Logging/Logger.h"
22#include "Foundation/Memory/MemoryBuffer.h"
23#include "Foundation/Platform/Timer.h"
25#include <glm/gtc/type_ptr.hpp>
29using std::numeric_limits;
44 const int taskSize_Linearize = 5000;
45 const int taskSize_ResampleDepth = 20;
46 const int taskSize_InterpolateDirs = 500;
47 const int taskSize_InterpolateMinor = 100;
48 const int taskSize_InterpolateMajor = 100;
49 const ivec3 taskSize_Classify = ivec3(32, 16, 16);
50 const int taskSize_PopCnt = 10000;
51 const int taskSize_ExtractVtx = 10000;
52 const int taskSize_ExtractIdx = 10000;
53 const int taskSize_Normals = 10000;
54 const int taskSize_BBox = 10000;
56 const size_t granularity = 1024;
58 int elapsed_Count = 0;
59 double elapsed_Total = 0.0;
60 double elapsed_Resample = 0.0;
61 double elapsed_Linearize = 0.0;
62 double elapsed_DepthResample = 0.0;
63 double elapsed_BeamResample = 0.0;
64 double elapsed_Analyze = 0.0;
65 double elapsed_Extract = 0.0;
66 double elapsed_Normals = 0.0;
67 double elapsed_SetupMesh = 0.0;
68 double elapsed_Store = 0.0;
72 static const float factorA = (float)(log2(10.0) / 10.0);
73 static const float factorAe = (float)(
log(10.0) / 10.0);
74 static const float scale_dB = 100.0f;
78 struct WrapFunctorPointer
82 WrapFunctorPointer(T* pointer) : pointer(pointer) {}
84 void operator()() { (*pointer)(); }
92 uint32_t* slicesToMerge =
nullptr;
93 size_t slicesToMergeModulo = 0;
94 glm::vec3* P =
nullptr;
95 glm::vec2* T =
nullptr;
96 size_t vertexOffset = 0;
97 float linearThreshold = 0.f;
98 float normalizedLayer = 0.f;
99 float separation = 0.f;
102 void operator()(int32_t index, ivec3 aSample, ivec3 bSample)
104 ivec3 I[2] = { aSample, bSample };
106 const size_t beamMinorCount = main->beamMinorCount;
107 const size_t sampleCount = main->sampleCount;
109 float linearValue[2];
111 for (
int m = 0; m < 2; m++) {
113 ivec3 Ic = glm::clamp(Ir, ivec3(0), maxFieldIndex);
115 size_t linearIndex = (Ic.z*beamMinorCount + Ic.y)*sampleCount + Ic.x;
117 linearValue[m] = main->persistent->linearValues[linearIndex] - linearThreshold;
119 float depth = Ic.x*main->depthStep + main->depthOffset;
120 vec3 o = main->metaPing.arrayPositionVessel;
121 vec3 d = main->rayDir[Ic.z*beamMinorCount + Ic.y];
125 int signed_one = Ic.x - Ir.x < 0 ? -1 : 1;
126 depth = max(0.f, depth - separation * signed_one);
130 int signed_one = Ic.y - Ir.y < 0 ? -1 : 1;
132 assert(0 <= Ic.y + signed_one);
133 assert(Ic.y + signed_one <= maxFieldIndex.y);
134 d += separation * glm::normalize(dd - main->rayDir[Ic.z * beamMinorCount + Ic.y + signed_one]);
137 int signed_one = Ic.z - Ir.z < 0 ? -1 : 1;
138 int ic_z = Ic.z + signed_one;
140 assert(0 <= Ic.z + signed_one);
141 assert(Ic.z + signed_one <= maxFieldIndex.z);
142 d += separation * glm::normalize(dd - main->rayDir[ic_z * beamMinorCount + Ic.y]);
145 positions[m] = o + depth*d;
148 float den = (linearValue[1] - linearValue[0]);
149 float t = abs(den) < numeric_limits<float>::min() ? 0.5f : -linearValue[0] / den;
151 size_t vo = vertexOffset + index;
152 if (slicesToMerge && (I[0].y == I[1].y) && (I[0].y == 0 || I[0].y == maxFieldIndex.y)) {
157 const size_t slice = (I[0].y == 0) ? 0 : 1;
158 const size_t axis = (I[0].x + 1 == I[1].x) ? 0 : 2;
160 assert((!axis && (I[0].z == I[1].z)) || ((I[0].z + 1 == I[1].z) && (I[0].x == I[1].x)));
161 assert((I[0].x + 1) <= sampleCount);
163 assert(0 <= I[0].z + 1);
164 assert(0 <= I[0].x + 1);
165 const size_t cell = (I[0].z + 1) * (sampleCount + 1) + (I[0].x + 1);
166 const size_t ix = cell * 4 + slice + axis;
168 assert(ix < slicesToMergeModulo);
169 assert(slicesToMerge[ix] == uint32_t(~0));
171 slicesToMerge[ix] = uint32_t(vo);
173 P[vo] = (1.f - t)*positions[0] + t*positions[1];
174 T[vo] = vec2(normalizedLayer, 0.5f);
177 void operator()(int32_t ixIndex, glm::ivec4* samples,
const uint32_t ixN)
179 for (uint32_t k = 0; k < ixN; k++) {
180 this->operator()(ixIndex + k,
181 glm::ivec3(samples[0][0],
184 glm::ivec3(samples[0][1 + k],
192 struct VerticalMaskTask
202 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"VertMask");
204 const size_t minorCount = parent->beamMinorCount;
206 const size_t sampleCount = parent->sampleCount;
207 const float doff = parent->depthOffset;
208 const float dstp = parent->depthStep;
209 const float maxRange = doff + dstp*sampleCount;
211 float minVerticalDepth = std::isfinite(parent->minVerticalDepth) ? std::max(0.f, parent->minVerticalDepth) : 0.f;
212 float maxVerticalDepth = std::isfinite(parent->maxVerticalDepth) ? std::max(minVerticalDepth, parent->maxVerticalDepth) : 10000.f;
214 EchoSounder::clipVertical(parent->persistent->linearValues, a * minorCount * sampleCount,
215 parent->metaPing.arrayPositionVessel, parent->rayDir, a * minorCount,
216 minVerticalDepth, maxVerticalDepth,
217 parent->depthOffset, parent->depthStep, maxRange,
218 minorCount * (b - a), sampleCount);
227 const size_t majorIndexStart;
228 const size_t majorIndexEnd;
234 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"ClipToSeabedTask");
236 const size_t minorCount = parent->beamMinorCount;
238 const size_t sampleCount = parent->sampleCount;
239 const float depthOffset = parent->depthOffset;
240 const float depthStep = parent->depthStep;
242 auto & output = parent->persistent->linearValues;
243 for (
size_t k = majorIndexStart; k < majorIndexEnd; k++) {
244 for (
size_t j = 0; j < minorCount; j++) {
246 size_t out = (k*minorCount + j)*sampleCount;
248 auto bottomDepth = parent->depths[k*minorCount +j];
249 auto clipDist = bottomDepth - parent->seabedClipOffset;
250 auto N = (bottomDepth != 0.f && std::isfinite(parent->seabedClipOffset)) ? std::min(
static_cast<size_t>(std::max(0.f, std::floor((clipDist - depthOffset) / depthStep))), sampleCount) : sampleCount;
251 for (
size_t i = N; i < sampleCount; ++i) {
252 output[out + i] = 0.f;
259EchoSounder::SinglePingIsoSurfacesMainTask::SinglePingIsoSurfacesMainTask(
Context* context,
260 const PingIsoComponent* isoComp,
const SinglePingIsoSurfacesData* isoData,
261 const BeamGroupComponent* groupComp,
264 persistent(isoData->persistent),
266 index(isoData->index),
267 thresholds(isoData->thresholds),
268 flipOrientation(isoComp->flipOrientation),
269 beamMinorClosed(groupComp->minorClosed),
270 metaPing(dataData->persistent->buffer.metaPings[index]),
271 layers(static_cast<int>(isoData->thresholds.size())),
272 sampleCount(dataData->persistent->config.sampleCount),
273 coordSys(dataData->persistent->config.coordSys),
274 capSeparation(isoComp->capSeparation),
275 seabedClipOffset(isoData->seabedClipOffset),
276 depthOffset(dataData->persistent->config.depthOffset),
277 depthStep(dataData->persistent->config.depthStep),
278 logarithmicUnit(dataData->persistent->config.useDecibel),
279 depthStepResample(isoComp->depthSpacing),
280 beamStepResample(isoComp->beamSpacing),
281 maxBeamUpsample(isoComp->beamMaxUpsample),
282 overflowThreshold(isoComp->overflowThreshold),
283 minVerticalDepth(isoComp->minVerticalDepth),
284 maxVerticalDepth(isoComp->maxVerticalDepth)
286 const auto srcMajNum = groupComp->majorCount;
287 const auto srcMinNum = groupComp->minorCount;
289 beamMajorCount = max(2u, srcMajNum);
290 beamMinorCount = max(2u, srcMinNum + (beamMinorClosed ? 1u : 0u));
291 beamCount = beamMajorCount*beamMinorCount;
292 persistent->values.resize(beamCount*sampleCount + beamMajorCount);
293 depths.resize(beamCount);
296 directionX.resize(beamCount);
298 directionY.resize(beamCount);
300 const auto & config = dataData->persistent->config;
301 auto * src = dataData->persistent->buffer.values.data() + index*
static_cast<size_t>(dataData->persistent->config.beamCount*sampleCount);
302 for (uint32_t major = 0; major < beamMajorCount; major++) {
303 for (uint32_t minor = 0; minor < beamMinorCount; minor++) {
306 if (srcMinNum <= minor) {
307 if (beamMinorClosed) {
314 const auto ixDst = major*(beamMinorCount) + minor;
315 const auto ixSrc = groupComp->beams[min(srcMajNum - 1, major)*beamMinorCount + k];
317 directionX[ixDst] = dataData->persistent->config.directionX[ixSrc];
318 directionY[ixDst] = dataData->persistent->config.directionY[ixSrc];
319 depths[ixDst] = dataData->persistent->buffer.bottomDepths[ixSrc];
321 memcpy(persistent->values.data() + sampleCount*ixDst, src + sampleCount*ixSrc,
sizeof(
float)*sampleCount);
325 if (srcMajNum == 1) {
327 unsigned srcMinNumPadded = srcMinNum + (beamMinorClosed ? 1u : 0u);
329 std::vector<uint32_t> beams(srcMinNumPadded);
330 for (
unsigned i = 0; i < srcMinNum; i++) {
331 beams[i] = groupComp->beams[i];
333 if (beamMinorClosed) {
334 beams[srcMinNum] = beams[0];
337 inflateFans(directionX, directionY,
338 config.directionX, config.beamWidthX,
339 config.directionY, config.beamWidthY,
340 beams, groupComp->topology, srcMinNumPadded);
345void EchoSounder::SinglePingIsoSurfacesMainTask::operator()()
349 Timer timerTotal, timerPass;
351 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"EchoGridMain");
355 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"PassResize1");
358 linearThresholds.resize(thresholds.size());
359 persistent->linearValues.resize(persistent->values.size());
360 if (depthStepResample != 0.0f) {
361 sampleCountResample = min(10000,
static_cast<int>(floor((depthStep * sampleCount) / depthStepResample)));
362 persistent->tmpValues.resize(beamCount*sampleCountResample);
365 elapsed_Resample += timerPass.elapsedSeconds();
368 if (logarithmicUnit) {
369 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"PassLinearize");
374 transform(thresholds.begin(), thresholds.end(), linearThresholds.begin(), dBToLinear);
376 size_t N = persistent->values.size();
377 for (
size_t o = 0; o < N; o += taskSize_Linearize) {
379 task.overflowThreshold = overflowThreshold;
380 task.in = persistent->values.data() + o;
381 task.out = persistent->linearValues.data() + o;
382 task.N = min(N, o + taskSize_Linearize) - o;
388 elapsed_Linearize += timerPass.elapsedSeconds();
391 linearThresholds = thresholds;
392 persistent->linearValues.swap(persistent->values);
397 assert(directionX.size() == beamMajorCount*beamMinorCount);
398 assert(directionY.size() == beamMajorCount*beamMinorCount);
401 int total = beamMajorCount*beamMinorCount;
402 rayDir.resize(total);
404 for (
int b = 0; b < total; b += taskSize_InterpolateDirs) {
406 CalculateBeamDirectionsTask(rayDir.data(),
408 directionX.data(), directionY.data(),
409 beamMajorCount, beamMinorCount, metaPing.arrayOrientationVessel,
410 b, min(b + taskSize_InterpolateDirs, total)));
417 if (std::isfinite(seabedClipOffset)) {
419 int step = (beamMajorCount + 7) / 8;
422 for (uint32_t b = 0; b < beamMajorCount; b += step) {
426 min(b + step, beamMajorCount)));
435 if (depthStepResample != 0.0f) {
436 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"DepthResample");
439 auto depthResampleGroup = context->
taskManager->createGroup();
440 for (uint32_t b = 0; b < beamCount; b += taskSize_ResampleDepth) {
441 context->
taskManager->enqueueChild(depthResampleGroup, DepthResampleTask(persistent->tmpValues.data(),
444 persistent->linearValues.data(),
447 b, min(b + taskSize_ResampleDepth, beamCount)));
452 persistent->linearValues.swap(persistent->tmpValues);
453 depthStep = depthStepResample;
454 sampleCount = sampleCountResample;
456 elapsed_DepthResample += timerPass.elapsedSeconds();
460 if(beamStepResample != 0.0f) {
461 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"BeamResample");
464 float angularStep = std::atan(beamStepResample / (depthOffset + sampleCount*depthStep));
466 std::vector<InterpolationSamplePos> iSamplesOut;
467 std::vector<InterpolationSamplePos> jSamplesOut;
468 SetupBeamFilter(iSamplesOut, jSamplesOut, rayDir,
469 angularStep, maxBeamUpsample,
470 beamMinorCount, beamMajorCount);
472 uint32_t beamMajorCountNew =
static_cast<uint32_t
>(jSamplesOut.size());
473 uint32_t beamMinorCountNew =
static_cast<uint32_t
>(iSamplesOut.size());
475 auto interpolateGroup1 = context->
taskManager->createGroup();
476 int total = beamMajorCountNew*beamMinorCountNew;
479 std::vector<glm::vec3> rayDirNew(total);
480 for (uint32_t j = 0; j < beamMajorCountNew; j++) {
481 for (uint32_t i = 0; i < beamMinorCountNew; i++) {
482 const auto & d00 = rayDir[(jSamplesOut[j].i + 0)*beamMinorCount + (iSamplesOut[i].i + 0)];
483 const auto & d01 = rayDir[(jSamplesOut[j].i + 0)*beamMinorCount + (iSamplesOut[i].i + 1)];
484 const auto & d10 = rayDir[(jSamplesOut[j].i + 1)*beamMinorCount + (iSamplesOut[i].i + 0)];
485 const auto & d11 = rayDir[(jSamplesOut[j].i + 1)*beamMinorCount + (iSamplesOut[i].i + 1)];
488 const auto t0 = iSamplesOut[i].t;
489 const auto G0 = std::acos(glm::dot(d00, d01));
490 const auto d0 = (1.f / std::sin(G0))*(std::sin(G0*(1.f - t0))*d00 + std::sin(G0*t0)*d01);
492 const auto G1 = std::acos(glm::dot(d10, d11));
493 const auto d1 = (1.f / std::sin(G1))*(std::sin(G1*(1.f - t0))*d10 + std::sin(G1*t0)*d11);
495 const auto G = std::acos(glm::dot(d0, d1));
496 const auto t = jSamplesOut[j].t;
497 const auto d = (1.f / std::sin(G))*(std::sin(G*(1.f - t))*d0 + std::sin(G*t)*d1);
499 rayDirNew[j*beamMinorCountNew + i] = d;
502 rayDir.swap(rayDirNew);
505 persistent->tmpValues.resize(beamMajorCount * beamMinorCountNew * sampleCount);
506 total = beamMajorCount*beamMinorCountNew;
507 for (
int b = 0; b < total; b += taskSize_InterpolateMinor) {
508 context->
taskManager->enqueueChild(interpolateGroup1,
509 InterpolateBeamDataMinorTask(persistent->tmpValues.data(),
510 beamMajorCount, beamMinorCountNew, beamMinorCount, sampleCount,
511 persistent->linearValues.data(), iSamplesOut.data(),
512 b, min(b + taskSize_InterpolateMinor, total)));
517 persistent->linearValues.swap(persistent->tmpValues);
518 beamMinorCount = beamMinorCountNew;
521 auto interpolateGroup2 = context->
taskManager->createGroup();
522 persistent->tmpValues.resize(beamMajorCountNew * beamMinorCount * sampleCount);
523 total = beamMajorCountNew * beamMinorCount;
524 for (
int b = 0; b < total; b += taskSize_InterpolateMajor) {
525 context->
taskManager->enqueueChild(interpolateGroup2,
526 InterpolateBeamDataMajorTask(persistent->tmpValues.data(),
527 beamMajorCountNew, beamMinorCount, beamMinorCount, sampleCount,
528 persistent->linearValues.data(), jSamplesOut.data(),
529 b, min(b + taskSize_InterpolateMajor, total)));
534 persistent->linearValues.swap(persistent->tmpValues);
535 beamMajorCount = beamMajorCountNew;
537 elapsed_BeamResample += timerPass.elapsedSeconds();
542 if (std::isfinite(minVerticalDepth) || std::isfinite(maxVerticalDepth)) {
544 int step = (beamMajorCount + 7) / 8;
547 for (uint32_t b = 0; b < beamMajorCount; b += step) {
549 VerticalMaskTask(
this,
551 min(b + step, beamMajorCount)));
560 ivec3 Ns(sampleCount, beamMinorCount, beamMajorCount);
561 persistent->volumeCases.resize(layers * Ns.x*Ns.y*Ns.z);
562 persistent->volumeOffsets.resize(persistent->volumeCases.size());
563 persistent->wallCases.resize(layers * 2 * (Ns.x*Ns.y + Ns.x*Ns.z + Ns.y*Ns.z));
564 persistent->wallOffsets.resize(persistent->wallCases.size());
565 elapsed_Resample += timerPass.elapsedSeconds();
568 ivec3 fieldDim(sampleCount, beamMinorCount, beamMajorCount);
569 ivec3 gridA(-1, beamMinorClosed ? 0 : -1, -1);
570 ivec3 gridB = fieldDim + ivec3(1, beamMinorClosed ? 0 : 1, 1);
572 const auto M = gridB - gridA;
574 vector<int32_t> cellOffsets;
581 std::vector<TaskId> tasks;
585 TaskId initSlicesToMergeGroup = NoTask;
586 const size_t slicesToMergeModulo = beamMinorClosed ? 4 * (beamMajorCount + 1) * (sampleCount + 1) : 0;
588 if (beamMinorClosed) {
589 initSlicesToMergeGroup = context->
taskManager->createGroup();
590 const size_t chunk = std::max(slicesToMerge.size() / Threads::hardwareConcurrency(), 64 * granularity);
591 for (
size_t i = 0; i < slicesToMerge.size(); i += chunk) {
592 size_t n = std::min(chunk, slicesToMerge.size() - i);
593 context->
taskManager->enqueueChild(initSlicesToMergeGroup,
594 [ptr = slicesToMerge.data() + i, n]()
596 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"InitSlicesToMerge");
597 std::memset(ptr, ~0u, sizeof(uint32_t)* n);
604 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"Analyze");
608 vertexOffsets, indexOffsets, cellOffsets,
611 activeCellVertexIndexOffsets,
612 activeCellTriangleIndexOffsets,
617 persistent->linearValues.data(),
618 fieldDim, gridA, gridB,
621 elapsed_Analyze += timerPass.elapsedSeconds();
624 auto vertexCount = vertexOffsets.back();
625 auto indexCount = indexOffsets.back();
627 auto mesh = context->meshManager->createLocked();
631 TaskId initIndexRemappingGroup = NoTask;
633 if (vertexCount && beamMinorClosed) {
634 initIndexRemappingGroup = context->
taskManager->createGroup();
635 indexRemapping.resize(vertexCount,
false);
636 const size_t chunk = std::max(indexRemapping.size() / Threads::hardwareConcurrency(), 64 * granularity);
637 for (
size_t i = 0; i < indexRemapping.size(); i += chunk) {
638 size_t j = std::min(i + chunk, indexRemapping.size());
639 tm->enqueueChild(initIndexRemappingGroup,
640 [ptr = indexRemapping.data(), i, j]()
642 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"InitIndexRemapping");
643 for (size_t k = i; k < j; k++) {
644 ptr[k] = static_cast<uint32_t>(k);
651 if (initSlicesToMergeGroup.
isValid()) {
652 tm->wait(initSlicesToMergeGroup);
653 tm->destroy(initSlicesToMergeGroup);
656 if (0 < vertexCount) {
658 Geometry::BoundingBox bbox;
660 auto P = mesh->mapPositions(0, vertexCount+1);
661 auto N = mesh->map<vec3>(VertexDataType::Normals, VertexFormats::Norm3f, 0, vertexCount);
662 auto T = mesh->map<vec2>(VertexDataType::TexCoords0, VertexFormats::Tex2f, 0, vertexCount);
664 indices.resize(indexCount,
false);
670 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"Extract");
674 for (
size_t i = 0; i < layers; i++) {
675 VertexEmit vertexEmit;
676 vertexEmit.main =
this;
677 vertexEmit.slicesToMerge = beamMinorClosed ? slicesToMerge.data() + i * slicesToMergeModulo :
nullptr;
678 vertexEmit.slicesToMergeModulo = slicesToMergeModulo;
679 vertexEmit.vertexOffset = vertexOffsets[i];
680 vertexEmit.linearThreshold = linearThresholds[i];
681 vertexEmit.normalizedLayer = (i + 0.5f) / layers;
682 vertexEmit.maxFieldIndex = glm::max(ivec3(0), fieldDim - ivec3(1));
683 vertexEmit.P = P.data;
684 vertexEmit.T = T.data;
685 vertexEmit.separation = 2.f * capSeparation * (layers - i - 1);
686 extractVertices(context,
688 IsoSurfaces::VertexEmitFunc(vertexEmit),
689 activeCellCases.data() + cellOffsets[i],
690 activeCellVertexIndexOffsets.data() + cellOffsets[i] + i,
691 activeCellIndices.data() + cellOffsets[i],
692 activeCellIJK.data() + cellOffsets[i],
693 cellOffsets[i + 1] - cellOffsets[i],
699 for (
size_t i = 0; i < layers; i++) {
700 Cogs::Core::IsoSurfaces::IndexEmitFunc emitter;
701 if (flipOrientation ==
true) {
703 [vertexOffset = vertexOffsets[i],
704 indices = indices.data() + indexOffsets[i]]
705 (uint32_t ixIndex, glm::ivec3 ,
const uint32_t* cellIndices,
const uint32_t ixN)
707 for (uint32_t k = 0; k < ixN; k += 3) {
708 indices[ixIndex + k + 0] = cellIndices[k + 0] + vertexOffset;
709 indices[ixIndex + k + 1] = cellIndices[k + 1] + vertexOffset;
710 indices[ixIndex + k + 2] = cellIndices[k + 2] + vertexOffset;
716 [vertexOffset = vertexOffsets[i],
717 indices = indices.data() + indexOffsets[i]]
718 (uint32_t ixIndex, glm::ivec3 ,
const uint32_t* cellIndices,
const uint32_t ixN)
720 for (uint32_t k = 0; k < ixN; k += 3) {
721 indices[ixIndex + k + 0] = cellIndices[k + 0] + vertexOffset;
722 indices[ixIndex + k + 1] = cellIndices[k + 2] + vertexOffset;
723 indices[ixIndex + k + 2] = cellIndices[k + 1] + vertexOffset;
727 extractIndices(context,
730 cellMap.data() + i * M.x*M.y*M.z,
731 activeCellCases.data() + cellOffsets[i],
732 activeCellVertexIndexOffsets.data() + cellOffsets[i] + i,
733 activeCellTriangleIndexOffsets.data() + cellOffsets[i] + i,
734 activeCellIndices.data() + cellOffsets[i],
735 activeCellIJK.data() + cellOffsets[i],
736 cellOffsets[i + 1] - cellOffsets[i],
741 tm->wait(vertexExtractGroup);
742 tm->destroy(vertexExtractGroup);
743 if (initIndexRemappingGroup.
isValid()) {
744 tm->wait(initIndexRemappingGroup);
745 tm->destroy(initIndexRemappingGroup);
747 if (beamMinorClosed) {
748 size_t NN = slicesToMerge.size() / 2;
749 const size_t chunk = std::max(NN / Threads::hardwareConcurrency(), 64 * granularity);
751 for (
size_t i = 0; i < NN; i += chunk) {
752 size_t j = std::min(i + chunk, NN);
753 tm->enqueueChild(indexExtractGroup,
754 [&slicesToMerge, &indexRemapping, i, j]() {
755 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"SetIndexRemapping");
756 for (
size_t k = i; k < j; k++) {
757 if ((slicesToMerge[2 * k + 0] != ~0u) && (slicesToMerge[2 * k + 1] != ~0u)) {
758 indexRemapping[slicesToMerge[2 * k + 1]] = slicesToMerge[2 * k + 0];
765 tm->wait(indexExtractGroup);
766 tm->destroy(indexExtractGroup);
768 elapsed_Extract += timerPass.elapsedSeconds();
772 if (beamMinorClosed) {
773 TaskId remapGroup = tm->createGroup();
774 const size_t NN = indexCount;
775 const size_t chunk = std::max(indexCount / Threads::hardwareConcurrency(),
size_t(16 * granularity));
776 for (
size_t i = 0; i < NN; i += chunk) {
777 size_t j = std::min(i + chunk, NN);
778 tm->enqueueChild(remapGroup,
779 [&indices, &indexRemapping, i, j]() {
780 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"DoIndexRemapping");
781 for (
size_t k = i; k < j; k++) {
782 indices[k] = indexRemapping[indices[k]];
786 tm->wait(remapGroup);
787 tm->destroy(remapGroup);
792 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"NormalsBBox");
795 TaskId group = tm->createGroup();
796 tm->enqueueChild(group, [&]
798 auto * indicesPtr = indices.data();
799 GeometryProcessing::normalsFromIndexedTriangles(context,
800 reinterpret_cast<float*
>(N.data), 3,
801 reinterpret_cast<const float*
>(P.data), 3,
802 vertexOffsets.back(),
808 tm->enqueueChild(group, [&]
810 bbox = Cogs::Geometry::makeEmptyBoundingBox<Cogs::Geometry::BoundingBox>();
811 includeInBBox(context,
813 reinterpret_cast<const float*
>(P.data), 3,
814 vertexOffsets.back(),
821 elapsed_Normals += timerPass.elapsedSeconds();
826 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"SetupMesh");
831 mesh->setBounds(bbox);
832 mesh->setIndexData(indices.data(), indexOffsets.back());
833 auto subMeshes = mesh->mapSubMeshes(layers);
834 for (uint32_t l = 0; l < layers; l++) {
835 auto & subMesh = subMeshes[l];
836 subMesh.startIndex = indexOffsets[l];
837 subMesh.numIndexes = indexOffsets[l + 1] - indexOffsets[l];
842 elapsed_SetupMesh += timerPass.elapsedSeconds();
849 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"Store");
852 std::lock_guard<std::mutex> lock(persistent->mutex);
853 persistent->values.clear();
854 persistent->linearValues.clear();
855 persistent->volumeCases.clear();
856 persistent->volumeOffsets.clear();
857 persistent->wallCases.clear();
858 persistent->wallOffsets.clear();
859 persistent->tmpValues.clear();
860 persistent->issuedMesh = mesh.getHandle();
861 persistent->issuedPosition = metaPing.vesselPositionGlobal;
862 persistent->issuedOrientation = metaPing.vesselOrientationGlobal;
863 persistent->runningTasks--;
865 elapsed_Store += timerPass.elapsedSeconds();
868 elapsed_Total += timerTotal.elapsedSeconds();
871#ifdef COGS_AUTO_PROFILE
872 if (2.0 < elapsed_Total) {
873 double total = elapsed_Total / elapsed_Count;
874 double resize = elapsed_Resample / elapsed_Count;
875 double linearize = elapsed_Linearize / elapsed_Count;
876 double depthResample = elapsed_DepthResample / elapsed_Count;
877 double beamResample = elapsed_BeamResample / elapsed_Count;
878 double analyze = elapsed_Analyze / elapsed_Count;
879 double extract = elapsed_Extract / elapsed_Count;
880 double normals = elapsed_Normals / elapsed_Count;
881 double setupmesh = elapsed_SetupMesh / elapsed_Count;
882 double store = elapsed_Store / elapsed_Count;
883 LOG_DEBUG(logger,
"N=%d TOT=%.1f RS=%.1f L=%.1f DR=%.1f BR=%.1f A=%.1f E=%.1f N=%.3f M=%.1f S=%.1f",
888 1000.0*depthResample,
897 elapsed_Resample = 0.0;
898 elapsed_Linearize = 0.0;
899 elapsed_DepthResample = 0.0;
900 elapsed_BeamResample = 0.0;
901 elapsed_Analyze = 0.0;
902 elapsed_Extract = 0.0;
903 elapsed_Normals = 0.0;
904 elapsed_SetupMesh = 0.0;
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
constexpr Log getLogger(const char(&name)[LEN]) noexcept
void COGSFOUNDATION_API log(const char *message, const char *source, const Category category, uint32_t errorNumber)
Logs the given message with source and category.
@ ClockwiseWinding
The mesh uses clockwise winding order for it's triangles as opposed to the counter-clockwise default.
Task id struct used to identify unique Task instances.
bool isValid() const
Check if the task id is valid.
@ TriangleList
List of triangles.