5#include "Components/Geometry/ExtrusionComponent.h"
6#include "Components/Data/TrajectoryComponent.h"
7#include "Components/Data/DataSetComponent.h"
8#include "Components/Core/CameraComponent.h"
9#include "Components/Core/MeshComponent.h"
10#include "Components/Core/SubMeshRenderComponent.h"
11#include "Components/Core/TransformComponent.h"
12#include "Components/Appearance/MaterialComponent.h"
14#include "Systems/Core/CameraSystem.h"
15#include "Systems/Core/TransformSystem.h"
16#include "Systems/Appearance/MaterialSystem.h"
18#include "Services/Variables.h"
20#include "Resources/Mesh.h"
21#include "Resources/MeshManager.h"
22#include "Resources/MaterialManager.h"
23#include "Resources/VertexFormats.h"
24#include "Resources/ResourceStore.h"
25#include "Resources/DefaultMaterial.h"
27#include "Utilities/Math.h"
29#include "Foundation/ComponentModel/Entity.h"
30#include "Foundation/Geometry/BoundingBox.hpp"
31#include "Foundation/Geometry/SampleListGenerator.hpp"
32#include "Foundation/Geometry/ValueQuery.hpp"
33#include "Foundation/Geometry/PathGenerator.hpp"
41 void updateData(ZipData & data,
const ZipComponent & component)
43 const ExtrusionComponent* extrusion = component.extrusion->getComponent<ExtrusionComponent>();
44 const TrajectoryComponent* trajectory = extrusion->trajectory->getComponent<TrajectoryComponent>();
45 const DataSetComponent* dataSet = component.dataSet->getComponent<DataSetComponent>();
46 if (trajectory ==
nullptr || dataSet ==
nullptr) {
50 const float endDepth = std::min(dataSet->indexes[dataSet->indexes.size() - 1], trajectory->indexes[trajectory->indexes.size() - 1]);
51 const float startDepth = std::max(dataSet->indexes[0], trajectory->indexes[0]);
53 std::vector<float> & depthList = data.depthList;
56 SampleListGenerator::generateIndexedSamples<float>(
59 trajectory->indexes.data(),
60 static_cast<int>(trajectory->indexes.size()),
63 std::vector<float> & samples = data.samples;
66 SampleListGenerator::createUniqueVector(
69 dataSet->indexes.data(),
70 dataSet->indexes.size(),
75 std::vector<glm::vec3> & basePositions = data.basePositions;
76 basePositions.resize(samples.size());
78 std::vector<glm::vec3> & baseDirections = data.baseDirections;
79 baseDirections.resize(samples.size());
81 std::vector<float> & values = data.values;
82 data.values.resize(samples.size());
84 ValueQuery::getValuesAtDepths(samples.data(),
static_cast<int>(samples.size()), dataSet->indexes.data(), dataSet->values.data(),
static_cast<int>(dataSet->values.size()), values.data());
86 auto minMax = std::minmax_element(dataSet->values.begin(), dataSet->values.end());
88 SampleListGenerator::normalizeValues<float, true>(values.data(), values.data(),
static_cast<int>(values.size()), *minMax.first, *minMax.second);
90 Geometry::PathGenerator::generateLinearPath(samples.data(),
static_cast<int>(samples.size()), trajectory->indexes.data(), trajectory->positions.data(),
static_cast<int>(trajectory->positions.size()), basePositions.data(), baseDirections.data());
93 void updatePositions(
const ZipData & data,
const ZipComponent & component, Mesh * mesh,
bool useGpu)
95 const glm::vec3 & axis = data.axis;
96 const float offset = data.radius;
98 const size_t numSamples = data.samples.size();
100 const bool useProjectedCrossSection =
true;
101 const bool useProjectedAxis =
false;
102 const bool useTrajectoryOrientedAxis = component.useTrajectoryOrientedAxis;
103 const bool useData = !component.highlightTarget;
105 float extrusionSize = 10.0f;
107 if (component.highlightTarget) {
108 const ZipComponent* zipTarget = component.highlightTarget->getComponent<ZipComponent>();
111 extrusionSize = zipTarget->scale;
115 const float dataScale = component.scale;
116 const glm::vec3 principalAxis(0, 0, -1);
119 auto positions = mesh->mapPositions(0, numSamples * 2);
121 for (
size_t i = 0; i < numSamples; i++) {
122 const glm::vec3 basePosition = data.basePositions[i];
123 const glm::vec3 trajectoryDirection = data.baseDirections[i];
125 glm::vec3 base = axis;
126 glm::vec3 extrusion = axis;
128 if (useProjectedCrossSection) {
129 glm::vec3 cross = glm::cross(axis, -trajectoryDirection);
130 base = glm::cross(-trajectoryDirection, cross);
131 base = glm::normalize(base);
134 if (useProjectedAxis) {
138 if (useTrajectoryOrientedAxis) {
139 glm::quat rotation = getRotation(principalAxis, trajectoryDirection);
140 base = rotation * axis;
145 positions[i] = basePosition + (base * offset);
150 value = data.values[i];
152 value = extrusionSize;
158 positions[numSamples + i] = positions[i] + extrusion * value;
161 std::vector<glm::vec3> positions(numSamples * 2);
162 std::vector<glm::vec3> parameters(numSamples * 2);
163 std::vector<glm::vec3> directions(numSamples * 2);
165 for (
size_t i = 0; i < numSamples; i++) {
166 positions[numSamples + i] = positions[i] = data.basePositions[i];
167 directions[numSamples + i] = directions[i] = data.baseDirections[i];
169 const float value = dataScale * (useData ? data.values[i] : extrusionSize);
170 const float textureValue = useData ? data.values[i] : 0;
172 parameters[i] = glm::vec3(data.radius, textureValue, data.radius);
173 parameters[numSamples + i] = glm::vec3(data.radius + value, textureValue, data.radius);
177 mesh->setTangents(directions);
180 mesh->setNormals(parameters);
182 mesh->setPositions(positions);
186 void updateIndexes(
const ZipData & data,
const ZipComponent & component, Mesh * mesh)
188 const uint32_t numSamples =
static_cast<uint32_t
>(data.samples.size());
192 mesh->clearIndexes();
194 if (component.enableFill) {
195 std::vector<uint32_t> indexes(6 * (data.samples.size() - 1));
197 for (uint32_t i = 0; i < numSamples - 1; i++) {
199 indexes[idx++] = numSamples + i;
200 indexes[idx++] = numSamples + i + 1;
203 indexes[idx++] = numSamples + i + 1;
204 indexes[idx++] = i + 1;
207 mesh->setIndexData(indexes);
212 if (component.enableOutline) {
213 std::vector<uint32_t> lineIndexes((numSamples - 1) * 2 + 4);
217 lineIndexes[idx++] = 0;
218 lineIndexes[idx++] = numSamples;
220 for (uint32_t i = 0; i < numSamples - 1; ++i) {
221 lineIndexes[idx++] = numSamples + i;
222 lineIndexes[idx++] = numSamples + i + 1;
225 lineIndexes[idx++] = numSamples * 2 - 1;
226 lineIndexes[idx++] = numSamples - 1;
234 void updateTexCoords(
const ZipData & data,
const ZipComponent & , Mesh * mesh)
236 const size_t numSamples = data.samples.size();
238 std::vector<glm::vec2> texCoords(numSamples * 2);
240 for (
size_t i = 0; i < numSamples; ++i) {
241 texCoords[i] = glm::vec2(data.values[i], 0);
242 texCoords[numSamples + i] = glm::vec2(data.values[i], 0);
245 mesh->setTexCoords(texCoords);
252 const bool gpuSetting =
context->
variables->get(
"systems.zipSystem.useGpu",
false);
253 bool resetComponentData =
false;
255 if (gpuSetting != useGpu) {
257 resetComponentData =
true;
265 if (!component.active)
continue;
267 if (resetComponentData) {
268 resetComponent(component);
271 bool didUpdate =
false;
273 if (!setupComponent(
context, component) && !component.highlightTarget)
continue;
275 if (needsUpdate(
context, component) && !component.highlightTarget) {
276 updateStaticLog(
context, component);
278 }
else if (component.highlightTarget) {
279 didUpdate = updateStaticHighLight(
context, component);
282 if (!useGpu && !didUpdate) {
283 updateDynamic(
context, component);
291 base::cleanup(context);
300 const ExtrusionComponent* extrusion = component.
extrusion->getComponent<ExtrusionComponent>();
301 if (extrusion ==
nullptr || extrusion->trajectory ==
nullptr) {
305 const TrajectoryComponent* trajectory = extrusion->trajectory->getComponent<TrajectoryComponent>();
306 const DataSetComponent* dataSet = component.
dataSet->getComponent<DataSetComponent>();
308 return extrusion->hasChanged() ||
309 (trajectory && trajectory->hasChanged()) ||
310 (dataSet && dataSet->hasChanged()) ||
314void Cogs::Core::ZipSystem::updateStaticLog(Context * context, ZipComponent & component)
316 const CameraComponent* cameraComponent = context->cameraSystem->getMainCamera();
317 const CameraData& cameraData = context->cameraSystem->getData(cameraComponent);
319 const ExtrusionComponent* extrusion = component.extrusion->getComponent<ExtrusionComponent>();
320 ZipData& data = this->getData(&component);
321 SubMeshRenderComponent* renderComponent = component.getComponent<SubMeshRenderComponent>();
322 Mesh* mesh = component.getComponent<MeshComponent>()->meshHandle.resolve();
324 updateData(data, component);
326 if (data.samples.size()) {
327 updateIndexes(data, component, mesh);
329 updateTexCoords(data, component, mesh);
334 data.radius = extrusion->radius;
335 if (component.rotateAxisToCamera) {
336 data.axis = glm::vec3(cameraData.inverseViewMatrix * glm::vec4(component.axis, 0));
339 data.axis = component.axis;
343 MaterialInstance* fillMaterial = context->materialInstanceManager->get(renderComponent->materials[0]);
344 fillMaterial->setVec4Property(axisKey, glm::vec4(component.axis, 0));
345 fillMaterial->options.depthBiasEnabled =
true;
346 fillMaterial->options.depthBias.constant = 8.0f;
347 fillMaterial->options.depthBias.slope = 8.0f;
349 MaterialInstance* lineMaterial = context->materialInstanceManager->get(renderComponent->materials[1]);
350 lineMaterial->setVec4Property(axisKey, glm::vec4(component.axis, 0));
351 lineMaterial->setVec4Property(diffuseColorKey, glm::vec4(0, 0, 0, 1));
353 MaterialComponent* material = component.getComponent<MaterialComponent>();
354 const MaterialData& materialData = context->materialSystem->getData(material);
356 renderComponent->materials[0] = materialData.instance;
359 renderComponent->materials[1] = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
360 renderComponent->materials[1]->setPermutation(
"Line");
363 material->depthBiasEnable =
true;
364 material->depthBiasConstant = 8.0f;
365 material->depthBiasSlope = 8.0f;
366 material->depthBiasClamp = 100.0f;
368 MaterialInstance* lineMaterial = context->materialInstanceManager->get(renderComponent->materials[1]);
369 lineMaterial->setVec4Property(DefaultMaterial::DiffuseColor, glm::vec4(0, 0, 0, 1));
370 lineMaterial->setBoolProperty(DefaultMaterial::EnableLighting,
false);
373 updatePositions(data, component, mesh, useGpu);
375 Geometry::BoundingBox box = Geometry::computeBoundingBox(data.basePositions.begin(), data.basePositions.end());
377 float adj = data.radius + component.scale;
378 Geometry::BoundingBox adjustedBox = { box.min - glm::vec3(adj, adj, 0), box.max + glm::vec3(adj, adj, 0) };
380 mesh->setBounds(adjustedBox);
383bool Cogs::Core::ZipSystem::setupComponent(Context * context, ZipComponent & component)
385 MeshComponent* meshComponent = component.getComponent<MeshComponent>();
386 SubMeshRenderComponent* renderComponent = component.getComponent<SubMeshRenderComponent>();
387 TransformComponent* transform = component.getComponent<TransformComponent>();
389 meshComponent->meshHandle = context->meshManager->create();
392 if (renderComponent->materials.size() != 2) {
393 renderComponent->materials.resize(2);
396 if (component.extrusion && component.dataSet) {
397 const ExtrusionComponent* extrusion = component.extrusion->getComponent<ExtrusionComponent>();
398 if (extrusion ==
nullptr) {
402 const TransformComponent* extrusionTransform = extrusion->getComponent<TransformComponent>();
404 context->transformSystem->copyTransform(extrusionTransform, transform);
406 MaterialComponent* material = component.getComponent<MaterialComponent>();
407 MaterialData& materialData = context->materialSystem->getData(material);
408 material->enableLighting =
false;
409 material->setChanged();
413 MaterialInstanceHandle instance = context->materialInstanceManager->createMaterialInstance(zipMaterial);
414 MaterialInstanceHandle instance2 = context->materialInstanceManager->createMaterialInstance(zipMaterial);
416 instance.resolve()->
setVec4Property(parameterKey, glm::vec4(1, 0, 0, 0));
417 instance2.resolve()->setVec4Property(parameterKey, glm::vec4(0, 0, 0, 0));
419 renderComponent->materials[0] = instance;
420 renderComponent->materials[1] = instance2;
422 materialData.instance = renderComponent->materials[0];
429 MaterialComponent* colorMapMaterial = colorMap->getComponent<MaterialComponent>();
431 if (useGpu && renderComponent->materials.size()) {
432 MaterialInstanceHandle zipMaterialInstance = renderComponent->materials[0];
434 if (zipMaterialInstance) {
438 }
else if (!useGpu && material->diffuseMap != colorMapMaterial->diffuseMap) {
439 material->diffuseMap = colorMapMaterial->diffuseMap;
441 material->diffuseColor = glm::vec4(1, 1, 1, 1);
442 material->setChanged();
452bool Cogs::Core::ZipSystem::updateStaticHighLight(Context * context, ZipComponent & component)
454 const ZipComponent* zipComponent = component.highlightTarget->getComponent<ZipComponent>();
455 TransformComponent* transform = component.getComponent<TransformComponent>();
456 ZipData& data = this->getData(&component);
458 MeshComponent* meshComponent = component.getComponent<MeshComponent>();
459 Mesh* mesh = context->meshManager->get(meshComponent->meshHandle);
461 if (zipComponent ==
nullptr || zipComponent->extrusion ==
nullptr || !zipComponent->active) {
465 const ExtrusionComponent* extrusion = zipComponent->extrusion->getComponent<ExtrusionComponent>();
466 if (extrusion ==
nullptr || extrusion->trajectory ==
nullptr) {
469 const TransformComponent* extrusionTransform = extrusion->getComponent<TransformComponent>();
470 TrajectoryComponent* trajectory = extrusion->trajectory->getComponent<TrajectoryComponent>();
471 ZipData& targetData = this->getData(zipComponent);
472 MaterialComponent* material = component.getComponent<MaterialComponent>();
474 context->transformSystem->copyTransform(extrusionTransform, transform);
476 component.useTrajectoryOrientedAxis = zipComponent->useTrajectoryOrientedAxis;
478 if (extrusion->hasChanged() ||
479 trajectory->hasChanged() ||
480 zipComponent->hasChanged() ||
481 component.hasChanged() ||
482 material->hasChanged()) {
483 data.axis = targetData.axis;
484 data.radius = targetData.radius;
486 const float startDepth = std::max(component.highlightStart, trajectory->indexes[0]);
487 const float endDepth = std::min(component.highlightEnd, trajectory->indexes[trajectory->indexes.size() - 1]);
489 data.samples.clear();
491 std::vector<float> indexSamples;
493 SampleListGenerator::generateIndexedSamples<float>(
496 targetData.samples.data(),
497 static_cast<int>(targetData.samples.size()),
500 data.basePositions.resize(data.samples.size());
501 data.baseDirections.resize(data.samples.size());
503 if (data.samples.size() < 2) {
508 Geometry::PathGenerator::generateLinearPath(data.samples.data(),
static_cast<int>(data.samples.size()), trajectory->indexes.data(), trajectory->positions.data(),
static_cast<int>(trajectory->positions.size()), data.basePositions.data(), data.baseDirections.data());
510 if (data.samples.size()) {
511 updatePositions(data, component, mesh, useGpu);
512 updateIndexes(data, component, mesh);
514 SubMeshRenderComponent* renderComponent = component.getComponent<SubMeshRenderComponent>();
515 MaterialData& materialData = context->materialSystem->getData(material);
519 material->enableLighting =
false;
521 if (!materialData.instance)
return true;
523 renderComponent->materials[0] = materialData.instance;
525 renderComponent->materials[1] = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
528 material->depthBiasEnable =
true;
529 material->depthBiasConstant = -1.0f;
530 material->depthBiasSlope = 0.0f;
534 material->setChanged();
536 MaterialInstance* fillMaterial = context->materialInstanceManager->get(renderComponent->materials[0]);
537 fillMaterial->setBoolProperty(DefaultMaterial::EnableLighting,
false);
538 fillMaterial->setTransparent();
539 fillMaterial->setName(
"HighlightFillMaterial");
541 MaterialInstance* lineMaterial = context->materialInstanceManager->get(renderComponent->materials[1]);
542 lineMaterial->setVec4Property(DefaultMaterial::DiffuseColor, glm::vec4(0, 0, 0, 1));
543 lineMaterial->setBoolProperty(DefaultMaterial::EnableLighting,
false);
546 renderComponent->materials[0] = context->materialInstanceManager->createMaterialInstance(zipMaterial);
547 renderComponent->materials[1] = context->materialInstanceManager->createMaterialInstance(zipMaterial);
550 MaterialInstance* fillMaterial = renderComponent->materials[0].resolve();
551 fillMaterial->setVec4Property(parameterKey, glm::vec4(0, 0, 0, 0));
552 fillMaterial->setVec4Property(diffuseColorKey, material->diffuseColor);
553 fillMaterial->setVec4Property(axisKey, glm::vec4(zipComponent->axis, 0));
555 if (material->diffuseColor.a < 1.0f) {
556 fillMaterial->setTransparent();
558 fillMaterial->setOpaque();
561 fillMaterial->options.depthBiasEnabled =
true;
562 fillMaterial->options.depthBias.constant = -1.0f;
563 fillMaterial->options.depthBias.slope = 0.0f;
567 MaterialInstance* lineMaterial = renderComponent->materials[1].resolve();
568 lineMaterial->setVec4Property(parameterKey, glm::vec4(0, 0, 0, 0));
569 lineMaterial->setVec4Property(diffuseColorKey, glm::vec4(0, 0, 0, 1));
570 lineMaterial->setVec4Property(axisKey, glm::vec4(zipComponent->axis, 0));
572 materialData.instance = renderComponent->materials[0];
578 Geometry::BoundingBox box = Geometry::computeBoundingBox(data.basePositions.begin(), data.basePositions.end());
580 float adj = data.radius + zipComponent->scale;
581 Geometry::BoundingBox adjustedBox = { box.min - glm::vec3(adj, adj, 0), box.max + glm::vec3(adj, adj, 0) };
583 mesh->setBounds(adjustedBox);
591void Cogs::Core::ZipSystem::setupMaterial(Context * context)
593 this->zipMaterial = context->materialManager->loadMaterial(
"ZipMaterial.material");
595 context->materialManager->processLoading();
597 const Material* zipMaterial = this->zipMaterial.resolve();
599 parameterKey = zipMaterial->getVec4Key(
"parameters");
600 axisKey = zipMaterial->getVec4Key(
"axis");
601 diffuseColorKey = zipMaterial->getVec4Key(
"diffuseColor");
603 colorMapKey = zipMaterial->getTextureKey(
"colorMap");
606void Cogs::Core::ZipSystem::resetComponent(ZipComponent & component)
608 SubMeshRenderComponent* renderComponent = component.getComponent<SubMeshRenderComponent>();
610 renderComponent->materials.resize(2);
614 MeshComponent* meshComponent = component.getComponent<MeshComponent>();
617 MaterialComponent* materialComponent = component.getComponent<MaterialComponent>();
618 MaterialData& materialData = context->materialSystem->getData(materialComponent);
620 materialComponent->setChanged();
622 component.setChanged();
625void Cogs::Core::ZipSystem::updateDynamic(Context * context, ZipComponent & component)
627 const CameraComponent* cameraComponent = context->cameraSystem->getMainCamera();
628 const CameraData& cameraData = context->cameraSystem->getData(cameraComponent);
630 if (cameraComponent->hasChanged() || cameraComponent->getComponent<TransformComponent>()->hasChanged()) {
631 ZipData& data = this->getData(&component);
632 Mesh* mesh = component.getComponent<MeshComponent>()->meshHandle.resolve();
634 if (component.highlightTarget && component.active) {
635 const ZipComponent* zipComponent = component.highlightTarget->getComponent<ZipComponent>();
637 if (zipComponent && zipComponent->active) {
638 data.axis = this->getData(zipComponent).axis;
640 updatePositions(data, component, mesh, useGpu);
643 if (component.rotateAxisToCamera) {
644 data.axis = glm::vec3(cameraData.inverseViewMatrix * glm::vec4(component.axis, 0));
647 data.axis = component.axis;
650 updatePositions(data, component, mesh, useGpu);
Context * context
Pointer to the Context instance the system lives in.
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.
std::unique_ptr< class Variables > variables
Variables service instance.
void cleanup(Context *context) override
Provided for custom cleanup logic in derived systems.
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.
@ Add
Render with additive blending.
Contains all Cogs related functionality.
void setTextureProperty(const StringView &key, TextureHandle value)
Set the texture property with the given key to the texture resource held by value.
void setVec4Property(const VariableKey key, glm::vec4 value)
Set the vec4 property with the given key to value.
@ BoundingBoxSet
Custom bounding box set, no automatic calculation of bounds should be performed.
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.
Component displaying a 3D log on a trajectory.
std::shared_ptr< ComponentModel::Entity > dataSet
Dataset entity with log depths and values.
std::shared_ptr< ComponentModel::Entity > extrusion
Wellbore entity owning.
@ TriangleList
List of triangles.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.