Cogs.Core
PingIsoSystem.cpp
1#include "Context.h"
2#include "EntityStore.h"
3#include "Components/Core/MeshComponent.h"
4#include "Components/Core/SubMeshRenderComponent.h"
5#include "Systems/Core/TransformSystem.h"
6#include "Resources/MeshManager.h"
7#include "Resources/MaterialManager.h"
8#include "Services/TaskManager.h"
9
10#include "../Components/DataSetComponent.h"
11#include "../Components/DataRefComponent.h"
12#include "../Components/LocationComponent.h"
13#include "../Components/BeamGroupComponent.h"
14
15#include "../Systems/DataSetSystem.h"
16#include "../Tasks/SinglePingIsoSurfacesTasks.h"
17#include "PingIsoSystem.h"
18#include "../Utils.h"
19
20#include "Foundation/Logging/Logger.h"
21
22namespace {
23 Cogs::Logging::Log logger = Cogs::Logging::getLogger("EchoPingIsoSystem");
24}
25
26
28using namespace Cogs::Core::EchoSounder;
29
31{
33 surfaceMaterial = context->materialManager->loadMaterial("ParametricGrid.material");
34 context->materialManager->processLoading();
35 rangeKey = surfaceMaterial->getVec4Key("range");
36 opacityKey = surfaceMaterial->getFloatKey("opacity");
37}
38
40{
41 bool activateMeshes = false;
42 for (auto & isoComp : pool) {
43 auto & isoData = getData(&isoComp);
44
47 if (!getDataSet(&dataComp, &dataData, isoComp, dataSetSystem)) {
48 isoComp.setChanged();
49 isoData.dataComp = nullptr;
50 continue;
51 }
52 const auto * groupComp = isoComp.getComponent<BeamGroupComponent>();
53 if (!groupComp || !groupComp->sane) {
54 isoComp.setChanged();
55 continue;
56 }
57
58 // Check for things that trigger reissue of geometry creation.
59 if (isoData.dataComp != dataComp) {
60 isoData.dataComp = dataComp;
61 isoData.reIssue = true;
62 }
63
64 const auto * locComp = isoComp.getComponent<LocationComponent>();
65 if (isoData.index != locComp->index) {
66 isoData.index = locComp->index;
67 isoData.reIssue = true;
68 }
69
70 if (dataComp->hasChanged()) {
71 isoData.reIssue = true;
72 }
73
74 bool updateMaterials = isoComp.hasChanged();
75
76 // Check if we should re-create geometry
77 if (!isoData.reIssue) {
78 if (isoComp.hasChanged()) {
79 const Reflection::FieldId firstNonTriggeringField = isoComp.getType().getFieldId(&PingIsoComponent::material);
80 for (Reflection::FieldId fieldId = 0; fieldId < firstNonTriggeringField; fieldId++) {
81 if (isoComp.hasFieldChanged(fieldId)) {
82 isoData.reIssue = true;
83 break;
84 }
85 }
86 }
87 if (groupComp->hasChanged()) {
88 isoData.reIssue = true;
89 }
90 }
91
92 bool tasksAreRunning = isoData.persistent->runningTasks > 0;
93 bool triggerUpdate = false;
94 // No worker tasks running? No need to lock persistent, as no other tasks are running
95 if (!tasksAreRunning) {
96
97 // Mesh ready to be presented?
98 if (isoData.persistent->issuedMesh) {
99 if (isoData.persistent->issuedMesh->isActive()) {
100 auto * meshComp = isoComp.getComponent<MeshComponent>();
101 meshComp->meshHandle = isoData.persistent->issuedMesh;
102 meshComp->setChanged();
103
104 auto * trComp = isoComp.getComponent<TransformComponent>();
105 trComp->position = isoData.persistent->issuedPosition;
106 trComp->rotation = isoData.persistent->issuedOrientation;
107 trComp->setChanged();
108 context->transformSystem->updateTransformData(*trComp);
109
110 // Create new material instances if needed.
111 while (isoData.layerMaterialInstances.size() < isoData.thresholds.size()) {
112 isoData.layerMaterialInstances.push_back(context->materialInstanceManager->createMaterialInstance(surfaceMaterial));
113 }
114 isoData.layerMaterialInstances.resize(isoData.thresholds.size());
115
116 auto mshRndCmp = isoComp.getComponent<SubMeshRenderComponent>();
117 mshRndCmp->materials.resize(isoData.layerMaterialInstances.size());
118 for (size_t i = 0; i < isoData.layerMaterialInstances.size(); i++) {
119 mshRndCmp->materials[i] = isoData.layerMaterialInstances[i];
120 }
121 mshRndCmp->setChanged();
122
123 updateMaterials = true;
124 activateMeshes = true;
125 isoData.persistent->issuedMesh = MeshHandle::NoHandle;
126 }
127 else {
128 triggerUpdate = true;
129 }
130 }
131
132 //Should we issue construction of a new mesh?
133 if (isoData.reIssue) {
134
135 // Limited by MeshRenderComponent, that only has 16 material slots.
136 if (16 < isoComp.thresholds.size()) {
137 isoComp.thresholds.resize(16);
138 }
139 isoData.thresholds = isoComp.thresholds;
140 isoData.seabedClipOffset = isoComp.seabedClipOffset;
141
142 isoData.persistent->runningTasks++;
143
144 auto task = context->taskManager->create(context->taskManager->GlobalQueue,
146 &isoComp, &isoData,
147 groupComp,
148 dataComp, dataData));
149 context->taskManager->enqueue(task);
150
151 isoData.reIssue = false;
152 triggerUpdate = true;
153 }
154
155 }
156
157 // Update material properties
158 if (updateMaterials && isoComp.material) {
159 for (size_t i = 0; i < isoData.layerMaterialInstances.size(); i++) {
160 isoData.layerMaterialInstances[i]->clone(isoComp.material.resolve());
161
162 if (isoComp.innerLayerOpaque && i + 1 == isoData.layerMaterialInstances.size()) {
163 isoData.layerMaterialInstances[i]->setOpaque();
164 }
165 else {
166 isoData.layerMaterialInstances[i]->setTransparent();
167 }
168 isoData.layerMaterialInstances[i]->setVec4Property(rangeKey, glm::vec4(0, 1, 0, 1));
169 isoData.layerMaterialInstances[i]->setFloatProperty(opacityKey, isoComp.opacity);
170 isoData.layerMaterialInstances[i]->options.depthBiasEnabled = true;
171 isoData.layerMaterialInstances[i]->options.depthBias.slope = 0.f;
172 isoData.layerMaterialInstances[i]->options.depthBias.constant = i*isoComp.layerDepthBiasStep;
173 isoData.layerMaterialInstances[i]->options.depthBias.clamp = 100000.f;
174 }
175 }
176
177 if (tasksAreRunning || triggerUpdate) {
178 context->engine->triggerUpdate();
179 }
180 }
181
182 if (activateMeshes) {
183 context->engine->swapResources();
184 }
185}
186
188{
190}
void setChanged()
Sets the component to the ComponentFlags::Changed state with carry.
Definition: Component.h:202
ComponentType * getComponent() const
Definition: Component.h:159
virtual void cleanup(Context *)
Provided for custom cleanup logic in derived systems.
Context * context
Pointer to the Context instance the system lives in.
virtual void initialize(Context *context)
Initialize the system.
void update()
Updates the system state to that of the current frame.
ComponentPool< ComponentType > pool
Pool of components managed by the system.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
Definition: Context.h:186
std::unique_ptr< class Engine > engine
Engine instance.
Definition: Context.h:222
Contains a handle to a Mesh resource to use when rendering using the MeshRenderComponent.
Definition: MeshComponent.h:15
MeshHandle meshHandle
Handle to a Mesh resource to use when rendering.
Definition: MeshComponent.h:29
Renders a mesh with flexible submesh usage.
std::vector< MaterialInstanceHandle > materials
Materials used to render individual sub-meshes.
Defines a 4x4 transformation matrix for the entity and a global offset for root entities.
glm::vec3 position
Local position relative to the global coordinates, or the parent coordinate system if the parent fiel...
void updateTransformData(const TransformComponent &component)
Force an update of the transform data associated with the given component.
Log implementation class.
Definition: LogManager.h:139
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
uint16_t FieldId
Type used to index fields.
Definition: Name.h:54
void cleanup(Context *context) override
Provided for custom cleanup logic in derived systems.
void initialize(Context *context) override
Initialize the system.
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.