Cogs.Core
RiserTelescopicJointComponent.cpp
1#include "RiserTelescopicJointComponent.h"
2
3#include "Context.h"
4#include "Types.h"
5#include "EntityStore.h"
6
7#include "Components/Data/TrajectoryComponent.h"
8#include "Components/Geometry/VariableExtrusionComponent.h"
9#include "Components/Appearance/MaterialComponent.h"
10
11#include "ProfileGenerator.h"
12
13#include "Foundation/Geometry/SampleListGenerator.hpp"
14
15using namespace Cogs::Geometry;
16using namespace Cogs::Reflection;
17
18void Cogs::Core::RiserTelescopicJointComponent::registerType()
19{
20 Field fields [] = {
23
25
28
32
35
38
41
43 };
44
45 Method methods [] = {
46 Method(Name("initialize"), &RiserTelescopicJointComponent::initialize),
47 Method(Name("update"), &RiserTelescopicJointComponent::update),
48 };
49
50 DynamicComponent::registerDerivedType<RiserTelescopicJointComponent>().setFields(fields).setMethods(methods);
51}
52
53void Cogs::Core::RiserTelescopicJointComponent::initialize(Context * context)
54{
55 body = context->store->createChildEntity("VariableExtrusionShape", getContainer());
56 arm = context->store->createChildEntity("VariableExtrusionShape", getContainer());
57 top = context->store->createChildEntity("VariableExtrusionShape", getContainer());
58}
59
60void Cogs::Core::RiserTelescopicJointComponent::update()
61{
62 auto variableExtrusion = getComponent<VariableExtrusionComponent>();
63
64 assert(variableExtrusion && "No variable extrusion available for riser.");
65
66 if (!variableExtrusion->trajectory) return;
67
68 auto trajectory = variableExtrusion->trajectory->getComponent<TrajectoryComponent>();
69
70 if (!trajectory) return;
71
72 if (!this->hasChanged() && !variableExtrusion->hasChanged()) {
73 if (this->getComponent<MaterialComponent>()->hasChanged()) {
74 updateChildren();
75 }
76
77 return;
78 }
79
80 std::vector<float> trajectoryDepths;
81
82 SampleListGenerator::generateIndexedSamples(startDepth, endDepth, trajectory->indexes.data(), static_cast<int>(trajectory->indexes.size()), trajectoryDepths);
83
84 if (trajectoryDepths.size() < 2) return;
85
86 if (trajectoryDepths[0] > startDepth || trajectoryDepths[trajectoryDepths.size() - 1] < endDepth) return;
87
88 updateChildren();
89
90 updateBody(trajectoryDepths);
91 updateArm(trajectoryDepths);
92 updateTop(trajectoryDepths);
93}
94
98void Cogs::Core::RiserTelescopicJointComponent::updateArm(const std::vector<float> & trajectoryDepths)
99{
100 auto variableExtrusion = arm->getComponent<VariableExtrusionComponent>();
101
102 std::vector<glm::vec2> profile;
103 std::vector<float> depths;
104
105 const float startDepth = this->startDepth + this->topLength;
106 const float endDepth = startDepth + this->armLength;
107 const float pistonLength = this->pistonLength * variableExtrusion->radiusScale;
108
109 const float innerRadius = this->armInnerRadius;
110 const float outerRadius = this->armOuterRadius;
111 const float bodyInnerRadius = this->pistonRadius;
112
113 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(startDepth);
114 profile.push_back(glm::vec2(outerRadius, 0)); depths.push_back(startDepth);
115
116 ProfileGenerator::insertPoints(depths, profile, outerRadius, startDepth, endDepth - pistonLength, trajectoryDepths.cbegin(), trajectoryDepths.cend());
117 ProfileGenerator::generateConnector(depths, profile, endDepth - pistonLength, endDepth, outerRadius, bodyInnerRadius, innerRadius, endDepth);
118 ProfileGenerator::insertPointsReverse(depths, profile, innerRadius, startDepth, endDepth, trajectoryDepths.cend());
119
120 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(startDepth);
121
122 if (this->reverse) {
123 ProfileGenerator::reverseProfile(depths, profile, this->startDepth, this->endDepth);
124 }
125
126 variableExtrusion->depths = std::move(depths);
127 variableExtrusion->profile = std::move(profile);
128
129 variableExtrusion->setChanged();
130
131 auto material = arm->getComponent<MaterialComponent>();
132
133 material->diffuseColor = armColor;
134 material->setChanged();
135}
136
140void Cogs::Core::RiserTelescopicJointComponent::updateTop(const std::vector<float> & trajectoryDepths)
141{
142 auto variableExtrusion = top->getComponent<VariableExtrusionComponent>();
143
144 std::vector<glm::vec2> profile;
145 std::vector<float> depths;
146
147 const float startDepth = this->startDepth;
148 const float endDepth = startDepth + this->topLength;
149
150 const float connectorLength = this->connectorLength * variableExtrusion->radiusScale;
151
152 const float innerRadius = this->armInnerRadius;
153 const float outerRadius = this->armOuterRadius;
154 const float connectorRadius = this->connectorRadius;
155
156 ProfileGenerator::generateConnector(depths, profile, startDepth, startDepth + connectorLength, innerRadius, connectorRadius, outerRadius, startDepth);
157 ProfileGenerator::insertPoints(depths, profile, outerRadius, startDepth + connectorLength, endDepth, trajectoryDepths.cbegin(), trajectoryDepths.cend());
158
159 profile.push_back(glm::vec2(outerRadius, 0)); depths.push_back(endDepth);
160 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(endDepth);
161 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(startDepth);
162
163 if (this->reverse) {
164 ProfileGenerator::reverseProfile(depths, profile, this->startDepth, this->endDepth);
165 }
166
167 variableExtrusion->depths = std::move(depths);
168 variableExtrusion->profile = std::move(profile);
169
170 variableExtrusion->setChanged();
171}
172
176void Cogs::Core::RiserTelescopicJointComponent::updateBody(const std::vector<float> & trajectoryDepths)
177{
178 auto variableExtrusion = body->getComponent<VariableExtrusionComponent>();
179
180 std::vector<glm::vec2> profile;
181 std::vector<float> depths;
182
183 const float endDepth = this->endDepth;
184 const float startDepth = endDepth - this->cylinderLength;
185
186 const float connectorLength = this->connectorLength * variableExtrusion->radiusScale;
187 const float connectorRadius = this->connectorRadius;
188
189 const float riserInnerRadius = this->armInnerRadius;
190 const float innerInnerRadius = this->armOuterRadius;
191 const float innerRadius = this->pistonRadius;
192 const float outerRadius = this->cylinderOuterRadius;
193 const float innerCylinderLength = this->innerCylinderLength;
194
195 ProfileGenerator::generateConnector(depths, profile, startDepth, startDepth + connectorLength, innerInnerRadius, connectorRadius, outerRadius, startDepth);
196 ProfileGenerator::insertPoints(depths, profile, outerRadius, startDepth + connectorLength, endDepth - connectorLength, trajectoryDepths.cbegin(), trajectoryDepths.cend());
197 ProfileGenerator::generateConnector(depths, profile, endDepth - connectorLength, endDepth, outerRadius, connectorRadius, riserInnerRadius, endDepth);
198
199 profile.push_back(glm::vec2(riserInnerRadius, 0)); depths.push_back(startDepth + innerCylinderLength);
200 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(startDepth + innerCylinderLength);
201
202 ProfileGenerator::insertPointsReverse(depths, profile, innerRadius, startDepth + connectorLength, startDepth + innerCylinderLength, trajectoryDepths.cend());
203
204 profile.push_back(glm::vec2(innerRadius, 0)); depths.push_back(startDepth + connectorLength);
205 profile.push_back(glm::vec2(innerInnerRadius, 0)); depths.push_back(startDepth + connectorLength);
206 profile.push_back(glm::vec2(innerInnerRadius, 0)); depths.push_back(startDepth);
207
208 if (this->reverse) {
209 ProfileGenerator::reverseProfile(depths, profile, this->startDepth, this->endDepth);
210 }
211
212 variableExtrusion->depths = std::move(depths);
213 variableExtrusion->profile = std::move(profile);
214
215 variableExtrusion->setChanged();
216}
217
218void Cogs::Core::RiserTelescopicJointComponent::updateChildren()
219{
220 const auto ves = getComponent<VariableExtrusionComponent>();
221
222 const auto children = {
223 arm->getComponent<VariableExtrusionComponent>(),
224 body->getComponent<VariableExtrusionComponent>(),
226 };
227
228 for (auto & c : children) {
229 c->trajectory = ves->trajectory;
230 c->closed = ves->closed;
231 c->radiusScale = ves->radiusScale;
232 }
233
234 const auto material = getComponent<MaterialComponent>();
235
236 const auto materials = {
237 body->getComponent<MaterialComponent>(),
238 top->getComponent<MaterialComponent>(),
239 };
240
241 for (auto & m : materials) {
242 m->diffuseColor = material->diffuseColor;
243 m->setChanged();
244 }
245}
ComponentType * getComponent() const
Definition: Component.h:159
void updateBody(const std::vector< float > &trajectoryDepths)
Updates the extrusion profile for the cylinder.
float innerCylinderLength
Length of the inner cylinder (inner stroke length).
void updateTop(const std::vector< float > &trajectoryDepths)
Update the extrusion profile for the arm.
float cylinderOuterRadius
Outer radius of the cylinder part.
bool reverse
If the joint profile should be reversed, i.e the arm after the cylinder.
void updateArm(const std::vector< float > &trajectoryDepths)
Update the extrusion profile for the arm.
float startDepth
Starting depth of the component.
Field definition describing a single data member of a data structure.
Definition: Field.h:68
Simple method definition.
Definition: Method.h:72
void reverseProfile(std::vector< float > &depths, std::vector< glm::vec2 > &profile, const float startDepth, const float endDepth)
Reverses the given profile.
Contains geometry calculations and generation.
Contains reflection support.
Definition: Component.h:11
Exposes material properties for legacy entities and code.
float radiusScale
Radius scale applied to the entire shape perpendicular to the direction of the trajectory.
std::shared_ptr< ComponentModel::Entity > trajectory
The trajectory this component is connected to.
Represents an unique name.
Definition: Name.h:70