Cogs.Core
RiserTensionerComponent.cpp
1#include "RiserTensionerComponent.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#include "Utilities/Math.h"
13
14#include "Foundation/Geometry/Glm.hpp"
15#include "Foundation/Geometry/SampleListGenerator.hpp"
16#include "Foundation/Geometry/PathGenerator.hpp"
17
18using namespace Cogs::Geometry;
19using namespace Cogs::Reflection;
20
21void Cogs::Core::RiserTensionerComponent::registerType()
22{
23 Field fields [] = {
26
29
37
40
42 };
43
44 Method methods [] = {
45 Method(Name("initialize"), &RiserTensionerComponent::initialize),
46 Method(Name("update"), &RiserTensionerComponent::update),
47 };
48
49 DynamicComponent::registerDerivedType<RiserTensionerComponent>().setFields(fields).setMethods(methods);
50}
51
52void Cogs::Core::RiserTensionerComponent::initialize(Context * context)
53{
54 innerShape = context->store->createChildEntity("VariableExtrusionShape", getContainer());
55 outerShape = context->store->createChildEntity("VariableExtrusionShape", getContainer());
56 trajectory = context->store->createChildEntity("Trajectory", getContainer());
57
58 innerShape->getComponent<VariableExtrusionComponent>()->trajectory = trajectory;
59 outerShape->getComponent<VariableExtrusionComponent>()->trajectory = trajectory;
60}
61
62void Cogs::Core::RiserTensionerComponent::update()
63{
64 auto variableExtrusion = getComponent<VariableExtrusionComponent>();
65
66 assert(variableExtrusion && "No variable extrusion available for riser.");
67
68 if (!variableExtrusion->trajectory) return;
69
70 auto mainTrajectory = variableExtrusion->trajectory->getComponent<TrajectoryComponent>();
71
72 if (!mainTrajectory) return;
73
74 if (!this->hasChanged() && !variableExtrusion->hasChanged() && !mainTrajectory->hasChanged()) {
75 if (this->getComponent<MaterialComponent>()->hasChanged()) {
76 updateChildren();
77 }
78
79 return;
80 }
81
82 updateChildren();
83
84 const float radiusScale = variableExtrusion->radiusScale;
85 const glm::vec3 scaleVector(radiusScale, radiusScale, 1);
86
87 float queryDepths [2] = {
88 this->startDepth,
89 this->endDepth,
90 };
91
92 glm::vec3 positions[2];
93 glm::vec3 directions[2];
94
95 PathGenerator::generateLinearPath(queryDepths,
96 2,
97 mainTrajectory->indexes.data(),
98 mainTrajectory->positions.data(),
99 static_cast<int>(mainTrajectory->indexes.size()),
100 positions,
101 directions);
102
103 const glm::vec3 topTrajectoryPosition = positions[0];
104 const glm::vec3 unscaledTopPosition = topTrajectoryPosition + this->topOffset;
105
106 const glm::vec3 topPosition = topTrajectoryPosition + (this->topOffset * scaleVector);
107 const glm::vec3 bottomTrajectoryPosition = positions[1];
108 const glm::vec3 bottomDirection = directions[1];
109
110 glm::vec3 bottomOffset = this->bottomOffset;
111 const glm::quat bottomRotation = getRotation(directions[0], bottomDirection);
112 bottomOffset = bottomRotation * bottomOffset;
113 const glm::vec3 unscaledBottomPosition = bottomTrajectoryPosition + bottomOffset;
114 const glm::vec3 bottomPosition = bottomTrajectoryPosition + (bottomOffset * scaleVector);
115
116 TrajectoryComponent * trajectory = this->trajectory->getComponent<TrajectoryComponent>();
117
118 auto innerShape = this->innerShape->getComponent<VariableExtrusionComponent>();
119 auto outerShape = this->outerShape->getComponent<VariableExtrusionComponent>();
120
121 const float unscaledTensionerLength = glm::length(unscaledTopPosition - unscaledBottomPosition);
122 const float tensionerLength = glm::length(topPosition - bottomPosition);
123
124 const float scaledLengthRatio = tensionerLength / unscaledTensionerLength;
125
126 trajectory->positions = { topPosition, bottomPosition };
127 trajectory->indexes = { 0, tensionerLength };
128 trajectory->setChanged();
129
130 const float cylinderRadius = this->cylinderRadius * radiusScale;
131 const float cylinderInnerRadius = this->cylinderInnerRadius * radiusScale;
132
133 const float cylinderBaseRadius = this->cylinderBaseRadius * radiusScale;
134 const float cylinderBaseLength = this->cylinderBaseLength * scaledLengthRatio;
135
136 const float cylinderLength = this->cylinderLength * scaledLengthRatio;
137
138 const float cylinderHeadRadius = this->cylinderHeadRadius * radiusScale;
139 const float cylinderHeadLength = this->cylinderHeadLength * scaledLengthRatio;
140
141 const float cylinderHeadStart = cylinderLength - cylinderHeadLength;
142
143 const float rodRadius = this->rodRadius * radiusScale;
144
145 std::vector<float> depths;
146 std::vector<glm::vec2> profile;
147
148 std::vector<float> innerDepths;
149 std::vector<glm::vec2> innerProfile;
150
151 profile.push_back(glm::vec2(0, 0)); depths.push_back(0);
152 profile.push_back(glm::vec2(cylinderBaseRadius, 0)); depths.push_back(0);
153 profile.push_back(glm::vec2(cylinderBaseRadius, 0)); depths.push_back(cylinderBaseLength);
154 profile.push_back(glm::vec2(cylinderRadius, 0)); depths.push_back(cylinderBaseLength);
155
156 profile.push_back(glm::vec2(cylinderRadius, 0)); depths.push_back(cylinderHeadStart);
157 profile.push_back(glm::vec2(cylinderHeadRadius, 0)); depths.push_back(cylinderHeadStart);
158 profile.push_back(glm::vec2(cylinderHeadRadius, 0)); depths.push_back(cylinderLength);
159 profile.push_back(glm::vec2(rodRadius, 0)); depths.push_back(cylinderLength);
160
161 profile.push_back(glm::vec2(rodRadius, 0)); depths.push_back(cylinderHeadStart);
162 profile.push_back(glm::vec2(cylinderInnerRadius, 0)); depths.push_back(cylinderHeadStart);
163 profile.push_back(glm::vec2(cylinderInnerRadius, 0)); depths.push_back(cylinderBaseLength);
164 profile.push_back(glm::vec2(0, 0)); depths.push_back(cylinderBaseLength);
165
166 outerShape->depths = std::move(depths);
167 outerShape->profile = std::move(profile);
168 outerShape->setChanged();
169
170 const float rodLength = this->rodLength * scaledLengthRatio;
171 const float rodStart = std::max(tensionerLength - rodLength, cylinderBaseLength);
172
173 innerProfile.push_back(glm::vec2(0, 0)); innerDepths.push_back(rodStart);
174 innerProfile.push_back(glm::vec2(rodRadius, 0)); innerDepths.push_back(rodStart);
175
176 innerProfile.push_back(glm::vec2(rodRadius, 0)); innerDepths.push_back(tensionerLength);
177 innerProfile.push_back(glm::vec2(0, 0)); innerDepths.push_back(tensionerLength);
178
179 innerShape->textureScale = glm::vec2(1.0f, 1.0f / (rodLength));
180 innerShape->textureOffset = glm::vec2(0.0f, -rodStart);
181
182 innerShape->depths = std::move(innerDepths);
183 innerShape->profile = std::move(innerProfile);
184 innerShape->setChanged();
185}
186
187void Cogs::Core::RiserTensionerComponent::updateChildren()
188{
189 const auto material = getComponent<MaterialComponent>();
190
191 const auto outerMaterial = outerShape->getComponent<MaterialComponent>();
192 outerMaterial->diffuseColor = material->diffuseColor;
193 outerMaterial->setChanged();
194}
float cylinderHeadRadius
Radius of the cylinder head.
float cylinderRadius
Radius of the main part of the outer cylinder.
float startDepth
Start depth along trajectory.
float cylinderHeadLength
Length of the cylinder head part (measured from the end of the cylinder).
glm::vec3 topOffset
Offset of top from trajectory position.
float cylinderBaseRadius
Radius of the cylinder base.
float cylinderInnerRadius
Inner radius of the cylinder.
float cylinderLength
Length of the entire outer cylinder.
float cylinderBaseLength
Length of the cylinder base part (measured from the start of the cylinder).
float endDepth
End depth along trajectory.
glm::vec3 bottomOffset
Offset of bottom from trajectory position.
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