Kale
Loading...
Searching...
No Matches
PathNodeGL.cpp
Go to the documentation of this file.
1/*
2 Copyright 2022 Rishi Challa
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#ifdef KALE_OPENGL
18
19#include "PathNode.hpp"
20
23
24#include <algorithm>
25
26using namespace Kale;
27
32
33 // Add PathNodes to the scene node loading map
34 Scene::addNodeSaveStateConstructor("PathNode", [](JSON json) -> std::shared_ptr<Node> {
35 return std::make_shared<PathNode>(json);
36 });
37
38 // Get shader paths
39 const std::string vertShaderPath = mainApp->getAssetFolderPath() + "shaders/PathNode.vert";
40 const std::string fragShaderPath = mainApp->getAssetFolderPath() + "shaders/PathNode.frag";
41
42 // Load the shaders
43 shader = std::make_unique<const OpenGL::Shader>(vertShaderPath.c_str(), fragShaderPath.c_str());
44
45 // Get the uniform locations
46 cameraUniform = static_cast<unsigned int>(shader->getUniformLocation("camera"));
47 localUniform = static_cast<unsigned int>(shader->getUniformLocation("local"));
48 vertexColorUniform = static_cast<unsigned int>(shader->getUniformLocation("vertexColor"));
49 strokeColorUniform = static_cast<unsigned int>(shader->getUniformLocation("strokeColor"));
50 zPositionUniform = static_cast<unsigned int>(shader->getUniformLocation("zPosition"));
51 beziersUniform = static_cast<unsigned int>(shader->getUniformLocation("beziers"));
52 numBeziersUniform = static_cast<unsigned int>(shader->getUniformLocation("numBeziers"));
53 fillUniform = static_cast<unsigned int>(shader->getUniformLocation("fill"));
54 strokeUniform = static_cast<unsigned int>(shader->getUniformLocation("stroke"));
55 strokeRadiusUniform = static_cast<unsigned int>(shader->getUniformLocation("strokeRadius"));
56
57 // Get the attribute locations
58 posAttribute = static_cast<unsigned int>(shader->getAttributeLocation("pos"));
59}
60
65 shader.reset();
66}
67
73
77 }
78
79 const std::array<Vector2f, 4> verts = {
84 };
85
86 std::copy(reinterpret_cast<const float*>(&verts.front()), reinterpret_cast<const float*>(&verts.back()), vertexArray->vertices.data.begin());
87
88 // OpenGL commands must be run on the main thread - add a task for it.
89 mainApp->runTaskOnMainThread([&]() { vertexArray->vertices.updateBuffer(); });
90}
91
97void PathNode::begin(const Scene& scene) {
99
103 }
104
105 const std::array<Vector2f, 4> verts = {
110 };
111
112 const std::array<unsigned int, 6> indices = {0, 1, 2, 1, 3, 2};
113
115 vertexArray = std::make_unique<OpenGL::VertexArray<Vector2f, 2>>(verts, indices, usage);
116 vertexArray->enableAttributePointer({posAttribute});
117}
118
125void PathNode::preUpdate(size_t threadNum, const Scene& scene, float deltaTime) {
126 // Call transformable update
128
129 // Update the Path based on the FSM if applicable
130 if (pathFSM.has_value()) {
131
132 // Update the state
133 pathFSM->updateState(deltaTime);
134
135 // Clear the path
136 std::fill(path.beziers.begin(), path.beziers.end(), CubicBezier{Vector2f::zero(), Vector2f::zero(), Vector2f::zero(), Vector2f::zero()});
137
138 // Loop through the composition & lerp between states as applicable
139 for (std::pair<int, float> composition : pathFSM->getStateComposition<int>()) {
140 path += pathFSM->getStructure<int>(composition.first) * composition.second;
141 }
142
143 // Update the bounding box
145 }
146
147 // Update the Path based on skeletal rig if applicable
148 if (skeletalAnimatable != nullptr) {
149 // Resize the path if it is not at the correct size
150 if (path.beziers.size() != basePath.value().beziers.size()) path.beziers.resize(basePath.value().beziers.size());
151
152 // Loop through the beziers and transform the beziers into the path
153 for (size_t i = 0; i < path.beziers.size(); i++) {
155 skeletalAnimatable->transform(basePath.value().beziers[i].start, skeletalWeights.value().at(i).startWeight, deltaTime),
156 skeletalAnimatable->transform(basePath.value().beziers[i].controlPoint1, skeletalWeights.value().at(i).controlPoint1Weight, deltaTime),
157 skeletalAnimatable->transform(basePath.value().beziers[i].controlPoint2, skeletalWeights.value().at(i).controlPoint2Weight, deltaTime),
158 skeletalAnimatable->transform(basePath.value().beziers[i].end, skeletalWeights.value().at(i).endWeight, deltaTime)
159 };
160 }
161
162 // Update the bounding box
164 }
165}
166
171void PathNode::render(const Camera& camera, float deltaTime) const {
172 // There is no vertex array setup - nothing to render
173 if (vertexArray == nullptr) return;
174
175 // Use the shader & provide uniforms
176 shader->useProgram();
177 shader->uniform(cameraUniform, camera);
182 shader->uniform(fillUniform, fill ? 1 : 0);
183 shader->uniform(strokeUniform, static_cast<int>(stroke));
185
186 shader->uniform(beziersUniform, reinterpret_cast<const Vector2f*>(path.beziers.data()), path.beziers.size() * 4);
187 shader->uniform(numBeziersUniform, static_cast<int>(path.beziers.size()));
188
189 // Draw, fragment shaders will do the rest of the work for us
190 vertexArray->draw();
191}
192
196void PathNode::end(const Scene& scene) {
197 vertexArray.reset();
198}
199
204 // Empty Body
205}
206
211PathNode::PathNode(const JSON& json) : Node(json.value("preUpdateTime", 100.0f), json.value("updateTime", 100.0f)) {
212 // Load Basic Properties
213 if (json.contains("name")) name = json["name"].get<std::string>();
214 if (json.contains("transform")) Transformable::transform = json["transform"].get<Transform>();
215 if (json.contains("zPosition")) zPosition = json["zPosition"].get<float>();
216 if (json.contains("fill")) fill = json["fill"].get<bool>();
217 if (json.contains("stroke")) stroke = static_cast<StrokeStyle>(json["stroke"].get<int>());
218 if (json.contains("strokeRadius")) strokeRadius = json["strokeRadius"].get<float>();
219 if (json.contains("color")) color = json["color"].get<Color>();
220 if (json.contains("strokeColor")) strokeColor = json["strokeColor"].get<Color>();
221 if (json.contains("path")) path = json["path"].get<Path>();
222
223 // Load FSMs
224 if (json.contains("transformFSM")) transformFSM = StateAnimatable<Transform>(json["transformFSM"]);
225 if (json.contains("pathFSM")) {
226 pathFSM = StateAnimatable<Path>(json["pathFSM"]);
227 path.beziers.resize(pathFSM->getStructure(pathFSM->getStateComposition<int>()[0].first).beziers.size());
228 }
229}
230
237PathNode::PathNode(const Path& path, bool fill, StrokeStyle stroke) : path(path), fill(fill), stroke(stroke) {
238 // Empty Body
239}
240
241#endif
std::string getAssetFolderPath() const
void runTaskOnMainThread(std::function< void()> task)
std::string name
Definition Node.hpp:98
std::vector< CubicBezier > beziers
Definition Path.hpp:61
Rect getBoundingBox() const
Definition Path.cpp:141
static unsigned int fillUniform
static void setup()
static unsigned int localUniform
static unsigned int numBeziersUniform
std::shared_ptr< SkeletalAnimatable > skeletalAnimatable
static unsigned int posAttribute
virtual void preUpdate(size_t threadNum, const Scene &scene, float deltaTime) override
static unsigned int cameraUniform
static unsigned int strokeUniform
virtual void render(const Camera &camera, float deltaTime) const override
static unsigned int zPositionUniform
void updateBoundingBox()
static void cleanup()
std::optional< std::vector< BezierWeights > > skeletalWeights
static std::unique_ptr< const OpenGL::Shader > shader
static unsigned int strokeRadiusUniform
std::optional< Path > basePath
std::unique_ptr< OpenGL::VertexArray< Vector2f, 2 > > vertexArray
std::optional< StateAnimatable< Path > > pathFSM
virtual void end(const Scene &scene) override
virtual void begin(const Scene &scene) override
static unsigned int vertexColorUniform
static unsigned int strokeColorUniform
StrokeStyle stroke
static unsigned int beziersUniform
static void addNodeSaveStateConstructor(const std::string &key, std::function< std::shared_ptr< Node >(JSON)> constructor)
Definition Scene.hpp:274
Transform getFullTransform() const
void updateTransform(float deltaTime)
std::optional< StateAnimatable< Transform > > transformFSM
nlohmann::json JSON
Definition Scene.hpp:39
Application * mainApp
Vector2f bottomRight
Definition Rect.hpp:36
Vector2f topRight() const
Definition Rect.cpp:56
Vector2f bottomLeft() const
Definition Rect.cpp:64
Vector2f topLeft
Definition Rect.hpp:31