5#include "Platform/Instrumentation.h"
6#include "Services/Variables.h"
7#include "Resources/MeshManager.h"
9#include "../Extensions/GeometryProcessing/GeometryProcessing.h"
10#include "../Extensions/IsoSurfaces/IsoSurfaces.h"
12#include "../BoundingBox.h"
13#include "../BeamUtils.h"
15#include "../Components/BeamGroupComponent.h"
16#include "../Systems/SwathIsoSystem.h"
18#include "../Tasks/BeamResampleTask.h"
19#include "../Tasks/SwathIsoSurfacesBuildMeshTask.h"
20#include "../Tasks/DepthResampleTask.h"
22#include "Foundation/Logging/Logger.h"
23#include "Foundation/Platform/Timer.h"
28 const glm::ivec3 taskSize_Classify = glm::ivec3(32, 16, 16);
29 const int taskSize_PopCnt = 10000;
30 const int taskSize_ExtractVtx = 10000;
31 const int taskSize_ExtractIdx = 10000;
32 const int taskSize_Normals = 10000;
33 const int taskSize_BBox = 10000;
35 int elapsed_Count = 0;
36 double elapsed_init = 0.0;
37 double elapsed_move = 0.0;
38 double elapsed_Total = 0.0;
39 double elapsed_Resample = 0.0;
40 double elapsed_Linearize = 0.0;
41 double elapsed_ClipVertical = 0.0;
42 double elapsed_Analyze = 0.0;
43 double elapsed_Extract = 0.0;
44 double elapsed_Normals = 0.0;
45 double elapsed_SetupMesh = 0.0;
47 template<
typename PContainer,
typename TContainer,
typename RayDirContainer,
typename MetaPingContainer>
54 const float threshold;
55 const float separation = 1e1f;
56 const float depthOffset;
57 const float depthStep;
59 const uint32_t vertexOffset;
60 const uint32_t uTextureDomain;
61 const uint32_t vTextureDomain;
63 const glm::ivec3 maxFieldIndex;
64 const RayDirContainer& rayDir;
65 const MetaPingContainer& metaPings;
67 VertexEmit(PContainer& P, TContainer& T,
68 const float * field,
const float threshold,
const float separation,
const float depthOffset,
const float depthStep,
const float layer,
69 const uint32_t sampleCount,
const uint32_t beamCount,
const uint32_t sliceCount,
70 const uint32_t vertexOffset,
const uint32_t uTextureDomain,
const uint32_t vTextureDomain,
71 const RayDirContainer& rayDir,
const MetaPingContainer& metaPings)
73 field(field), threshold(threshold), separation(separation), depthOffset(depthOffset), depthStep(depthStep), layer(layer),
74 Ns(sampleCount, beamCount, sliceCount),
75 maxFieldIndex(glm::max(glm::ivec3(0), glm::ivec3((int)sampleCount - 1, (int)beamCount - 1, (int)sliceCount - 1))),
76 vertexOffset(vertexOffset), uTextureDomain(uTextureDomain), vTextureDomain(vTextureDomain),
77 rayDir(rayDir), metaPings(metaPings)
80 VertexEmit(
const VertexEmit&) =
default;
82 void emit(uint32_t index, glm::ivec3 aSample, glm::ivec3 bSample)
84 glm::ivec3 I[2] = { aSample, bSample };
89 glm::vec3 positions[2];
90 for (
int m = 0; m < 2; m++) {
92 glm::ivec3 Ic = glm::clamp(Ir, glm::ivec3(0), maxFieldIndex);
94 value[m] = field[(Ic.z*Ns.y + Ic.y)*Ns.x + Ic.x];
95 linearValue[m] = value[m] - threshold;
96 depth[m] = depthOffset + Ic.x*depthStep;
98 glm::vec3 p = metaPings[Ic.z].arrayPositionGlobal + depth[m] * (metaPings[Ic.z].vesselOrientationGlobal * rayDir[Ic.y]);
102 int signed_one = Ic.x - Ir.x < 0 ? -1 : 1;
104 p -= separation * signed_one * (metaPings[Ic.z].vesselOrientationGlobal * rayDir[Ic.y]);
108 int signed_one = Ic.y - Ir.y < 0 ? -1 : 1;
111 glm::vec3 ppp = metaPings[Ic.z].arrayPositionGlobal + depth[m] * (metaPings[Ic.z].vesselOrientationGlobal * rayDir[Ic.y + signed_one]);
112 p += separation * glm::normalize(pp - ppp);
116 int signed_one = Ic.z - Ir.z < 0 ? -1 : 1;
119 glm::vec3 ppp = metaPings[Ic.z + signed_one].arrayPositionGlobal + depth[m] * (metaPings[Ic.z + signed_one].vesselOrientationGlobal * rayDir[Ic.y]);
120 p += separation * glm::normalize(pp - ppp);
125 float den = (linearValue[1] - linearValue[0]);
126 float t = glm::abs(den) < std::numeric_limits<float>::min() ? 0.5f : -linearValue[0] / den;
127 auto p = glm::mix(positions[0], positions[1], t);
129 int vo = vertexOffset + index;
133 float e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::Size)];
134 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::Zero)] = 0.f;
135 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::One)] = 1.f;
136 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::PositionX)] = p.x;
137 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::PositionY)] = p.y;
138 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::VerticalDepth)] = -p.z;
139 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::BeamDistance)] = glm::mix(depth[0], depth[1], t);
140 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::Value)] =
static_cast<float>(threshold);
141 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::LayerNormalized)] = layer;
142 e[
static_cast<uint32_t
>(Cogs::Core::EchoSounder::SwathIsoComponent::TextureDomain::Age)] = 0.f;
144 T[vo].x = e[uTextureDomain];
145 T[vo].y = e[vTextureDomain];
148 void operator()(int32_t ixIndex, glm::ivec4* samples,
const uint32_t ixN)
150 for (uint32_t k = 0; k < ixN; k++) {
152 glm::ivec3(samples[0][0],
155 glm::ivec3(samples[0][1 + k],
170 uint32_t vertexOffset;
175 IndexEmit(uint32_t vertexOffset,
180 : vertexOffset(vertexOffset), indices(indices), keepIndex(keepIndex), minZ(minZ), maxZ(maxZ)
183 IndexEmit(
const IndexEmit&) =
default;
185 void operator()(uint32_t ixIndex, glm::ivec3 cell,
const uint32_t* ix,
const uint32_t ixN)
187 for (uint32_t k = 0; k < ixN; k += 3) {
188 auto i = ixIndex + k;
190 keepIndex[i / 3] = (minZ <= cell.z) && (cell.z < maxZ);
191 if constexpr (flip ==
false) {
192 indices[i + 0] = ix[k + 0] + vertexOffset;
193 indices[i + 1] = ix[k + 1] + vertexOffset;
194 indices[i + 2] = ix[k + 2] + vertexOffset;
197 indices[i + 0] = ix[k + 0] + vertexOffset;
198 indices[i + 1] = ix[k + 2] + vertexOffset;
199 indices[i + 2] = ix[k + 1] + vertexOffset;
207Cogs::Core::EchoSounder::SwathIsoSurfacesBuildMeshTask::SwathIsoSurfacesBuildMeshTask(
Cogs::Core::Context* context,
209 const uint32_t chunkIndex,
214: SwathBuildMeshTask(context, mesh, chunkIndex, isoData.pathSpacing, isoData.beamSpacing, groupComp, dataData, isoData.resamplingPositions, isoData.chunks),
215 seabedClipOffset(isoData.seabedClipOffset),
216 useDecibel(dataData.persistent->config.useDecibel),
217 flipOrientation(isoData.flipOrientation),
218 depthSpacing(isoData.depthSpacing),
219 overflowThreshold(isoData.overflowThreshold),
220 minVerticalDepth(isoData.minVerticalDepth),
221 maxVerticalDepth(isoData.maxVerticalDepth),
222 maxDepthUpsample(context->variables->get(
"echo.maxDepthUpsample")->getFloat()),
223 depthOffset(dataData.persistent->config.depthOffset),
224 coordSys(dataData.persistent->config.coordSys),
225 depthStep(dataData.persistent->config.depthStep),
226 separation(isoComp.capSeparation),
227 sampleCount(dataData.persistent->config.sampleCount),
228 uTextureDomain(isoComp.uTextureDomain),
229 vTextureDomain(isoComp.vTextureDomain),
230 uTextureRange(isoComp.uTextureRange),
231 vTextureRange(isoComp.vTextureRange),
232 thresholds(isoData.thresholds)
235 const auto & dataConf = dataData.persistent->config;
236 const auto & buffer = dataData.persistent->buffer;
239 depths.resize(beamCount * sliceCount);
240 values.resize(sampleCount * beamCount * sliceCount);
241 arrayOrientationVessel.resize(sliceCount);
242 arrayPositionVessel.resize(sliceCount);
243 const auto beamCount_src = dataConf.beamCount;
244 for (uint32_t i = 0; i < sliceCount; i++) {
245 uint32_t k = (bix_a + i) % dataConf.capacity;
246 auto &metaPing = buffer.metaPings[k];
247 arrayOrientationVessel[i] = metaPing.arrayOrientationVessel;
248 arrayPositionVessel[i] = metaPing.arrayPositionVessel;
249 for (uint32_t j = 0; j < beamCount; j++) {
250 const auto ix = beams[j];
251 depths[beamCount*i + j] = buffer.bottomDepths[beamCount_src*k + ix];
252 std::memcpy(values.data() + sampleCount*(beamCount*i + j),
253 buffer.values.data() + sampleCount*(beamCount_src*k + ix),
254 sizeof(
float)*sampleCount);
257 elapsed_init += timer.elapsedSeconds();
260Cogs::Core::EchoSounder::SwathIsoSurfacesBuildMeshTask::SwathIsoSurfacesBuildMeshTask(
const SwathIsoSurfacesBuildMeshTask& other)
261: SwathBuildMeshTask(other),
262 seabedClipOffset(other.seabedClipOffset),
263 useDecibel(other.useDecibel),
264 flipOrientation(other.flipOrientation),
265 depthSpacing(other.depthSpacing),
266 maxDepthUpsample(other.maxDepthUpsample),
267 depthOffset(other.depthOffset),
268 coordSys(other.coordSys),
269 depthStep(other.depthStep),
270 separation(other.separation),
271 sampleCount(other.sampleCount),
272 overflowThreshold(other.overflowThreshold),
273 minVerticalDepth(other.minVerticalDepth),
274 maxVerticalDepth(other.maxVerticalDepth),
275 uTextureDomain(other.uTextureDomain),
276 vTextureDomain(other.vTextureDomain),
277 uTextureRange(other.uTextureRange),
278 vTextureRange(other.vTextureRange),
279 thresholds(other.thresholds)
283 depths.copy(other.depths);
284 values.copy(other.values);
285 arrayOrientationVessel.copy(other.arrayOrientationVessel);
286 arrayPositionVessel.copy(other.arrayPositionVessel);
287 elapsed_move += timer.elapsedSeconds();
290void Cogs::Core::EchoSounder::SwathIsoSurfacesBuildMeshTask::operator()()
293 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"SwathIsoBuildMesh");
297 std::vector<float> linearizedThresholds;
298 linearizeAndClipValues(linearizedThresholds);
299 elapsed_Linearize = timer.elapsedSeconds();
301 if (std::isfinite(minVerticalDepth) || std::isfinite(maxVerticalDepth)) {
303 elapsed_ClipVertical = timer.elapsedSeconds();
307 std::vector<glm::vec3> beamDir;
308 assert(directionX.size() == beamCount);
309 assert(directionY.size() == beamCount);
310 beamDir.resize(beamCount);
311 CalculateBeamDirectionsTask(beamDir.data(),
313 directionX.data(), directionY.data(),
314 1, beamCount, metaPings[0].arrayOrientationVessel,
320 beamResample(beamDir);
322 elapsed_Resample += timer.elapsedSeconds();
327 const auto Ns = glm::ivec3(sampleCount, beamCount, sliceCount);
328 const auto gridA = glm::ivec3(-1, -1, tail ? -1 : 0);
329 const auto gridB = glm::max(gridA, Ns + glm::ivec3(1, 1, head ? 1 : 0));
330 const auto layers =
static_cast<uint32_t
>(thresholds.size());
331 const auto M = gridB - gridA;
333 std::vector<int32_t> vertexOffsets;
334 std::vector<int32_t> indexOffsets;
335 std::vector<int32_t> cellOffsets;
343 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"Analyze");
346 vertexOffsets, indexOffsets, cellOffsets,
348 activeCellCases, activeCellVertexIndexOffsets, activeCellTriangleIndexOffsets, activeCellIndices, activeCellIJK,
349 linearizedThresholds,
true, values.data(),
352 elapsed_Analyze += timer.elapsedSeconds();
355 const auto vertexCount = vertexOffsets.back();
356 const auto indexCount = indexOffsets.back();
358 if (0 < vertexCount) {
359 auto proxyMesh = context->meshManager->createLocked();
362 Cogs::Geometry::BoundingBox bbox;
364 auto P = proxyMesh->mapPositions(0, vertexCount+1);
365 auto N = proxyMesh->map<glm::vec3>(VertexDataType::Normals, VertexFormats::Norm3f, 0, vertexCount);
366 auto T = proxyMesh->map<glm::vec2>(VertexDataType::TexCoords0, VertexFormats::Tex2f, 0, vertexCount);
368 indices.resize(indexCount,
false);
374 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"Extract");
377 auto extractGroup = context->
taskManager->createGroup();
378 for (uint32_t i = 0; i < layers; i++) {
379 IsoSurfaces::VertexEmitFunc vertexEmit = VertexEmit<decltype(P), decltype(T), decltype(beamDir), decltype(metaPings)>
381 values.data(), linearizedThresholds[i], 2.f*separation * (layers - i) , depthOffset, depthStep, (i + 0.5f) / layers,
382 sampleCount, beamCount, sliceCount,
383 vertexOffsets[i], (uint32_t)uTextureDomain, (uint32_t)vTextureDomain,
386 IsoSurfaces::extractVertices(context, extractGroup,
388 activeCellCases.data() + cellOffsets[i],
389 activeCellVertexIndexOffsets.data() + cellOffsets[i] + i,
390 activeCellIndices.data() + cellOffsets[i],
391 activeCellIJK.data() + cellOffsets[i],
392 cellOffsets[i + 1] - cellOffsets[i],
396 Cogs::Core::IsoSurfaces::IndexEmitFunc indexEmit;
397 if (flipOrientation ==
false) {
398 indexEmit = IndexEmit<false>(vertexOffsets[i],
399 indices.data() + indexOffsets[i],
400 keepIndex.data() + indexOffsets[i] / 3,
401 (
int)sliceA - (tail ? 1 : 0),
402 (
int)sliceB + (head ? 1 : 0));
405 indexEmit = IndexEmit<true>(vertexOffsets[i],
406 indices.data() + indexOffsets[i],
407 keepIndex.data() + indexOffsets[i] / 3,
408 (
int)sliceA - (tail ? 1 : 0),
409 (
int)sliceB + (head ? 1 : 0));
413 IsoSurfaces::extractIndices(context,
416 cellMap.data() + i * M.x*M.y*M.z,
417 activeCellCases.data() + cellOffsets[i],
418 activeCellVertexIndexOffsets.data() + cellOffsets[i] + i,
419 activeCellTriangleIndexOffsets.data() + cellOffsets[i] + i,
420 activeCellIndices.data() + cellOffsets[i],
421 activeCellIJK.data() + cellOffsets[i],
422 cellOffsets[i + 1] - cellOffsets[i],
430 elapsed_Extract += timer.elapsedSeconds();
434 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"NormalsBBox");
437 auto bboxGroup = context->
taskManager->createGroup();
440 bbox = Cogs::Geometry::makeEmptyBoundingBox<Cogs::Geometry::BoundingBox>();
441 includeInBBox(context,
443 reinterpret_cast<const float*
>(P.data), 3,
444 vertexOffsets.back(),
447 GeometryProcessing::normalsFromIndexedTriangles(context,
448 reinterpret_cast<float*
>(N.data), 3,
449 reinterpret_cast<const float*
>(P.data), 3,
450 vertexOffsets.back(),
457 elapsed_Normals += timer.elapsedSeconds();
462 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"SetupMesh");
465 std::vector<int32_t> prunedIndexOffsets(layers + 1);
468 auto d = indices.data();
470 for (uint32_t l = 0; l < layers; l++) {
471 for (
int i = indexOffsets[l]; i < indexOffsets[l + 1]; i += 3) {
472 if (keepIndex[i / 3]) {
473 *d++ = indices[i + 0];
474 *d++ = indices[i + 1];
475 *d++ = indices[i + 2];
478 prunedIndexOffsets[l + 1] =
static_cast<int32_t
>(d - indices.data());
480 indices.resize(prunedIndexOffsets.back());
482 proxyMesh->setBounds(bbox);
483 proxyMesh->setIndexData(indices.data(), indices.size());
484 proxyMesh->mapSubMeshes(layers);
485 for (uint32_t l = 0; l < layers; l++) {
486 auto & subMesh = proxyMesh->getSubMeshes()[l];
487 subMesh.startIndex = prunedIndexOffsets[l];
488 subMesh.numIndexes = prunedIndexOffsets[l + 1] - prunedIndexOffsets[l];
493 this->mesh = proxyMesh.getHandle();
495 elapsed_SetupMesh += timer.elapsedSeconds();
502 elapsed_Total += timerTotal.elapsedSeconds();
505#if defined(COGS_AUTO_PROFILE)
506 if (2.0 < elapsed_Total) {
507 double total = elapsed_Total / elapsed_Count;
508 double resample = elapsed_Resample / elapsed_Count;
509 double linearize = elapsed_Linearize / elapsed_Count;
510 double clipVertical = elapsed_ClipVertical / elapsed_Count;
511 double analyze = elapsed_Analyze / elapsed_Count;
512 double extract = elapsed_Extract / elapsed_Count;
513 double normals = elapsed_Normals / elapsed_Count;
514 double setupmesh = elapsed_SetupMesh / elapsed_Count;
515 LOG_DEBUG(logger,
"N=%d TOT=%.1f RS=%.1f L=%.1f CL=%.1f A=%.1f E=%.1f N=%.3f M=%.1f",
527 elapsed_Resample = 0.0;
528 elapsed_Linearize = 0.0;
529 elapsed_ClipVertical = 0.0;
530 elapsed_Analyze = 0.0;
531 elapsed_Extract = 0.0;
532 elapsed_Normals = 0.0;
533 elapsed_SetupMesh = 0.0;
540void Cogs::Core::EchoSounder::SwathIsoSurfacesBuildMeshTask::linearizeAndClipValues(std::vector<float>& linearizedThresholds)
542 static const float factorA = (float)(log2(10.0) / 10.0);
543 static const float scale_dB = 100.0f;
545 float overflowThresholdLin = std::exp2(factorA*(overflowThreshold + scale_dB));
548 for (uint32_t s = 0; s < sliceCount; s++) {
549 for (uint32_t b = 0; b < beamCount; b++) {
550 auto bottomDepth = depths[s*beamCount + b];
551 auto clipDist = bottomDepth - seabedClipOffset;
552 auto N = (bottomDepth != 0.f && std::isfinite(seabedClipOffset)) ? std::min(
static_cast<uint32_t
>(std::max(0.f, std::floor((clipDist - depthOffset) / depthStep))), sampleCount) : sampleCount;
553 for (uint32_t i = 0; i < N; i++) {
554 auto v = std::exp2(factorA*(values[(s*beamCount + b)*sampleCount + i] + scale_dB));
555 if (!std::isfinite(v)) {
556 v = v < 0.f ? 0.f : std::numeric_limits<float>::max();
558 values[(s*beamCount + b)*sampleCount + i] = v;
560 for (uint32_t i = N; i < sampleCount; i++) {
561 values[(s*beamCount + b)*sampleCount + i] = 0.f;
563 if (std::isfinite(overflowThresholdLin)) {
564 for (uint32_t i = 0; i < N; i++) {
565 float &v = values[(s*beamCount + b)*sampleCount + i];
566 if (v > overflowThresholdLin) {
574 linearizedThresholds.resize(thresholds.size());
575 for (
size_t i = 0; i < thresholds.size(); i++) {
576 auto v = std::exp2(factorA*(thresholds[i] + scale_dB));
577 if (!std::isfinite(v)) {
578 v = v < 0.f ? 0.f : std::numeric_limits<float>::max();
580 linearizedThresholds[i] = v;
585 for (uint32_t s = 0; s < sliceCount; s++) {
586 for (uint32_t b = 0; b < beamCount; b++) {
587 auto bottomDepth = depths[s*beamCount + b];
588 auto clipDist = bottomDepth - seabedClipOffset;
589 auto N = (bottomDepth != 0.f && std::isfinite(seabedClipOffset)) ? std::min(
static_cast<uint32_t
>(std::max(0.f, std::floor((clipDist - depthOffset) / depthStep))), sampleCount) : sampleCount;
590 for (uint32_t i = N; i < sampleCount; i++) {
591 values[(s*beamCount)*sampleCount + i] = 0.f;
594 if (std::isfinite(overflowThresholdLin)) {
595 for (uint32_t i = 0; i < N; i++) {
596 if (values[i] > overflowThresholdLin) {
604 linearizedThresholds = thresholds;
609void Cogs::Core::EchoSounder::SwathIsoSurfacesBuildMeshTask::clipVerticalMask()
611 const float doff = depthOffset;
612 const float dstp = depthStep;
613 const float maxRange = doff + dstp * sampleCount;
616 float minVerticalDepth1 = std::isfinite(minVerticalDepth) ? std::max(0.f, minVerticalDepth) : 0.f;
617 float maxVerticalDepth1 = std::isfinite(maxVerticalDepth) ? std::max(minVerticalDepth, maxVerticalDepth) : 10000.f;
619 std::vector<glm::vec3> relBeamDir(beamCount);
621 for (
size_t j = 0; j < beamCount; j++) {
622 relBeamDir[j] = getBeamDir(coordSys, directionX[j], directionY[j]);
625 for (
size_t k = 0; k < sliceCount; k++) {
626 std::vector<glm::vec3> vesselBeamDir(beamCount);
627 for (
size_t j = 0; j < beamCount; ++j) {
628 vesselBeamDir[j] = arrayOrientationVessel[k] * relBeamDir[j];
630 clipVertical(values, sampleCount * beamCount * k,
631 arrayPositionVessel[k], vesselBeamDir, 0,
632 minVerticalDepth1, maxVerticalDepth1,
633 depthOffset, depthStep, maxRange,
634 beamCount, sampleCount);
639void Cogs::Core::EchoSounder::SwathIsoSurfacesBuildMeshTask::depthResample()
641 if (depthSpacing == 0.f)
return;
643 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"DepthResample");
645 uint32_t sampleCountResample = std::min(10000u,
static_cast<uint32_t
>(floor((depthStep * sampleCount) / depthSpacing)));
646 floatTmp.resize(sliceCount * beamCount * sampleCountResample);
648 auto depthResampleGroup = context->
taskManager->createGroup();
649 for (uint32_t s = 0; s < sliceCount; s++) {
650 context->
taskManager->enqueueChild(depthResampleGroup, DepthResampleTask(floatTmp.data() + s * beamCount * sampleCountResample,
653 values.data() + s * beamCount * sampleCount,
661 sampleCount = sampleCountResample;
662 depthStep = depthSpacing;
663 values.swap(floatTmp);
666void Cogs::Core::EchoSounder::SwathIsoSurfacesBuildMeshTask::beamResample(std::vector<glm::vec3>& beamDir)
668 if (beamSpacing == 0.f)
return;
670 std::vector<float> minorAngles(beamCount);
671 minorAngles[0] = 0.f;
672 for (uint32_t i = 1; i < beamCount; i++) {
673 minorAngles[i] = minorAngles[i - 1] + std::acos(glm::dot(beamDir[i - 1], beamDir[i]));
675 float clampedStep = std::max(beamSpacing, abs((minorAngles.back() - minorAngles.front()) / (maxBeamUpsample*beamCount)));
677 std::vector<InterpolationSamplePos> samplesOut;
678 SetupBeamFilterUnivariate(samplesOut, minorAngles, clampedStep, beamCount);
680 uint32_t beamCountNew =
static_cast<uint32_t
>(samplesOut.size());
682 std::vector<glm::vec3> beamDirNew(beamCountNew);
683 for (uint32_t i = 0; i < beamCountNew; i++) {
684 const auto & d0 = beamDir[samplesOut[i].i + 0];
685 const auto & d1 = beamDir[samplesOut[i].i + 1];
688 const auto G = std::acos(glm::dot(d0, d1));
689 const auto t = samplesOut[i].t;
690 const auto d = (1.f / std::sin(G))*(std::sin(G*(1.f - t))*d0 + std::sin(G*t)*d1);
695 floatTmp.resize(beamCountNew * sliceCount * sampleCount);
696 auto interpolateGroup1 = context->
taskManager->createGroup();
698 for (uint32_t s = 0; s < sliceCount; s++) {
699 context->
taskManager->enqueueChild(interpolateGroup1,
700 InterpolateBeamDataMinorTask(floatTmp.data() + s* beamCountNew * sampleCount,
701 1, beamCountNew, beamCount, sampleCount,
702 values.data() + s* beamCount * sampleCount,
703 samplesOut.data(), 0, beamCountNew));
708 beamDir.swap(beamDirNew);
709 values.swap(floatTmp);
710 beamCount = beamCountNew;
714void Cogs::Core::EchoSounder::SwathIsoSurfacesBuildMeshTask::pathResample()
716 if (pathSpacing == 0.f)
return;
718 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"PathResample");
720 auto sliceCount_new =
static_cast<uint32_t
>(resamplingPositions.size());
721 decltype(metaPings) newMetaPings(sliceCount_new);
722 floatTmp.resize(sampleCount*beamCount*sliceCount_new);
724 const auto o = resamplingPositions[0].bufferIndex;
725 for (uint32_t i = 0; i < sliceCount_new; i++) {
726 const auto k = (resamplingPositions[i].bufferIndex - o + bufferCapacity) % bufferCapacity;
727 const auto t = resamplingPositions[i].fractional;
728 const auto s = (1.f - t);
730 newMetaPings[i].vesselPositionGlobal = s*metaPings[k].vesselPositionGlobal + t*metaPings[k + 1].vesselPositionGlobal;
731 newMetaPings[i].arrayPositionVessel = metaPings[k].arrayPositionVessel;
732 newMetaPings[i].arrayPositionGlobal = s*metaPings[k].arrayPositionGlobal + t*metaPings[k + 1].arrayPositionGlobal;
734 newMetaPings[i].vesselOrientationGlobal = glm::slerp(metaPings[k].vesselOrientationGlobal, metaPings[k + 1].vesselOrientationGlobal, t);
735 newMetaPings[i].arrayOrientationVessel = metaPings[k].arrayOrientationVessel;
736 newMetaPings[i].arrayOrientationGlobal = newMetaPings[i].vesselOrientationGlobal * newMetaPings[i].arrayOrientationVessel;
738 for (uint32_t j = 0; j < beamCount; j++) {
739 for (uint32_t l = 0; l < sampleCount; l++) {
740 floatTmp[(beamCount*i + j)*sampleCount + l] = s*values[(beamCount*k + j)*sampleCount + l] + t*values[(beamCount*(k + 1) + j)*sampleCount + l];
745 values.swap(floatTmp);
746 metaPings.swap(newMetaPings);
747 sliceCount = sliceCount_new;
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.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ ClockwiseWinding
The mesh uses clockwise winding order for it's triangles as opposed to the counter-clockwise default.
@ TriangleList
List of triangles.