Cogs.Core
TensionRingComponent.cpp
1#include "TensionRingComponent.h"
2
3#include "Context.h"
4#include "Types.h"
5#include "EntityStore.h"
6
7#include "Components/Geometry/VariableExtrusionComponent.h"
8#include "Components/Data/TrajectoryComponent.h"
9#include "Components/Core/MeshRenderComponent.h"
10#include "Components/Appearance/MaterialComponent.h"
11
12#include "ProfileGenerator.h"
13#include "Utilities/Math.h"
14
15#include "Foundation/Geometry/Glm.hpp"
16#include "Foundation/Geometry/SampleListGenerator.hpp"
17#include "Foundation/Geometry/PathGenerator.hpp"
18
19using namespace Cogs::Reflection;
20using namespace Cogs::Geometry;
21
22void Cogs::Core::TensionRingComponent::registerType()
23{
24 Field fields [] = {
27
30
34
35 Field(Name("startAngle"), &TensionRingComponent::startAngle),
36 };
37
38 Method methods [] = {
39 Method(Name("initialize"), &TensionRingComponent::initialize),
40 Method(Name("update"), &TensionRingComponent::update),
41 };
42
43 DynamicComponent::registerDerivedType<TensionRingComponent>().setFields(fields).setMethods(methods);
44}
45
46void Cogs::Core::TensionRingComponent::initialize(Context * context)
47{
48 shape1 = context->store->createChildEntity("VariableExtrusionShape", getContainer());
49 shape2 = context->store->createChildEntity("VariableExtrusionShape", getContainer());
50
51 trajectory1 = context->store->createChildEntity("Trajectory", getContainer());
52 trajectory2 = context->store->createChildEntity("Trajectory", getContainer());
53}
54
55void Cogs::Core::TensionRingComponent::update()
56{
57 auto variableExtrusion = getComponent<VariableExtrusionComponent>();
58
59 assert(variableExtrusion && "No variable extrusion available for riser.");
60
61 if (!variableExtrusion->trajectory) return;
62
63 auto mainTrajectory = variableExtrusion->trajectory->getComponent<TrajectoryComponent>();
64
65 if (!mainTrajectory) return;
66
67 if (!this->hasChanged() && !mainTrajectory->hasChanged() && !variableExtrusion->hasChanged()) {
68 if (this->getComponent<MaterialComponent>()->hasChanged()) {
69 updateChildren();
70 }
71
72 return;
73 }
74
75 updateChildren();
76
77 std::vector<float> trajectoryDepths;
78
79 SampleListGenerator::generateIndexedSamples(startDepth, endDepth, mainTrajectory->indexes.data(), static_cast<int>(mainTrajectory->indexes.size()), trajectoryDepths);
80
81 if (trajectoryDepths.size() < 2) return;
82
83 if (trajectoryDepths[0] > startDepth || trajectoryDepths[trajectoryDepths.size() - 1] < endDepth) return;
84
85 const float radiusScale = variableExtrusion->radiusScale;
86 const glm::vec3 scaleVector(radiusScale, radiusScale, 1);
87
88 auto leftTrajectory = trajectory1->getComponent<TrajectoryComponent>();
89 auto rightTrajectory = trajectory2->getComponent<TrajectoryComponent>();
90
91 leftTrajectory->positions.resize(trajectoryDepths.size());
92 leftTrajectory->indexes.resize(trajectoryDepths.size());
93
94 rightTrajectory->positions.resize(trajectoryDepths.size());
95 rightTrajectory->indexes.resize(trajectoryDepths.size());
96
97 auto shape1 = this->shape1->getComponent<VariableExtrusionComponent>();
98 auto shape2 = this->shape2->getComponent<VariableExtrusionComponent>();
99
100 std::vector<glm::vec3> positions(trajectoryDepths.size());
101 std::vector<glm::vec3> directions(trajectoryDepths.size());
102
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()),
108 positions.data(),
109 directions.data());
110
111 for (size_t i = 0; i < trajectoryDepths.size(); ++i) {
112 const glm::vec3 & trajPos = positions[i];
113 const glm::vec3 & direction = directions[i];
114
115 glm::vec3 offsetLeft(0, this->splitDistance, 0);
116 glm::vec3 offsetRight(0, -this->splitDistance, 0);
117 glm::vec3 offsetRotationAxis = directions[0];
118
119 if (directions[0].z == 0.0f) {
120 offsetLeft = glm::vec3(0, 0, this->splitDistance);
121 offsetRight = glm::vec3(0, 0, -this->splitDistance);
122 }
123
124 auto offsetRotation = glm::angleAxis(splitAngle, offsetRotationAxis);
125 offsetLeft = offsetRotation * offsetRotationAxis;
126 offsetRight = offsetRotation * offsetRotationAxis;
127
128 auto rotation = getRotation(directions[0], direction);
129 offsetLeft = rotation * offsetRotationAxis;
130 offsetRight = rotation * offsetRotationAxis;
131
132 leftTrajectory->positions[i] = trajPos + (offsetLeft * scaleVector);
133 leftTrajectory->indexes[i] = trajectoryDepths[i];
134
135 rightTrajectory->positions[i] = trajPos + (offsetRight * scaleVector);
136 rightTrajectory->indexes[i] = trajectoryDepths[i];
137 }
138
139 const float depth = this->startDepth;
140
141 const float length = this->endDepth - depth;
142 const float partLength = length / 3;
143
144 const float innerRadius = this->innerRadius * radiusScale;
145 const float outerRadius = this->outerRadius * radiusScale;
146 const float extensionRadius = this->extensionRadius * radiusScale;
147
148 std::vector<float> depths;
149 std::vector<glm::vec2> profile;
150
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);
160
161 shape1->depths = depths;
162 shape1->profile = profile;
163 shape1->setChanged();
164
165 shape2->depths = std::move(depths);
166 shape2->profile = std::move(profile);
167 shape2->setChanged();
168
169 auto meshRenderComponent2 = shape2->getComponent<MeshRenderComponent>();
170 meshRenderComponent2->setVisible(this->splitDistance != 0);
171
172 if (this->splitDistance == 0.0f) {
173 shape1->closed = variableExtrusion->closed;
174 shape1->angle = startAngle;
175 shape1->enableRotation = shape1->angle != 0;
176 } else {
177 //NOTE: Setting closed on TensionRing has no effect when split distance != 0
178 // need to be able to set start and end angle in extrusion shape for this to be possible.
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;
184 }
185}
186
187void Cogs::Core::TensionRingComponent::updateChildren()
188{
189 const auto ves = getComponent<VariableExtrusionComponent>();
190
191 const auto children = {
192 shape1->getComponent<VariableExtrusionComponent>(),
193 shape2->getComponent<VariableExtrusionComponent>(),
194 };
195
196 for (auto & c : children) {
197 c->trajectory = ves->trajectory;
198 c->closed = ves->closed;
199 }
200
201 const auto material = getComponent<MaterialComponent>();
202
203 const auto materials = {
204 shape1->getComponent<MaterialComponent>(),
205 shape2->getComponent<MaterialComponent>(),
206 };
207
208 for (auto & m : materials) {
209 m->diffuseColor = material->diffuseColor;
210 m->setChanged();
211 }
212}
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.
Definition: Field.h:68
Simple method definition.
Definition: Method.h:72
Contains geometry calculations and generation.
Contains reflection support.
Definition: Component.h:11
Represents an unique name.
Definition: Name.h:70