1#include "TensionRingComponent.h"
5#include "EntityStore.h"
7#include "Components/Geometry/VariableExtrusionComponent.h"
8#include "Components/Data/TrajectoryComponent.h"
9#include "Components/Core/MeshRenderComponent.h"
10#include "Components/Appearance/MaterialComponent.h"
12#include "ProfileGenerator.h"
13#include "Utilities/Math.h"
15#include "Foundation/Geometry/Glm.hpp"
16#include "Foundation/Geometry/SampleListGenerator.hpp"
17#include "Foundation/Geometry/PathGenerator.hpp"
22void Cogs::Core::TensionRingComponent::registerType()
35 Field(
Name(
"startAngle"), &TensionRingComponent::startAngle),
39 Method(
Name(
"initialize"), &TensionRingComponent::initialize),
40 Method(
Name(
"update"), &TensionRingComponent::update),
43 DynamicComponent::registerDerivedType<TensionRingComponent>().setFields(fields).setMethods(methods);
46void Cogs::Core::TensionRingComponent::initialize(Context * context)
48 shape1 = context->store->createChildEntity(
"VariableExtrusionShape", getContainer());
49 shape2 = context->store->createChildEntity(
"VariableExtrusionShape", getContainer());
51 trajectory1 = context->store->createChildEntity(
"Trajectory", getContainer());
52 trajectory2 = context->store->createChildEntity(
"Trajectory", getContainer());
55void Cogs::Core::TensionRingComponent::update()
57 auto variableExtrusion = getComponent<VariableExtrusionComponent>();
59 assert(variableExtrusion &&
"No variable extrusion available for riser.");
61 if (!variableExtrusion->trajectory)
return;
63 auto mainTrajectory = variableExtrusion->trajectory->getComponent<TrajectoryComponent>();
65 if (!mainTrajectory)
return;
67 if (!this->hasChanged() && !mainTrajectory->hasChanged() && !variableExtrusion->hasChanged()) {
68 if (this->getComponent<MaterialComponent>()->hasChanged()) {
77 std::vector<float> trajectoryDepths;
79 SampleListGenerator::generateIndexedSamples(startDepth, endDepth, mainTrajectory->indexes.data(),
static_cast<int>(mainTrajectory->indexes.size()), trajectoryDepths);
81 if (trajectoryDepths.size() < 2)
return;
83 if (trajectoryDepths[0] > startDepth || trajectoryDepths[trajectoryDepths.size() - 1] < endDepth)
return;
85 const float radiusScale = variableExtrusion->radiusScale;
86 const glm::vec3 scaleVector(radiusScale, radiusScale, 1);
88 auto leftTrajectory = trajectory1->getComponent<TrajectoryComponent>();
89 auto rightTrajectory = trajectory2->getComponent<TrajectoryComponent>();
91 leftTrajectory->positions.resize(trajectoryDepths.size());
92 leftTrajectory->indexes.resize(trajectoryDepths.size());
94 rightTrajectory->positions.resize(trajectoryDepths.size());
95 rightTrajectory->indexes.resize(trajectoryDepths.size());
97 auto shape1 = this->shape1->getComponent<VariableExtrusionComponent>();
98 auto shape2 = this->shape2->getComponent<VariableExtrusionComponent>();
100 std::vector<glm::vec3> positions(trajectoryDepths.size());
101 std::vector<glm::vec3> directions(trajectoryDepths.size());
103 PathGenerator::generateLinearPath(trajectoryDepths.data(),
104 static_cast<int>(trajectoryDepths.size()),
105 mainTrajectory->indexes.data(),
106 mainTrajectory->positions.data(),
107 static_cast<int>(mainTrajectory->indexes.size()),
111 for (
size_t i = 0; i < trajectoryDepths.size(); ++i) {
112 const glm::vec3 & trajPos = positions[i];
113 const glm::vec3 & direction = directions[i];
115 glm::vec3 offsetLeft(0, this->splitDistance, 0);
116 glm::vec3 offsetRight(0, -this->splitDistance, 0);
117 glm::vec3 offsetRotationAxis = directions[0];
119 if (directions[0].z == 0.0f) {
120 offsetLeft = glm::vec3(0, 0, this->splitDistance);
121 offsetRight = glm::vec3(0, 0, -this->splitDistance);
124 auto offsetRotation = glm::angleAxis(splitAngle, offsetRotationAxis);
125 offsetLeft = offsetRotation * offsetRotationAxis;
126 offsetRight = offsetRotation * offsetRotationAxis;
128 auto rotation = getRotation(directions[0], direction);
129 offsetLeft = rotation * offsetRotationAxis;
130 offsetRight = rotation * offsetRotationAxis;
132 leftTrajectory->positions[i] = trajPos + (offsetLeft * scaleVector);
133 leftTrajectory->indexes[i] = trajectoryDepths[i];
135 rightTrajectory->positions[i] = trajPos + (offsetRight * scaleVector);
136 rightTrajectory->indexes[i] = trajectoryDepths[i];
139 const float depth = this->startDepth;
141 const float length = this->endDepth - depth;
142 const float partLength = length / 3;
144 const float innerRadius = this->innerRadius * radiusScale;
145 const float outerRadius = this->outerRadius * radiusScale;
146 const float extensionRadius = this->extensionRadius * radiusScale;
148 std::vector<float> depths;
149 std::vector<glm::vec2> profile;
151 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(depth);
152 profile.push_back(glm::vec2(outerRadius, 0)); depths.push_back(depth);
153 profile.push_back(glm::vec2(outerRadius, 0)); depths.push_back(depth + partLength);
154 profile.push_back(glm::vec2(extensionRadius, 0)); depths.push_back(depth + partLength);
155 profile.push_back(glm::vec2(extensionRadius, 0)); depths.push_back(depth + partLength * 2);
156 profile.push_back(glm::vec2(outerRadius, 0)); depths.push_back(depth + partLength * 2);
157 profile.push_back(glm::vec2(outerRadius, 0)); depths.push_back(depth + length);
158 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(depth + length);
159 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(depth);
161 shape1->depths = depths;
162 shape1->profile = profile;
163 shape1->setChanged();
165 shape2->depths = std::move(depths);
166 shape2->profile = std::move(profile);
167 shape2->setChanged();
169 auto meshRenderComponent2 = shape2->getComponent<MeshRenderComponent>();
170 meshRenderComponent2->setVisible(this->splitDistance != 0);
172 if (this->splitDistance == 0.0f) {
173 shape1->closed = variableExtrusion->closed;
174 shape1->angle = startAngle;
175 shape1->enableRotation = shape1->angle != 0;
179 shape1->closed =
false;
180 shape1->angle = this->splitAngle;
181 shape1->enableRotation =
true;
182 shape2->angle = shape1->angle + glm::pi<float>();
183 shape2->closed =
false;
187void Cogs::Core::TensionRingComponent::updateChildren()
189 const auto ves = getComponent<VariableExtrusionComponent>();
191 const auto children = {
192 shape1->getComponent<VariableExtrusionComponent>(),
193 shape2->getComponent<VariableExtrusionComponent>(),
196 for (
auto & c : children) {
197 c->trajectory = ves->trajectory;
198 c->closed = ves->closed;
201 const auto material = getComponent<MaterialComponent>();
203 const auto materials = {
204 shape1->getComponent<MaterialComponent>(),
205 shape2->getComponent<MaterialComponent>(),
208 for (
auto & m : materials) {
209 m->diffuseColor = material->diffuseColor;
float endDepth
End depth along trajectory.
float startDepth
Start depth along trajectory.
float outerRadius
Outer radius of the tension ring.
float extensionRadius
Outermost extended radius of the ring.
float innerRadius
Inner radius of the tension ring.
float splitAngle
Specify at which angle in radians the ring should be split in two.
float splitDistance
The distance between the two halves of the ring if it is split in two.
Field definition describing a single data member of a data structure.
Simple method definition.
Contains geometry calculations and generation.
Contains reflection support.
Represents an unique name.