1#define _USE_MATH_DEFINES
5#elif (defined(__GNUC__) || defined(__clang__)) && !defined(EMSCRIPTEN)
9#include "UniformGridSystem.h"
11#include "../Components/UniformGridIsoComponent.h"
14#include "EntityStore.h"
15#include "Resources/ResourceStore.h"
16#include "Resources/MaterialManager.h"
17#include "Resources/MeshManager.h"
18#include "Resources/TextureManager.h"
19#include "Components/Core/SceneComponent.h"
20#include "Components/Core/TransformComponent.h"
21#include "Components/Core/MeshComponent.h"
22#include "Components/Core/MeshRenderComponent.h"
23#include "Components/Core/SubMeshRenderComponent.h"
25#include "Resources/Mesh.h"
26#include "Services/Features.h"
28#include "../BeamUtils.h"
30#include "Foundation/Logging/Logger.h"
31#include "Foundation/Platform/Timer.h"
51#elif defined(__GNUC__) || defined(__clang__)
52 __get_cpuid(level, &eax, &ebx, &ecx, &edx);
54#error "implement cpuid for this compiler"
57 uint32_t eax, ebx, ecx, edx;
60 float dbToLinear(
float v)
62 float w = powf(10.0f, v*(1.0f/20.0f));
64 w = v < 0.f ? 0.f : std::numeric_limits<float>::max();
70namespace Cogs::Core::EchoSounder {
72 void sampleTile_border_sse41(
float * data,
74 const glm::vec3 tileIndex,
75 const glm::uvec3 tilePos,
76 const glm::uvec3 dataSize,
77 const glm::uvec3 maxIndices,
79 const glm::vec3 scale,
80 const glm::vec3 arrayPositionGlobal,
81 const glm::vec4* frustum,
82 const float minDistanceSquared,
83 const float maxDistanceSquared,
84 const glm::quat inverseOrientation,
85 const uint32_t coordSys,
86 const uint32_t minorCount,
87 const uint32_t sampleCount,
88 const glm::vec3 polarScale,
89 const glm::vec3 polarShift);
91 void sampleTile_inner_sse41(
float * data,
93 const glm::vec3 tileIndex,
94 const glm::uvec3 tilePos,
95 const glm::uvec3 dataSize,
96 const glm::uvec3 maxIndices,
98 const glm::vec3 scale,
99 const glm::vec3 arrayPositionGlobal,
100 const glm::vec4* frustum,
101 const float minDistanceSquared,
102 const float maxDistanceSquared,
103 const glm::quat inverseOrientation,
104 const uint32_t coordSys,
105 const uint32_t minorCount,
106 const uint32_t sampleCount,
107 const glm::vec3 polarScale,
108 const glm::vec3 polarShift);
110 void sampleTile_inner_fma_gather(
float * data,
112 const glm::vec3 tileIndex,
113 const glm::uvec3 tilePos,
114 const glm::uvec3 dataSize,
115 const glm::uvec3 maxIndices,
117 const glm::vec3 scale,
118 const glm::vec3 arrayPositionGlobal,
119 const glm::vec4* frustum,
120 const float minDistanceSquared,
121 const float maxDistanceSquared,
122 const glm::quat inverseOrientation,
123 const uint32_t coordSys,
124 const uint32_t minorCount,
125 const uint32_t sampleCount,
126 const glm::vec3 polarScale,
127 const glm::vec3 polarShift);
129 void sampleTile3_avx2(
float * data,
133 const glm::vec3 tileIndex,
134 const glm::uvec3 tilePos,
135 const glm::uvec3 dataSize,
136 const glm::uvec3 maxIndices,
138 const glm::vec3 scale,
139 const glm::vec3 arrayPositionGlobal,
140 const glm::vec4* frustum,
141 const float minDistanceSquared,
142 const float maxDistanceSquared,
143 const glm::quat inverseOrientation,
144 const uint32_t coordSys,
145 const uint32_t minorCount,
146 const uint32_t sampleCount,
147 const glm::vec3 polarScale,
148 const glm::vec3 polarShift);
150 void sampleTile3_border_avx2(
float * data,
154 const glm::vec3 tileIndex,
155 const glm::uvec3 tilePos,
156 const glm::uvec3 dataSize,
157 const glm::uvec3 maxIndices,
159 const glm::vec3 scale,
160 const glm::vec3 arrayPositionGlobal,
161 const glm::vec4* frustum,
162 const float minDistanceSquared,
163 const float maxDistanceSquared,
164 const glm::quat inverseOrientation,
165 const uint32_t coordSys,
166 const uint32_t minorCount,
167 const uint32_t sampleCount,
168 const glm::vec3 polarScale,
169 const glm::vec3 polarShift);
171 MeshHandle createIsoSurfacesReference(Context* context,
177 const glm::uvec3 layout,
178 const glm::vec3 minCorner,
179 const glm::vec3 maxCorner,
180 const float *thresholds,
size_t count);
182 MeshHandle createIsoSurfacesAVX2(Context* context,
188 const glm::uvec3 gridLayout,
189 const glm::vec3 minCorner,
190 const glm::vec3 maxCorner,
191 const float *thresholds,
size_t count);
193 MeshHandle createIsoSurfacesSplitAVX2(Context* context,
199 const glm::uvec3 gridLayout,
200 const glm::vec3 minCorner,
201 const glm::vec3 maxCorner,
202 const float *thresholds,
size_t count);
206 Context* context = system->
context;
209 float *thresholds = this->thresholds.data();
210 size_t count = this->thresholds.size();
211 std::vector<float> t(count);
212 for(uint32_t i=0; i<count; i++) t[i] = dbToLinear(thresholds[i]);
213 if (!count || tile.maxValue <= t[0] || t[count-1] <= tile.minValue)
return mesh;
215 const glm::vec3 maxCorner = minCorner + glm::vec3(size)*scale;
217 uint64_t analyze = 0;
221 case ComputeType::Reference:
222 case ComputeType::SSE41:
223 case ComputeType::FMA:
224 mesh = createIsoSurfacesReference(context, analyze, vtx, idx,
227 minCorner, maxCorner,
230 case ComputeType::AVX2:
232 mesh = createIsoSurfacesSplitAVX2(context, analyze, vtx, idx,
235 minCorner, maxCorner,
239 mesh = createIsoSurfacesAVX2(context, analyze, vtx, idx,
242 minCorner, maxCorner,
246 isoSurf.analyze.fetch_add(uint32_t(analyze));
247 isoSurf.vtx.fetch_add(uint32_t(vtx));
248 isoSurf.idx.fetch_add(uint32_t(idx));
249 isoSurf.N.fetch_add(1);
252 glm::vec3 getSamplePosRef(
const glm::uvec3 ,
253 const glm::vec3 tilePos,
254 const glm::vec3 scale,
255 const glm::vec3 arrayPositionGlobal,
256 const glm::vec4* frustum,
257 const float minDistanceSquared,
258 const float maxDistanceSquared,
259 const glm::quat inverseOrientation,
260 const uint32_t coordSys,
261 const glm::vec3 polarScale,
262 const glm::vec3 polarShift,
267 glm::vec3 p = scale * glm::vec3(x, y, z);
268 glm::vec3 q = (tilePos - arrayPositionGlobal) + p;
269 float r2 = glm::dot(q, q);
271 bool in_0 = 0.f <= glm::dot(glm::vec3(frustum[0]), q);
272 bool in_1 = 0.f <= glm::dot(glm::vec3(frustum[1]), q);
273 bool in_2 = 0.f <= glm::dot(glm::vec3(frustum[2]), q);
274 bool in_3 = 0.f <= glm::dot(glm::vec3(frustum[3]), q);
275 bool in_4 = minDistanceSquared <= r2;
276 bool in_5 = r2 <= maxDistanceSquared;
277 if (!in_0 || !in_1 || !in_2 || !in_3 || !in_4 || !in_5)
return glm::vec3(-1.f);
279 glm::vec3 a = inverseOrientation * q;
280 float r = std::sqrt(r2);
284 float dirX = std::asin(a.x / r);
285 float dirY = std::asin(a.y / r);
286 polarPos = glm::vec3(dirY, dirX, r);
288 else if (coordSys == 1) {
289 float dirX = std::asin(a.x / r);
290 float dirY = std::atan(a.y / a.z);
291 polarPos = glm::vec3(dirY, dirX, a.z);
293 glm::vec3 xi = glm::max(glm::vec3(0.f), polarScale*(polarPos - polarShift));
302 CpuId level1(0x00000001u);
303 has_sse41 = level1.ecx & (1u << 19u);
304 bool osxsave = level1.ecx & (1u << 27u);
307 CpuId level7(0x00000007u);
308 has_avx2 = level7.ebx & (1u << 5u);
310 if(has_sse41) LOG_INFO(logger,
"Has SSE41");
311 if(has_avx2) LOG_INFO(logger,
"Has AVX2");
313 Queue = context->
taskManager->createQueue(
"EchoSounder", Threads::hardwareConcurrency()-1);
315 point_material = context->materialManager->loadMaterial(
"UniformGridPoint.material");
316 context->materialManager->processLoading();
317 point_instance = context->materialInstanceManager->createMaterialInstance(point_material);
318 float pointSize = 16.0f;
319 point_instance->setProperty(
"pointSize", &pointSize,
sizeof(
float));
320 point_instance->setOption(
"BlendMode",
"Blend");
321 point_instance->setupInstance(point_material.resolve());
326 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::preUpdate");
327 static std::vector<uint32_t> pointTransferData = {
328 0x00888888, 0xff888888, 0xff888888, 0xff888888,
329 0xffFF3300, 0xffFF3300, 0xffFF3300, 0xffFF3300,
330 0xff00DD00, 0xff00DD00, 0xff00DD00, 0xff00DD00,
331 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF,
333 for (
auto & component : pool) {
335 bool update_all = data.decibelMin != component.decibelMin || data.decibelMax != component.decibelMax;
336 if(!data.visualizer_group){
337 data.visualizer_group = context->
store->
createChildEntity(
"Group", component.getContainer(),
"VisualizerGroup");
340 data.decibelMin = component.decibelMin;
341 data.decibelMax = component.decibelMax;
343 update_outline(context, &component);
345 data.compute = component.compute;
350 if(iso_component->thresholds.size() != data.thresholds.size()){
351 data.thresholds = iso_component->thresholds;
354 for(
size_t i=0; i<iso_component->thresholds.size(); i++){
355 if(iso_component->thresholds[i] != data.thresholds[i]){
356 data.thresholds = iso_component->thresholds;
363 const float fmin = std::numeric_limits<float>::min();
364 glm::vec4 range(iso_component->uTextureRange.x,
365 1.f / std::max(fmin, iso_component->uTextureRange.y - iso_component->uTextureRange.x),
366 iso_component->vTextureRange.x,
367 1.f / std::max(fmin, iso_component->vTextureRange.y - iso_component->vTextureRange.x));
371 size_t count = iso_component->thresholds.size();
372 if(!data.layerMaterialInstances.size()) data.layerMaterialInstances.resize(count);
373 for(uint32_t i=0; i<count; i++){
375 if(!instance) instance = context->materialInstanceManager->createMaterialInstance(iso_component->material);
377 if(i == count-1 && iso_component->innerLayerOpaque){
387 const float fmin = std::numeric_limits<float>::min();
388 glm::vec4 range(iso_component->uTextureRange.x,
389 1.f / std::max(fmin, iso_component->uTextureRange.y - iso_component->uTextureRange.x),
390 iso_component->vTextureRange.x,
391 1.f / std::max(fmin, iso_component->vTextureRange.y - iso_component->vTextureRange.x));
397 std::unique_lock<
decltype(data.tiles_mu)> lock(data.tiles_mu, std::defer_lock);
398 if(!lock.try_lock())
continue;
400 for(
auto &tmp : data.destroy)
402 data.destroy.clear();
403 for(
auto &tmp : data.tiles){
404 TileKey key = tmp.first;
405 Tile &tile = tmp.second;
407 if(update_all) data.change_sv =
true;
408 if(tile.update &&
HandleIsValid(tile.mesh) && tile.mesh->isActive() && iso_component){
410 if (!tile.visualizer) {
411 tile.visualizer = context->
store->
createChildEntity(
"EchoUniformGridIsoVisualizer", data.visualizer_group.get(),
"UniformGridIsoVisualizer");
414 glm::uvec3 tileIndex(decodeTileKey(key));
415 glm::vec3 tileCoord(glm::vec3(tileIndex)-glm::vec3(1<<15));
416 glm::vec3 tilePos = tileCoord*(glm::vec3(data.size-glm::uvec3(1))*data.scale);
417 tComp->position = tilePos;
418 tComp->scale = data.scale;
421 if (src) src->
materials = data.layerMaterialInstances;
427 if (tile.visualizer) {
432 context->
store->
removeChild(data.visualizer_group.get(), tile.visualizer.get());
433 tile.visualizer.reset();
437 if (tile.update || update_all) {
439 if (!tile.visualizer) {
440 tile.visualizer = context->
store->
createChildEntity(
"EchoUniformGridPointVisualizer", data.visualizer_group.get(),
"UniformGridPointVisualizer");
442 auto task = [
this, &context, &data, key, &tile]() {
443 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::pointVizTask");
444 float valueMin = dbToLinear(data.decibelMin);
445 float valueMax = dbToLinear(data.decibelMax);
446 float valueScale = 1.0f / (valueMax - valueMin);
447 std::vector<glm::vec3> positions;
448 std::vector<glm::vec4> colors;
449 size_t t_size = pointTransferData.size();
450 float cinv = 1.0f / 255.0f;
451 for (uint32_t z = 0; z < data.size.z; z += viz_z_div) {
452 for (uint32_t y = 0; y < data.size.y; y += viz_y_div) {
453 for (uint32_t x = 0; x < data.size.x; x += viz_x_div) {
454 uint32_t index = z * data.size.y*data.size.x + y * data.size.x + x;
455 float val = glm::clamp<float>(valueScale*tile.data[index], 0.0f, 1.0f);
456 float vali = val * (t_size - 1);
457 float a = vali - floor(vali);
458 uint32_t il = glm::clamp<uint32_t>((uint32_t)floor(vali), 0, t_size);
459 uint32_t iu = glm::clamp<uint32_t>((uint32_t)ceil(vali), 0, t_size);
460 uint32_t cl = pointTransferData[il];
461 uint32_t cu = pointTransferData[iu];
462 glm::vec4 coll(((cl>>0)&0xff)*cinv, ((cl>>8)&0xff)*cinv,
463 ((cl>>16)&0xff)*cinv, ((cl>>24)&0xff)*cinv);
464 glm::vec4 colu(((cu>>0)&0xff)*cinv, ((cu>>8)&0xff)*cinv,
465 ((cu>>16)&0xff)*cinv, ((cu>>24)&0xff)*cinv);
466 glm::vec4 color = glm::mix(coll, colu, a);
467 colors.push_back(color);
468 positions.push_back(glm::vec3(x, y, z)*data.scale);
473 glm::uvec3 tileIndex(decodeTileKey(key));
474 glm::vec3 tileCoord(glm::vec3(tileIndex)-glm::vec3(1<<15));
475 glm::vec3 tilePos = tileCoord*(glm::vec3(data.size-glm::uvec3(1))*data.scale);
476 tComp->position = tilePos;
480 auto mesh = context->meshManager->createLocked();
482 mesh->set(VertexDataType::Positions, &VertexFormats::Pos3f, positions.data(), positions.data() + positions.size());
483 mesh->set(VertexDataType::Colors0, &VertexFormats::Color4f, colors.data(), colors.data() + colors.size());
485 mc->meshHandle = mesh.getHandle();
497 if (!component->show_frustum){
498 for(
auto &tmp : data.boundingFrustum){
502 meshComp->setChanged();
506 for(
auto &tmp : data.config){
507 uint32_t
id = tmp.first;
508 UniformGridConfig &config(*tmp.second);
510 if(!data.boundingFrustum.count(
id)){
512 data.boundingFrustum[id] = entity;
514 auto mat = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
515 mat->setPermutation(
"Line");
516 mat->setVariant(
"LightModel",
"BaseColor");
517 mat->setVariant(
"EnableLighting",
false);
518 mat->setVariant(
"VertexColor",
true);
520 auto *matRndComp = entity->getComponent<MeshRenderComponent>();
521 matRndComp->material = mat;
523 matRndComp->setChanged();
527 auto * trComp = entity->getComponent<TransformComponent>();
528 trComp->rotation = data.vesselOrientationGlobal;
529 trComp->position = data.vesselPositionGlobal;
530 trComp->setChanged();
532 glm::quat arrayOrientationVessel;
533 glm::vec3 arrayPositionVessel;
534 getArrayToVesselTransform(arrayOrientationVessel,
536 config.transducerAlpha,
537 config.transducerOffset);
539 float minDistance = config.depthOffset;
540 float maxDistance = minDistance + config.sampleCount * config.depthStep;
542 uint32_t beamCount = config.majorCount*config.minorCount;
544 float minDirectionX = std::numeric_limits<float>::max();
545 float maxDirectionX = -std::numeric_limits<float>::max();
546 float minDirectionY = std::numeric_limits<float>::max();
547 float maxDirectionY = -std::numeric_limits<float>::max();
548 float maxBeamWidthX = -std::numeric_limits<float>::max();
549 float maxBeamWidthY = -std::numeric_limits<float>::max();
550 for(uint32_t i=0; i<beamCount; i++){
551 maxDirectionX = glm::max(maxDirectionX, config.directionX[i]);
552 minDirectionX = glm::min(minDirectionX, config.directionX[i]);
553 maxDirectionY = glm::max(maxDirectionY, config.directionY[i]);
554 minDirectionY = glm::min(minDirectionY, config.directionY[i]);
555 maxBeamWidthX = glm::max(maxBeamWidthX, config.beamWidthX[i]);
556 maxBeamWidthY = glm::max(maxBeamWidthY, config.beamWidthY[i]);
559 if (config.majorCount == 1) {
560 minDirectionX -= 0.5f*maxBeamWidthX;
561 maxDirectionX += 0.5f*maxBeamWidthX;
563 if (config.minorCount == 1) {
564 minDirectionY -= 0.5f*maxBeamWidthY;
565 maxDirectionY += 0.5f*maxBeamWidthY;
568 auto * meshComp = entity->getComponent<MeshComponent>();
569 glm::vec4 frustum[6];
570 getBoundingFrustum(frustum,
571 arrayOrientationVessel,
574 minDirectionX, maxDirectionX,
575 minDirectionY, maxDirectionY,
576 minDistance, maxDistance);
577 meshComp->meshHandle = buildFrustumOutline(context, frustum);
578 meshComp->setChanged();
581void Cogs::Core::EchoSounder::UniformGridSystem::config(UniformGridComponent *component, UniformGridConfig &config)
583 UniformGridData &data = getData(component);
584 std::unique_lock<
decltype(data.mu)> lock(data.mu);
585 uint32_t
id = config.configId;
586 data.config[id] = std::make_shared<UniformGridConfig>(std::move(config));
588void Cogs::Core::EchoSounder::UniformGridSystem::clear(UniformGridComponent *component)
590 UniformGridData &data = getData(component);
591 std::unique_lock<
decltype(data.mu)> lock(data.mu);
592 for(
auto &tmp : data.tiles){
593 _aligned_free(tmp.second.data);
594 Entity *ptr = tmp.second.visualizer.get();
601 constexpr float PI = float(M_PI);
602 if(x < 1e-5)
return 1.0f;
603 return sinf(PI*x)/(PI*x);
605float Lanczos(
float x,
float tau)
607 return Sinc(x) * Sinc(x/tau);
609void Cogs::Core::EchoSounder::UniformGridSampleData::filter_ping()
611 float w = filter_width;
613 float a = filter_falloff;
614 int32_t iwidth = 1 + int32_t(floor(r))*2;
615 int32_t ihalf = iwidth/2;
616 if(iwidth < 3 || a == 0.0f)
return;
618 std::vector<float> weights(iwidth, 0.0f);
619 for(int32_t t=0; t<iwidth; t++){
626 weights[t] = std::exp(-a*(x*x))-std::exp(-a*(r*r));
633 for(int32_t t=0; t<iwidth; t++)
635 for(int32_t t=0; t<iwidth; t++)
636 weights[t] = (
float)(weights[t]/sum);
637 assert(std::isnormal(sum));
638 Memory::TypedBuffer<float> linear_resampled;
639 uint32_t beamCount = config->majorCount*config->minorCount;
640 uint32_t sampleCount = config->sampleCount;
641 linear_resampled.resize(beamCount*sampleCount,
false);
642 for(uint32_t b=0; b<beamCount; b++){
643 uint32_t off = b*sampleCount;
644 for(uint32_t s=0; s<sampleCount; s++){
647 int32_t st = glm::clamp((int32_t)s-ihalf, (int32_t)0, (int32_t)sampleCount-1);
648 avg = linear[off+st]*weights[0];
650 for(int32_t t=1; t<iwidth; t++){
651 int32_t st = glm::clamp((int32_t)s+t-ihalf, (int32_t)0, (int32_t)sampleCount-1);
652 avg += linear[off+st]*weights[t];
654 linear_resampled[off+s] = avg;
657 data.sample_data->linear.swap(linear_resampled);
665 data.component = component;
667 auto task = [
this, con, component](){ this->dispatch(con, component); };
675 data.shutdown =
true;
677 std::unique_lock<
decltype(data.mu)> lock(data.mu);
684 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::dispatch");
688 if(data.change_sv || data.update_iso){
689 std::unique_lock<
decltype(data.tiles_mu)> lock(data.tiles_mu);
691 data.change_sv =
false;
692 for(
auto &tmp1 : data.tiles)
693 tmp1.second.update_iso =
true;
694 data.update_iso =
true;
696 data.update_iso = data.update_isosurface();
700 if(data.sample_data){
701 using clock = std::chrono::high_resolution_clock;
702 auto t0 = clock::now();
704 std::unique_lock<
decltype(data.tiles_mu)> lock(data.tiles_mu);
705 if((component->size != data.size || component->scale != data.scale) &&
706 component->scale.x > 0.0f && component->scale.y > 0.0f && component->scale.z > 0.0f){
707 data.size = component->size;
708 data.scale = component->scale;
710 for(
auto &tmp : data.tiles){
711 _aligned_free(tmp.second.data);
712 Entity *ptr = tmp.second.visualizer.get();
713 if(ptr) data.destroy.push_back(ptr);
718 data.sample_data->evict_tiles();
720 data.sample_data->cull_tiles();
721 data.sample_data->gen_tiles();
725 context->
taskManager->wait(data.sample_data->linear_group);
726 data.sample_data->filter_ping();
728 auto group = context->
taskManager->createGroup(Queue);
729 size_t concurrency = Threads::hardwareConcurrency()-1;
731 if(data.sample_data->tiles_inside.size()){
732 size_t tile_count = (size_t)data.sample_data->tiles_inside.size();
733 size_t task_count = std::min(tile_count, concurrency);
734 size_t steps = tile_count/task_count+1;
735 for(
size_t i=0; i<tile_count; i+=steps){
736 size_t end = std::min(i+steps, tile_count);
737 auto task = [sample_data=data.sample_data, i, end](){ sample_data->sample_inside(i, end); };
741 if(data.sample_data->tiles_intersecting.size()){
742 size_t tile_count = (size_t)data.sample_data->tiles_intersecting.size();
743 size_t task_count = std::min(tile_count, concurrency);
744 size_t steps = tile_count/task_count+1;
745 for(
size_t i=0; i<tile_count; i+=steps){
746 size_t end = std::min(i+steps, tile_count);
747 auto task = [sample_data=data.sample_data, i, end](){ sample_data->sample_intersecting(i, end); };
754 const char* s =
"REF";
755 switch (data.sample_data->compute) {
756 case ComputeType::SSE41: s =
"SSE41";
break;
757 case ComputeType::FMA: s =
"FMA";
break;
758 case ComputeType::AVX2: s =
"AVX2";
break;
762 float N_tot = (float)(data.sample_intersecting.N + data.sample_inside.N);
763 if (data.runs == 9) {
764 auto threadTimeToWallTime = 1.f / (Threads::hardwareConcurrency() - 1);
766 LOG_DEBUG(logger,
"%s: sample_b %.2fms (%.3fms) sample_i %.2fms (%.3fms) pop=%.1f%% iso %.2fms (%.3fms/%.3fms/%.3fms)",
768 threadTimeToWallTime*(1.f / 1000.f) * data.sample_intersecting.us,
769 ((1.f / 1000.f) * data.sample_intersecting.us) / data.sample_intersecting.N,
770 threadTimeToWallTime*(1.f / 1000.f) * data.sample_inside.us,
771 ((1.f / 1000.f) * data.sample_inside.us) / data.sample_inside.N,
772 (100.f*data.isoSurf.N) / N_tot,
773 threadTimeToWallTime*(1.f / 1000.f) *(data.isoSurf.analyze + data.isoSurf.vtx + data.isoSurf.idx),
774 ((1.f / 1000.f) * data.isoSurf.analyze) / data.isoSurf.N,
775 ((1.f / 1000.f) * data.isoSurf.vtx) / data.isoSurf.N,
776 ((1.f / 1000.f) * data.isoSurf.idx) / data.isoSurf.N);
778 data.sample_intersecting.us = 0;
779 data.sample_intersecting.N = 0;
780 data.sample_inside.us = 0;
781 data.sample_inside.N = 0;
782 data.isoSurf.analyze = 0;
783 data.isoSurf.vtx = 0;
784 data.isoSurf.idx = 0;
790 auto t1 = clock::now();
791 LOG_DEBUG(logger,
"add_point %.4f s (%.2f ms) size (%d, %d, %d) scale (%.3f, %.3f, %.3f)",
792 std::chrono::duration<float>(t1-t0).count(),
793 std::chrono::duration<float, std::milli>(t1-t0).count(),
794 data.size.x, data.size.y, data.size.z,
795 data.scale.x, data.scale.y, data.scale.z);
797 std::unique_lock<
decltype(data.mu)> lock(data.mu);
798 delete data.sample_data;
799 data.sample_data =
nullptr;
800 if(data.sample_data_backbuffer){
801 data.sample_data = data.sample_data_backbuffer;
802 data.vesselOrientationGlobal = data.sample_data->vesselOrientationGlobal;
803 data.vesselPositionGlobal = data.sample_data->vesselPositionGlobal;
804 data.sample_data_backbuffer =
nullptr;
809 if(!data.update_iso) std::this_thread::sleep_for(std::chrono::milliseconds(8));
810 auto task = [
this, context, component](){ this->dispatch(context, component); };
814 data.cv.notify_all();
817void Cogs::Core::EchoSounder::UniformGridSystem::addPing(Context * context, UniformGridComponent *component, UniformGridPing &ping)
819 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::addPing");
820 uint64_t ping_number;
821 UniformGridData &data = getData(component);
823 std::unique_lock<
decltype(data.mu)> lock(data.mu);
824 ping_number = data.ping_number++;
825 if(data.sample_data && data.sample_data_backbuffer){
826 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::drop_ping");
828 LOG_DEBUG(logger,
"Dropping ping (Handled: %llu Droped: %llu)", data.pings_handled, data.pings_droped);
831 data.pings_handled++;
832 UniformGridSampleData *sample_data =
new UniformGridSampleData(context,
this, component, data, ping, ping_number);
833 if(!data.sample_data){
834 data.sample_data = sample_data;
835 data.vesselOrientationGlobal = sample_data->vesselOrientationGlobal;
836 data.vesselPositionGlobal = sample_data->vesselPositionGlobal;
839 data.sample_data_backbuffer = sample_data;
842Cogs::Core::EchoSounder::UniformGridSampleData::UniformGridSampleData(Context *context, UniformGridSystem *system, UniformGridComponent *component, UniformGridData &data, UniformGridPing &ping, uint64_t ping_number):
845 component(component),
847 config(data.config[ping.configId]),
848 average_alpha(component->average_alpha),
849 filter_width(component->filter_width),
850 filter_falloff(component->filter_falloff),
851 ping_number(ping_number)
853 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::UniformGridSampleData");
855 if(component->compute == ComputeType::AVX2 && !system->has_avx2)
856 component->compute = ComputeType::SSE41;
857 if(component->compute == ComputeType::AVX2 && !system->has_sse41)
858 component->compute = ComputeType::Reference;
859 compute = component->compute;
861 vesselOrientationGlobal = ping.orientation;
862 vesselPositionGlobal = ping.position;
863 glm::quat arrayOrientationVessel;
864 glm::vec3 arrayPositionVessel;
865 getArrayToVesselTransform(arrayOrientationVessel,
867 config->transducerAlpha,
868 config->transducerOffset);
869 arrayOrientationGlobal = vesselOrientationGlobal * arrayOrientationVessel;
870 arrayPositionGlobal = vesselPositionGlobal + vesselOrientationGlobal * arrayPositionVessel;
872 inverseOrientation = glm::inverse(arrayOrientationGlobal);
874 minDistance = config->depthOffset;
875 maxDistance = minDistance + config->sampleCount * config->depthStep;
877 minDistanceSquared = minDistance * minDistance;
878 maxDistanceSquared = maxDistance * maxDistance;
880 majorCount = config->majorCount;
881 minorCount = config->minorCount;
882 uint32_t beamCount = majorCount * minorCount;
884 float minDirectionX = std::numeric_limits<float>::max();
885 float maxDirectionX = -std::numeric_limits<float>::max();
886 float minDirectionY = std::numeric_limits<float>::max();
887 float maxDirectionY = -std::numeric_limits<float>::max();
888 float maxBeamWidthX = -std::numeric_limits<float>::max();
889 float maxBeamWidthY = -std::numeric_limits<float>::max();
890 for(uint32_t i = 0; i<beamCount; i++){
891 maxDirectionX = glm::max(maxDirectionX, config->directionX[i]);
892 minDirectionX = glm::min(minDirectionX, config->directionX[i]);
893 maxDirectionY = glm::max(maxDirectionY, config->directionY[i]);
894 minDirectionY = glm::min(minDirectionY, config->directionY[i]);
895 maxBeamWidthX = glm::max(maxBeamWidthX, config->beamWidthX[i]);
896 maxBeamWidthY = glm::max(maxBeamWidthY, config->beamWidthY[i]);
899 if (majorCount == 1) {
900 minDirectionX -= 0.5f*maxBeamWidthX;
901 maxDirectionX += 0.5f*maxBeamWidthX;
903 if (minorCount == 1) {
904 minDirectionY -= 0.5f*maxBeamWidthY;
905 maxDirectionY += 0.5f*maxBeamWidthY;
909 getBoundingFrustum(frustum,
910 arrayOrientationGlobal,
913 minDirectionX, maxDirectionX,
914 minDirectionY, maxDirectionY,
915 minDistance, maxDistance);
917 maxIndices = glm::uvec3(glm::max(1u, minorCount) - 1u,
918 glm::max(1u, majorCount) - 1u,
919 glm::max(1u, config->sampleCount) - 1u);
920 polarShift = glm::vec3(minDirectionY, minDirectionX, minDistance);
921 polarScale = glm::vec3((glm::max(2u, minorCount) - 2u) / (maxDirectionY - minDirectionY),
922 (glm::max(2u, majorCount) - 2u) / (maxDirectionX - minDirectionX),
923 (glm::max(2u, config->sampleCount) - 2u) / (maxDistance - minDistance));
927 size_t concurrency = Threads::hardwareConcurrency()-2;
928 uint32_t sampleCount = config->sampleCount;
929 uint32_t steps = (uint32_t)((beamCount*sampleCount)/concurrency+1);
931 decibel = std::move(ping.storage);
932 linear.resize(beamCount*sampleCount,
false);
933 for(uint32_t i=0; i<beamCount*sampleCount; i+=steps){
934 uint32_t end = std::min(i+steps, beamCount*sampleCount);
935 auto task = [
this, start=i, end](){
936 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::dBToLinearTask");
937 float *db = (
float*)decibel.data();
938 for(uint32_t i=start; i<end; i++){
939 linear[i] = glm::clamp(dbToLinear(db[i]), 0.0f, 1.0f);
951static int FrustrumAABBIntersect(glm::vec4 *frustum,
float minDistanceSquared,
float maxDistanceSquared, glm::vec3 &min, glm::vec3 &max,
float r2min,
float r2max)
954 for(uint32_t i=0; i<4; i++){
955 glm::vec3 vmin, vmax;
956 if(frustum[i].x < 0) {
963 if(frustum[i].y < 0) {
970 if(frustum[i].z < 0) {
977 if(glm::dot(glm::vec3(frustum[i]), vmin) < 0.0f)
979 if(glm::dot(glm::vec3(frustum[i]), vmax) <= 0.0f)
983 if(r2min > maxDistanceSquared)
return OUTSIDE;
984 else if(r2max >= maxDistanceSquared) ret = INTERSECTION;
987 if(r2max < minDistanceSquared)
return OUTSIDE;
988 else if(r2min <= minDistanceSquared) ret = INTERSECTION;
992void Cogs::Core::EchoSounder::UniformGridSampleData::cull_tiles()
995 glm::vec3 aabb_min(std::numeric_limits<float>::max());
996 glm::vec3 aabb_max(-std::numeric_limits<float>::max());
997 uint32_t beamCount = minorCount * majorCount;
998 for(uint32_t i=0; i<beamCount; i++){
999 glm::vec3 d = arrayOrientationGlobal * getBeamDir(config->coordSys, config->directionX[i], config->directionY[i]);
1000 glm::vec3 min = d * minDistance + arrayPositionGlobal;
1001 glm::vec3 max = d * maxDistance + arrayPositionGlobal;
1002 aabb_min = glm::min(aabb_min, min);
1003 aabb_min = glm::min(aabb_min, max);
1004 aabb_max = glm::max(aabb_max, min);
1005 aabb_max = glm::max(aabb_max, max);
1008 glm::vec3 invSize = glm::vec3(1.0f)/glm::vec3(data.size-glm::uvec3(1));
1009 glm::vec3 invScale = glm::vec3(1.0f)/data.scale;
1011 glm::ivec3 imin = glm::floor(aabb_min*invScale*invSize);
1012 glm::ivec3 imax = glm::ceil(aabb_max*invScale*invSize);
1013 imin-=glm::ivec3(2);
1014 imax+=glm::ivec3(2);
1017 for(int32_t tx=imin.x; tx<=imax.x; tx++){
1018 for(int32_t ty=imin.y; ty<=imax.y; ty++){
1019 for(int32_t tz=imin.z; tz<=imax.z; tz++){
1020 glm::vec3 tileCoord(tx, ty, tz);
1021 glm::vec3 tilePos = tileCoord*(glm::vec3(data.size-glm::uvec3(1))*data.scale);
1022 glm::vec3 q_a = tilePos - arrayPositionGlobal;
1023 glm::vec3 q_b = q_a + glm::vec3(data.size-glm::uvec3(1)) * data.scale;
1024 glm::vec3 q_min = glm::min(q_a, q_b);
1025 glm::vec3 q_max = glm::max(q_a, q_b);
1027 float r2min = std::numeric_limits<float>::max();
1028 float r2max = -std::numeric_limits<float>::max();
1029 for(uint32_t i=0; i<8; i++){
1030 glm::vec3 q(i & 1 ? q_min.x : q_max.x,
1031 i & 2 ? q_min.y : q_max.y,
1032 i & 4 ? q_min.z : q_max.z);
1033 float r2 = glm::dot(q, q);
1034 r2min = glm::min(r2min, r2);
1035 r2max = glm::max(r2max, r2);
1037 int qi = FrustrumAABBIntersect(frustum, minDistanceSquared, maxDistanceSquared, q_min, q_max, r2min, r2max);
1038 if(qi == OUTSIDE)
continue;
1039 if(qi == INSIDE) tiles_inside.push_back(glm::ivec3(tx, ty, tz));
1040 else tiles_intersecting.push_back(glm::ivec3(tx, ty, tz));
1045void Cogs::Core::EchoSounder::UniformGridSampleData::evict_tiles()
1047 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::evict_tiles");
1048 if(data.tiles.size() > component->max_tiles){
1049 data.evict_number++;
1050 for(
auto it = data.tiles.begin(); it != data.tiles.end(); ){
1051 if(it->second.ping_number < data.evict_number){
1052 _aligned_free(it->second.data);
1053 Entity *ptr = it->second.visualizer.get();
1054 if(ptr) data.destroy.push_back(ptr);
1055 it = data.tiles.erase(it);
1066 tile.data = (
float*)_aligned_malloc(
sizeof(
float)*data.size.x*data.size.y*data.size.z,
sizeof(float)*8);
1069 tile.data = (
float*)_aligned_malloc(
sizeof(
float)*data.size.x*data.size.y*data.size.z,
sizeof(float)*8);
1072 LOG_ERROR(logger,
"UniformGrid: OutOfMemory! Clearing!\n");
1073 system->clear(component);
1074 tile.data = (
float*)_aligned_malloc(
sizeof(
float)*data.size.x*data.size.y*data.size.z,
sizeof(float)*8);
1077 LOG_ERROR(logger,
"UniformGrid: OutOfMemory! Exit!\n");
1080 memset(tile.data, 0,
sizeof(
float)*data.size.x*data.size.y*data.size.z);
1081 tile.minValue = -std::numeric_limits<float>::max();
1082 tile.maxValue = std::numeric_limits<float>::max();
1085void Cogs::Core::EchoSounder::UniformGridSampleData::gen_tiles()
1087 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::gen_tiles");
1088 for(
auto tileIndex: tiles_inside){
1089 glm::uvec3 tilePos = glm::vec3(tileIndex)+glm::vec3(1<<15);
1090 TileKey key = encodeTileKey(tilePos);
1091 if(data.tiles.count(key) == 0){
1092 data.tiles[key] = GenTile();
1095 for(
auto tileIndex: tiles_intersecting){
1096 glm::uvec3 tilePos = glm::vec3(tileIndex)+glm::vec3(1<<15);
1097 TileKey key = encodeTileKey(tilePos);
1098 if(data.tiles.count(key) == 0){
1099 data.tiles[key] = GenTile();
1103void Cogs::Core::EchoSounder::UniformGridSampleData::sample_ref(
float *d,
const float *v, uint32_t z, uint32_t y, uint32_t x,
float r2, glm::vec3 q)
1105 glm::vec3 a = inverseOrientation * q;
1106 float r = std::sqrt(r2);
1111 float dirX = std::asin(a.x / r);
1112 float dirY = std::asin(a.y / r);
1113 glm::vec3 polarPos = glm::vec3(dirY, dirX, r);
1118 if (config->majorCount > 1 && config->minorCount > 1) {
1120 glm::vec3 xi = polarScale * (polarPos - polarShift);
1121 if ((xi.x <= 0.0f || xi.y <= 0.0f || xi.z <= 0.0f ||
1122 xi.x > maxIndices.x || xi.y > maxIndices.y || xi.z > maxIndices.z))
1126 glm::vec3 tau = glm::floor(xi);
1128 i = glm::uvec3(tau);
1129 j = glm::uvec2(i) + glm::uvec2(1);
1133 glm::vec3 xi = glm::max(glm::vec3(0.f), polarScale*(polarPos - polarShift));
1136 glm::vec3 tau = glm::floor(xi);
1138 i = glm::min(maxIndices, glm::uvec3(tau));
1139 j = glm::min(glm::uvec2(maxIndices), glm::uvec2(i) + glm::uvec2(1));
1142 float val00 = v[(i.y*minorCount + i.x)*config->sampleCount + i.z];
1143 float val01 = v[(j.y*minorCount + i.x)*config->sampleCount + i.z];
1144 float val0 = (1.f - t.y)*val00 + t.y*val01;
1146 float val10 = v[(i.y*minorCount + j.x)*config->sampleCount + i.z];
1147 float val11 = v[(j.y*minorCount + j.x)*config->sampleCount + i.z];
1148 float val1 = (1.f - t.y)*val10 + t.y*val11;
1150 float val = (1.f - t.x)*val0 + t.x*val1;
1152 uint32_t index = z * data.size.y*data.size.x + y * data.size.x + x;
1155 float prev = d[index];
1160 float alpha = average_alpha;
1161 d[index] = val*alpha + prev*(1.0f-alpha);
1168void Cogs::Core::EchoSounder::UniformGridSampleData::sample_sn90_ref(
float *d,
const float *v, uint32_t z, uint32_t y, uint32_t x,
float r2, glm::vec3 q)
1170 glm::vec3 a = inverseOrientation * q;
1171 float r = std::sqrt(r2);
1180 float dirX = std::asin(a.x / r);
1181 float dirY = std::atan(a.y / a.z);
1182 glm::vec3 polarPos = glm::vec3(dirY, dirX, a.z);
1185 glm::vec3 xi = glm::max(glm::vec3(0.f), polarScale*(polarPos - polarShift));
1188 glm::vec3 tau = glm::floor(xi);
1189 glm::vec3 t = xi - tau;
1192 glm::uvec3 i = glm::min(maxIndices, glm::uvec3(tau));
1193 glm::uvec2 j = glm::min(glm::uvec2(maxIndices), glm::uvec2(i) + glm::uvec2(1));
1195 float val00 = v[(i.y*minorCount + i.x)*config->sampleCount + i.z];
1196 float val01 = v[(j.y*minorCount + i.x)*config->sampleCount + i.z];
1197 float val0 = (1.f - t.y)*val00 + t.y*val01;
1199 float val10 = v[(i.y*minorCount + j.x)*config->sampleCount + i.z];
1200 float val11 = v[(j.y*minorCount + j.x)*config->sampleCount + i.z];
1201 float val1 = (1.f - t.y)*val10 + t.y*val11;
1203 float val = (1.f - t.x)*val0 + t.x*val1;
1205 glm::uvec2 i = glm::min(glm::uvec2(maxIndices), glm::uvec2(tau));
1206 glm::uvec2 j = glm::min(glm::uvec2(maxIndices), glm::uvec2(i) + glm::uvec2(1));
1209 float scale = -2.0f*cos(dirY)*polarScale.y;
1211 uint32_t z00 = (uint32_t)std::clamp(tau.z + s*scale, 0.0f, (
float)maxIndices.z);
1212 uint32_t z01 = (uint32_t)std::clamp(tau.z + (s-1)*scale, 0.0f, (float)maxIndices.z);
1213 uint32_t z10 = (uint32_t)std::clamp(tau.z + s*scale, 0.0f, (
float)maxIndices.z);
1214 uint32_t z11 = (uint32_t)std::clamp(tau.z + (s-1)*scale, 0.0f, (float)maxIndices.z);
1216 float val00 = v[(i.y*minorCount + i.x)*config->sampleCount + z00];
1217 float val01 = v[(j.y*minorCount + i.x)*config->sampleCount + z01];
1218 float val0 = (1.f - t.y)*val00 + t.y*val01;
1220 float val10 = v[(i.y*minorCount + j.x)*config->sampleCount + z10];
1221 float val11 = v[(j.y*minorCount + j.x)*config->sampleCount + z11];
1222 float val1 = (1.f - t.y)*val10 + t.y*val11;
1224 float val = (1.f - t.x)*val0 + t.x*val1;
1226 glm::uvec2 i = glm::min(glm::uvec2(maxIndices), glm::uvec2(tau));
1227 glm::uvec2 j = glm::min(glm::uvec2(maxIndices), glm::uvec2(i) + glm::uvec2(1));
1230 float scale = -2.0f*cos(dirY)*polarScale.y;
1232 uint32_t z000 = std::min<uint32_t>(maxIndices.z, tau.z + s*scale);
1233 uint32_t z010 = std::min<uint32_t>(maxIndices.z, tau.z + (s-1)*scale);
1234 uint32_t z100 = std::min<uint32_t>(maxIndices.z, tau.z + s*scale);
1235 uint32_t z110 = std::min<uint32_t>(maxIndices.z, tau.z + (s-1)*scale);
1237 uint32_t z001 = std::min<uint32_t>(maxIndices.z, tau.z + s*scale + 1);
1238 uint32_t z011 = std::min<uint32_t>(maxIndices.z, tau.z + (s-1)*scale + 1);
1239 uint32_t z101 = std::min<uint32_t>(maxIndices.z, tau.z + s*scale + 1);
1240 uint32_t z111 = std::min<uint32_t>(maxIndices.z, tau.z + (s-1)*scale + 1);
1242 float val000 = v[(i.y*minorCount + i.x)*config->sampleCount + z000];
1243 float val010 = v[(j.y*minorCount + i.x)*config->sampleCount + z010];
1244 float val00 = (1.f - t.y)*val000 + t.y*val010;
1246 float val100 = v[(i.y*minorCount + j.x)*config->sampleCount + z100];
1247 float val110 = v[(j.y*minorCount + j.x)*config->sampleCount + z110];
1248 float val10 = (1.f - t.y)*val100 + t.y*val110;
1250 float val0 = (1.f - t.x)*val00 + t.x*val10;
1252 float val001 = v[(i.y*minorCount + i.x)*config->sampleCount + z001];
1253 float val011 = v[(j.y*minorCount + i.x)*config->sampleCount + z011];
1254 float val01 = (1.f - t.y)*val001 + t.y*val011;
1256 float val101 = v[(i.y*minorCount + j.x)*config->sampleCount + z101];
1257 float val111 = v[(j.y*minorCount + j.x)*config->sampleCount + z111];
1258 float val11 = (1.f - t.y)*val101 + t.y*val111;
1260 float val1 = (1.f - t.x)*val01 + t.x*val11;
1262 float val = (1.f - t.z)*val0 + t.z*val1;
1265 uint32_t index = z * data.size.y*data.size.x + y * data.size.x + x;
1269void Cogs::Core::EchoSounder::UniformGridSampleData::sample_intersecting(
size_t start,
size_t end)
1273 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::sampleIntersectingTask");
1274 float *v = linear.data();
1275 for (
size_t ti = start; ti < end; ti++) {
1276 Timer timer = Timer::startNew();
1277 glm::vec3 tileCoord = tiles_intersecting[ti];
1278 glm::vec3 tilePos = tileCoord*(glm::vec3(data.size-glm::uvec3(1))*data.scale);
1279 glm::uvec3 tileIndex = tileCoord+glm::vec3(1<<15);
1280 TileKey key = encodeTileKey(tileIndex);
1281 Tile &tile = data.tiles[key];
1282 if (config->coordSys == 0) {
1283 for (uint32_t z = 0; z < data.size.z; z++) {
1284 for (uint32_t y = 0; y < data.size.y; y++) {
1285 for (uint32_t x = 0; x < data.size.x; x++) {
1286 glm::vec3 p = data.scale * glm::vec3(x, y, z);
1287 glm::vec3 q = (tilePos - arrayPositionGlobal) + p;
1288 float r2 = glm::dot(q, q);
1290 bool in_0 = 0.f <= glm::dot(glm::vec3(frustum[0]), q);
1291 bool in_1 = 0.f <= glm::dot(glm::vec3(frustum[1]), q);
1292 bool in_2 = 0.f <= glm::dot(glm::vec3(frustum[2]), q);
1293 bool in_3 = 0.f <= glm::dot(glm::vec3(frustum[3]), q);
1294 bool in_4 = minDistanceSquared <= r2;
1295 bool in_5 = r2 <= maxDistanceSquared;
1296 if (!in_0 || !in_1 || !in_2 || !in_3 || !in_4 || !in_5)
continue;
1297 sample_ref(tile.data, v, z, y, x, r2, q);
1302 else if (config->coordSys == 1) {
1304 case ComputeType::SSE41:
1305 sampleTile_border_sse41(tile.data, v, tileCoord, tileIndex, data.size, maxIndices, tilePos, data.scale, arrayPositionGlobal, frustum,
1306 minDistanceSquared, maxDistanceSquared, inverseOrientation,
1307 config->coordSys, minorCount, config->sampleCount, polarScale, polarShift);
1309 case ComputeType::FMA:
1310 sampleTile_inner_fma_gather(tile.data, v, tileCoord, tileIndex, data.size, maxIndices, tilePos, data.scale, arrayPositionGlobal, frustum,
1311 minDistanceSquared, maxDistanceSquared, inverseOrientation,
1312 config->coordSys, minorCount, config->sampleCount, polarScale, polarShift);
1314 case ComputeType::AVX2:
1315 sampleTile3_border_avx2(tile.data, tile.minValue, tile.maxValue, v, tileCoord, tileIndex, data.size, maxIndices, tilePos, data.scale, arrayPositionGlobal, frustum,
1316 minDistanceSquared, maxDistanceSquared, inverseOrientation,
1317 config->coordSys, minorCount, config->sampleCount, polarScale, polarShift);
1320 for (uint32_t z = 0; z < data.size.z; z++) {
1321 for (uint32_t y = 0; y < data.size.y; y++) {
1322 for (uint32_t x = 0; x < data.size.x; x++) {
1323 glm::vec3 p = data.scale * glm::vec3(x, y, z);
1324 glm::vec3 q = (tilePos - arrayPositionGlobal) + p;
1325 float r2 = glm::dot(q, q);
1327 bool in_0 = 0.f <= glm::dot(glm::vec3(frustum[0]), q);
1328 bool in_1 = 0.f <= glm::dot(glm::vec3(frustum[1]), q);
1329 bool in_2 = 0.f <= glm::dot(glm::vec3(frustum[2]), q);
1330 bool in_3 = 0.f <= glm::dot(glm::vec3(frustum[3]), q);
1331 bool in_4 = minDistanceSquared <= r2;
1332 bool in_5 = r2 <= maxDistanceSquared;
1333 if (!in_0 || !in_1 || !in_2 || !in_3 || !in_4 || !in_5)
continue;
1334 sample_sn90_ref(tile.data, v, z, y, x, r2, q);
1341 else { assert(
false &&
"Unhandled coordinate system"); }
1342 data.sample_intersecting.us.fetch_add(uint32_t(1e6*timer.elapsedSeconds()));
1343 data.sample_intersecting.N.fetch_add(1);
1344 tile.mesh = data.createIsoSurfaces(tile, scratch, tilePos);
1345 tile.ping_number = ping_number;
1349void Cogs::Core::EchoSounder::UniformGridSampleData::sample_inside(
size_t start,
size_t end)
1353 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::sampleInsideTask");
1354 float *v = linear.data();
1355 for(
size_t ti=start; ti<end; ti++){
1356 Timer timer = Timer::startNew();
1357 glm::vec3 tileCoord = tiles_inside[ti];
1358 glm::vec3 tilePos = tileCoord*(glm::vec3(data.size-glm::uvec3(1))*data.scale);
1359 glm::uvec3 tileIndex = tileCoord+glm::vec3(1<<15);
1360 TileKey key = encodeTileKey(tileIndex);
1361 Tile &tile = data.tiles[key];
1362 if(config->coordSys == 0){
1363 for(uint32_t z=0; z<data.size.z; z++){
1364 for(uint32_t y=0; y<data.size.y; y++){
1365 for(uint32_t x=0; x<data.size.x; x++){
1366 glm::vec3 p = data.scale * glm::vec3(x, y, z);
1367 glm::vec3 q = (tilePos - arrayPositionGlobal) + p;
1368 float r2 = glm::dot(q, q);
1369 sample_ref(tile.data, v, z, y, x, r2, q);
1374 else if(config->coordSys == 1){
1376 case ComputeType::SSE41:
1377 sampleTile_border_sse41(tile.data, v, tileCoord, tileIndex, data.size, maxIndices, tilePos, data.scale, arrayPositionGlobal, frustum,
1378 minDistanceSquared, maxDistanceSquared, inverseOrientation,
1379 config->coordSys, minorCount, config->sampleCount, polarScale, polarShift);
1381 case ComputeType::FMA:
1382 sampleTile_inner_fma_gather(tile.data, v, tileCoord, tileIndex, data.size, maxIndices, tilePos, data.scale, arrayPositionGlobal, frustum,
1383 minDistanceSquared, maxDistanceSquared, inverseOrientation,
1384 config->coordSys, minorCount, config->sampleCount, polarScale, polarShift);
1386 case ComputeType::AVX2:
1387 sampleTile3_border_avx2(tile.data, tile.minValue, tile.maxValue, v, tileCoord, tileIndex, data.size, maxIndices, tilePos, data.scale, arrayPositionGlobal, frustum,
1388 minDistanceSquared, maxDistanceSquared, inverseOrientation,
1389 config->coordSys, minorCount, config->sampleCount, polarScale, polarShift);
1392 for (uint32_t z = 0; z < data.size.z; z++) {
1393 for (uint32_t y = 0; y < data.size.y; y++) {
1394 for (uint32_t x = 0; x < data.size.x; x++) {
1395 glm::vec3 p = data.scale * glm::vec3(x, y, z);
1396 glm::vec3 q = (tilePos - arrayPositionGlobal) + p;
1397 float r2 = glm::dot(q, q);
1398 sample_sn90_ref(tile.data, v, z, y, x, r2, q);
1405 else { assert(
false &&
"Unhandled coordinate system"); }
1406 data.sample_inside.us.fetch_add(uint32_t(1e6*timer.elapsedSeconds()));
1407 data.sample_inside.N.fetch_add(1);
1408 tile.mesh = data.createIsoSurfaces(tile, scratch, tilePos);
1409 tile.ping_number = ping_number;
1413namespace Cogs::Core::EchoSounder{
1414 typedef std::pair<TileKey, Tile*> Tmp;
1416 bool operator() (
const Tmp &lhs,
const Tmp &rhs)
const
1418 return lhs.second->ping_number<rhs.second->ping_number;
1422bool Cogs::Core::EchoSounder::UniformGridData::update_isosurface()
1424 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::update_isosurface");
1425 std::priority_queue<Tmp, std::vector<Tmp>, TileOrder> queue;
1426 for(
auto &tmp : tiles){
1427 if(tmp.second.update_iso){
1428 queue.push(std::pair<TileKey, Tile*>(tmp.first, &tmp.second));
1431 if(!queue.size())
return false;
1434 std::vector<Tmp> update_tiles;
1436 while(!queue.empty()){
1437 update_tiles.push_back(queue.top());
1445 auto group = system->context->taskManager->createGroup(system->Queue);
1446 size_t concurrency = Threads::hardwareConcurrency()-1;
1447 size_t tile_count = update_tiles.size();
1448 size_t task_count = std::min(tile_count, concurrency);
1449 size_t steps = tile_count/task_count+1;
1450 for(
size_t i=0; i<tile_count; i+=steps){
1451 size_t end = std::min(i+steps, tile_count);
1452 auto task = [
this, &update_tiles, i, end]()
1454 CpuInstrumentationScope(SCOPE_ECHOSOUNDER,
"UniformGrid::update_isosurface_task");
1456 for(
size_t j=i; j<end; j++){
1457 Tmp tmp = update_tiles[j];
1458 Tile &tile = *tmp.second;
1459 glm::uvec3 tileIndex(decodeTileKey(tmp.first));
1460 glm::vec3 tileCoord(glm::vec3(tileIndex)-glm::vec3(1<<15));
1461 glm::vec3 tilePos = tileCoord*(glm::vec3(size-glm::uvec3(1))*scale);
1462 tile.mesh = createIsoSurfaces(tile, scratch, tilePos);
1464 tile.update_iso =
false;
1467 system->context->taskManager->enqueueChild(group, task);
1469 system->context->taskManager->wait(group);
class Entity * getContainer() const
Get the container currently owning this component instance.
Container for components, providing composition of dynamic entities.
T * getComponent() const
Get a pointer to the first component implementing the given type in the entity.
virtual ComponentHandle createComponent()
Create a new component instance.
Context * context
Pointer to the Context instance the system lives in.
virtual void initialize(Context *context)
Initialize the system.
virtual void destroyComponent(ComponentHandle)
Destroy the component held by the given handle.
void preUpdate()
Run the pre-update method of the system.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
class EntityStore * store
Entity store.
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
EntityPtr createChildEntity(const StringView &type, ComponentModel::Entity *parent, const StringView &name=StringView())
Create a new Entity, parenting it to the given parent.
void removeChild(ComponentModel::Entity *parent, const ComponentModel::Entity *entity)
Remove the parent-child relationship between parent and entity.
Contains a handle to a Mesh resource to use when rendering using the MeshRenderComponent.
MeshHandle meshHandle
Handle to a Mesh resource to use when rendering.
Renders the contents of a MeshComponent using the given materials.
MaterialInstanceHandle material
Material used to render the mesh.
Renders a mesh with flexible submesh usage.
std::vector< MaterialInstanceHandle > materials
Materials used to render individual sub-meshes.
static constexpr TaskQueueId GlobalQueue
Global task queue.
Log implementation class.
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
@ CustomMaterial
Custom material set. Keeps legacy material component from changing the material instance.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Handle to a Component instance.
ComponentType * resolveComponent() const
void setFloatProperty(const VariableKey key, float value)
Set the float property with the given key to value.
void setTransparent()
Set the material instance to transparent, indicating to the renderer that blending should be enabled ...
void setTextureAddressMode(const StringView &key, const StringView &addressMode)
Set texture address mode with textual name.
void clone(MaterialInstance *instance)
Clone the the given material instance.
MaterialOptions options
Material rendering options used by this instance.
void setVec4Property(const VariableKey key, glm::vec4 value)
Set the vec4 property with the given key to value.
Material * material
Material resource this MaterialInstance is created from.
void setOpaque()
Set the material instance to opaque, indicating to the renderer that blending should be disabled for ...
bool depthWriteEnabled
If depth writes should be enabled rendering the geometry with the material instance.
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
@ PointList
List of points.