diff --git a/ParticleGenerator/res/config/imgui.ini b/ParticleGenerator/res/config/imgui.ini index 2689187f8485437d98bb77d8297f1f9d77b690f1..d4e4896d772a7e2ef39d75dad9c3caca905fc5cd 100644 --- a/ParticleGenerator/res/config/imgui.ini +++ b/ParticleGenerator/res/config/imgui.ini @@ -3,10 +3,12 @@ Pos=60,60 Size=400,400 [Window][Dear ImGui Demo] -Pos=1032,14 +Pos=1051,35 Size=550,680 +Collapsed=1 [Window][Particle Generator] -Pos=-1,11 -Size=823,650 +Pos=7,9 +Size=476,521 +Collapsed=1 diff --git a/ParticleGenerator/src/Particle/PathPregenerated.cpp b/ParticleGenerator/src/Particle/PathPregenerated.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7554e01b25e67049405be805867d39717620c127 --- /dev/null +++ b/ParticleGenerator/src/Particle/PathPregenerated.cpp @@ -0,0 +1,27 @@ +#include "PathPregenerated.hpp" + +#include <iostream> +#include <cmath> + +namespace pg::particle { + PathPregenerated::PathPregenerated(size_t birth, const ct::Curve & curve, double u, double inc, glm::dvec3 posVar, double limitor) + : Particle(birth), _curve(curve), _positionVariation(posVar), _u(u), _increment(inc), _limitor(limitor) { + if(!this->_curve.empty()) { + this->setModel(glm::mat4(1.f)); + this->translate(this->_curve.at(0)); + } + } + + void PathPregenerated::update(double delta) { + this->_u += this->_increment; + size_t curvePosition = static_cast<size_t>(std::lerp(0.0, this->_curve.size()-1, this->_u)); + + if((this->_u > this->_limitor && this->_limitor > 0.0) || curvePosition >= this->_curve.size()) { + this->setBorn(static_cast<size_t>(0.0)); + return; + } + + this->setModel(glm::mat4(1.f)); + this->translate(this->_curve.at(curvePosition) + this->_positionVariation); + } +} \ No newline at end of file diff --git a/ParticleGenerator/src/Particle/PathPregenerated.hpp b/ParticleGenerator/src/Particle/PathPregenerated.hpp new file mode 100644 index 0000000000000000000000000000000000000000..53d485a35caf0a03b80336e85f59916255a27544 --- /dev/null +++ b/ParticleGenerator/src/Particle/PathPregenerated.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "Particle.hpp" + +namespace pg::particle { + class PathPregenerated : public Particle { + private: + const ct::Curve & _curve; + glm::dvec3 _positionVariation; + double _u, _increment, _limitor; + + public: + PathPregenerated(size_t birth, const ct::Curve & curve, double u = 0.0, double inc = 0.01, glm::dvec3 posvar = glm::dvec3(), double limitor = 0.0); + + inline const ct::Curve & getCurve() const {return this->_curve;} + inline double getParameterValue() const {return this->_u;} + inline glm::dvec3 getPositionVariation() const {return _positionVariation;} + inline double getParameterIncrement() const {return this->_increment;} + inline double getParameterLifeLimitor() const {return this->_limitor;} + + inline void setPositionVariation(const glm::dvec3& positionVariation) {this->_positionVariation = positionVariation;} + inline void setParameterValue(double u) {this->_u = u;} + inline void setParameterIncrement(double inc) {this->_increment = inc;} + inline void setParameterLifeLimitor(double limitor) {this->_limitor = limitor;} + + virtual void update(double delta = 0.0) override; + + }; +} \ No newline at end of file diff --git a/ParticleGenerator/src/Particle/generator/PathPregeneratedGenerator.cpp b/ParticleGenerator/src/Particle/generator/PathPregeneratedGenerator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8206d419ee051fcf77a78cd386e13332b7c038aa --- /dev/null +++ b/ParticleGenerator/src/Particle/generator/PathPregeneratedGenerator.cpp @@ -0,0 +1,70 @@ +#include "PathPregeneratedGenerator.hpp" + +#include <random> + +#define GLM_ENABLE_EXPERIMENTAL +#include <glm/gtx/rotate_vector.hpp> + +#include <iostream> + +namespace pg::particle { + PathPregeneratedGenerator::PathPregeneratedGenerator(ct::CurveGenerator * generator, const ct::Curve & ctrlPoints, double increment, double max, ct::Point position, float posVar) + : _generator(generator), _controlPoints(ctrlPoints), _path(), _u(0.f), _spacing(0.f), _increment(0.01f), _limitor(0.f) { + this->update(increment, max); + } + + void PathPregeneratedGenerator::update(double increment, double max) { + std::vector<double> parameters; + for(double i = 0.0; i <= max; i += increment) { + parameters.push_back(i); + } + + this->_path.clear(); + this->_path = this->_generator->generate(this->_controlPoints, parameters); + } + + std::vector<std::unique_ptr<PathPregenerated>> PathPregeneratedGenerator::generate(size_t count, size_t birth) const { + std::random_device device; + std::mt19937 randomEngine(device()); + + using ureal_dist = std::uniform_real_distribution<double>; + ureal_dist positionGenerator(-this->getPositionVariation(), this->getPositionVariation()); + + std::vector<std::unique_ptr<PathPregenerated>> particles; + particles.reserve(count); + + std::vector<ct::Point> realCtrlPoint; + for(auto & point : this->_controlPoints) { + glm::dvec3 glmPoint = point; + + glmPoint = glm::rotateZ<double>(glmPoint, glm::radians<double>(this->m_rotation.z)); + glmPoint = glm::rotateY<double>(glmPoint, glm::radians<double>(this->m_rotation.y)); + glmPoint = glm::rotateX<double>(glmPoint, glm::radians<double>(this->m_rotation.x)); + + realCtrlPoint.push_back(glmPoint + ct::Point(m_position)); + } + + float u_space = 0.0; + for (unsigned int i = 0; i < count; ++i) + { + glm::dvec3 positionVariation(0.0); + + positionVariation.x = positionGenerator(randomEngine); + positionVariation.y = positionGenerator(randomEngine); + positionVariation.z = positionGenerator(randomEngine); + + PathPregenerated * particle = new PathPregenerated(birth, this->_path, this->_u + u_space, this->_increment, positionVariation, this->_limitor); + particle->setPositionVariation(positionVariation); + particle->setParameterLifeLimitor(this->getParameterLifeLimitor()); + + u_space += this->getSpacing(); + if(u_space > 1.0) { + u_space = 0.0; + } + + particles.push_back(std::unique_ptr<PathPregenerated>(particle)); + } + + return particles; + } +} \ No newline at end of file diff --git a/ParticleGenerator/src/Particle/generator/PathPregeneratedGenerator.hpp b/ParticleGenerator/src/Particle/generator/PathPregeneratedGenerator.hpp new file mode 100644 index 0000000000000000000000000000000000000000..48edcbde96c3d1040a31b7d8593c93e085bfa15e --- /dev/null +++ b/ParticleGenerator/src/Particle/generator/PathPregeneratedGenerator.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "Generator.hpp" +#include "../PathPregenerated.hpp" + +namespace pg::particle { + class PathPregeneratedGenerator : public Generator<PathPregenerated> { + private: + ct::CurveGenerator * _generator; + ct::Curve _controlPoints; + ct::Curve _path; + float _u, _spacing, _increment, _limitor; + + public: + PathPregeneratedGenerator(ct::CurveGenerator *, const ct::Curve &, double = 0.01, double = 1.00000001, ct::Point = ct::Point(), float = 0.f); + + inline ct::CurveGenerator * getGenerator() const {return this->_generator;} + inline const ct::Curve & getControlPoint() const {return this->_controlPoints;} + inline const ct::Curve & getPath() const {return this->_path;} + inline float getParameter() const {return this->_u;} + inline float getSpacing() const {return this->_spacing;} + inline float getParameterIncrement() const {return this->_increment;} + inline float getParameterLifeLimitor() const {return this->_limitor;} + + inline void setGenerator(ct::CurveGenerator * generator) {this->_generator = generator;} + inline void setDefaultParameterValue(float u) {this->_u = u;} + inline void setParameterIncrement(float inc) {this->_increment = inc;} + inline void setParameterLifeLimitor(float limitor) {this->_limitor = limitor;} + + virtual void update(double, double); + virtual std::vector<std::unique_ptr<PathPregenerated>> generate(size_t count, size_t birth = 0) const; + }; +} \ No newline at end of file diff --git a/ParticleGenerator/src/Scene/Scenes/PathPregenerated.cpp b/ParticleGenerator/src/Scene/Scenes/PathPregenerated.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1c4c2e7bed17cb3e2050603c737aee009b3712b --- /dev/null +++ b/ParticleGenerator/src/Scene/Scenes/PathPregenerated.cpp @@ -0,0 +1,143 @@ +#include "PathPregenerated.hpp" + +#include <chrono> +#include <glm/gtc/matrix_transform.hpp> + +namespace pg::scene { + PathPregenerated::PathPregenerated(ct::CurveGenerator * generator, const ct::Curve & ctrlpoint) + : SceneParticle(1024), + _ubo(0), + _program(), + _texture(), + _generator(generator, ctrlpoint), + _trajectory(&this->_generator), + _color(1.f) {} + + void PathPregenerated::initialize() { + this->_billboard.initialize(); + this->_trajectory.initialize(); + if(!this->_program.usable()) { + pg::Source vertices("res/shaders/scene/Billboard.vert", pg::Source::Categorie::VERTEX); + pg::Source fragment("res/shaders/scene/Billboard.frag", pg::Source::Categorie::FRAGMENT); + + this->_program << vertices; + this->_program << fragment; + + this->_program.link(); + + vertices.release(); + fragment.release(); + } + + pg::error::OpenGLError::check(); + + glCreateBuffers(1, &this->_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, this->_ubo); + glBufferData(GL_UNIFORM_BUFFER, 1024 * sizeof(glm::mat4), nullptr, GL_DYNAMIC_DRAW); + + GLuint uniforme_index = glGetUniformBlockIndex(this->_program.id(), "uModels_t"); + glBindBufferBase(GL_UNIFORM_BUFFER, uniforme_index, this->_ubo); + + pg::error::OpenGLError::check(); + + this->_texture.load("res/textures/smoke1.png"); + + pg::error::OpenGLError::check(); + + this->_generator.setPosition({0.f, 0.f, 0.f}); + this->_generator.setPositionVariation(0.5f); + //this->_generator.setParameterIncrement(0.01f); + //this->_generator.setParameterLifeLimitor(1.0f); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glClearColor(0.25f, 0.f, 0.15f, 1.0f); + } + + void PathPregenerated::update(double current_time) { + static auto start = std::chrono::high_resolution_clock::now(); + auto end = std::chrono::high_resolution_clock::now(); + + if(!this->isFreezeEnable()) { + pg::particle::Particle::purge(this->_particles, static_cast<size_t>(current_time), this->getLifetime()); + if(duration_cast<std::chrono::milliseconds>(end - start).count() >= 500) { + start = std::chrono::high_resolution_clock::now(); + if(this->isSpawnEnable()) { + this->spawn(this->getSpawnCount(), current_time); + } + } + + if(duration_cast<std::chrono::milliseconds>(end - start).count() >= 10) { + for(auto& particle : this->_particles) { + particle->update(0.0); + } + } + } + } + + void PathPregenerated::render(const Camera & camera, double current_time) { + const glm::mat4 VIEW_MATRIX = camera.getViewMatrix(); + const glm::mat4 PROJECTION_MATRIX = camera.getViewFrustum().getProjectionMatrix(); + + this->_trajectory.render(camera, current_time); + + std::vector<glm::mat4> models; + + for(auto & particle : this->_particles) { + models.push_back(particle->getModel()); + } + + pg::error::OpenGLError::check(); + + glBindBuffer(GL_UNIFORM_BUFFER, this->_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, models.size() * sizeof(glm::mat4), models.data()); + + pg::error::OpenGLError::check(); + + this->_program.use(); + + this->_program.setUniform("uView", VIEW_MATRIX); + this->_program.setUniform("uProj", PROJECTION_MATRIX); + this->_program.setUniform("uSlot", 0); + this->_program.setUniform("uColor", this->_color); + + pg::error::OpenGLError::check(); + + this->_texture.bind(); + if(this->isRenderEnable()) { + this->_billboard.draw(this->_particles.size()); + } + + pg::error::OpenGLError::check(); + } + + void PathPregenerated::destroy() { + glDeleteBuffers(1, &this->_ubo); + this->_billboard.destroy(); + this->_particles.clear(); + + pg::error::OpenGLError::check(); + } + + void PathPregenerated::changeParticletexture(const std::string & PathPregenerated) { + this->_texture.load(PathPregenerated); + } + + void PathPregenerated::spawn(int count, double current_time) { + //this->_generator._model = glm::mat4(1.f); + //this->_generator._model = glm::rotate(this->_generator._model, glm::radians(this->_generator.getRotation().z), {0.f, 0.f, 1.f}); + //this->_generator._model = glm::rotate(this->_generator._model, glm::radians(this->_generator.getRotation().y), {0.f, 1.f, 0.f}); + //this->_generator._model = glm::rotate(this->_generator._model, glm::radians(this->_generator.getRotation().x), {1.f, 0.f, 0.f}); + //this->_generator._model = glm::translate(this->_generator._model, this->_generator.getPosition()); + + this->_generator.setModel(glm::mat4(1.f)); + this->_generator.rotate(this->_generator.getRotation()); + this->_generator.translate(this->_generator.getPosition()); + + if((count + this->_particles.size()) <= this->getMaxParticles()) { + std::vector<std::unique_ptr<pg::particle::PathPregenerated>> newParticles = this->_generator.generate(count, static_cast<size_t>(current_time)); + this->_particles.insert(this->_particles.begin(), std::make_move_iterator(newParticles.begin()), std::make_move_iterator(newParticles.end())); + } + + } +} \ No newline at end of file diff --git a/ParticleGenerator/src/Scene/Scenes/PathPregenerated.hpp b/ParticleGenerator/src/Scene/Scenes/PathPregenerated.hpp new file mode 100644 index 0000000000000000000000000000000000000000..85f3eb7e6c0e2dd5620b374e08ece1f8afc67fc4 --- /dev/null +++ b/ParticleGenerator/src/Scene/Scenes/PathPregenerated.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "../Scene.hpp" +#include "TrajectoryPregenerated.hpp" + +#include "../../Renderer/Renderer.hpp" +#include "../../Particle/generator/PathPregeneratedGenerator.hpp" +#include "../../Interface/Scene/Path.hpp" +#include "../../Mesh/Billboard.hpp" +#include "../../System/Window.hpp" + +namespace pg::scene { + class PathPregenerated : public SceneParticle { + private: + GLuint _ubo; + + Program _program; + Billboard _billboard; + TrajectoryPregenerated _trajectory; + Material _texture; + particle::PathPregeneratedGenerator _generator; + glm::vec4 _color; + + public: + PathPregenerated(ct::CurveGenerator *, const ct::Curve &); + virtual ~PathPregenerated() = default; + + virtual void initialize(); + virtual void render(const Camera &, double); + virtual void update(double); + virtual void destroy(); + + inline const Program & getProgram() const {return this->_program;} + inline const Material & getTexture() const {return this->_texture;} + inline const particle::PathPregeneratedGenerator & getGenerator() const {return this->_generator;} + + void changeParticletexture(const std::string &); + + virtual std::string name() const {return "Path Pregenerated Scene";} + //virtual std::optional<interface::Interface *> interface() {return std::optional<interface::Interface *>(&this->_interface);} + + virtual void spawn(int, double); + + friend class pg::interface::Path; + }; +} \ No newline at end of file diff --git a/ParticleGenerator/src/Scene/Scenes/TrajectoryPregenerated.cpp b/ParticleGenerator/src/Scene/Scenes/TrajectoryPregenerated.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ed027ab5f219ce67e714144ed7689e4fe2934bf7 --- /dev/null +++ b/ParticleGenerator/src/Scene/Scenes/TrajectoryPregenerated.cpp @@ -0,0 +1,90 @@ +#include "TrajectoryPregenerated.hpp" +#include <glm/gtc/matrix_transform.hpp> + +#include <CurveTools/CPU/CurveSampler.hpp> + +namespace pg::scene { + TrajectoryPregenerated::TrajectoryPregenerated(particle::PathPregeneratedGenerator * generator, double increment) + : _generator(generator), + _vbo(this->_vao, {layout::POSITION, layout::COLOR}), + _increment(increment), + _color(0.0f, 1.f, 0.f, 1.f), + _pointSize(8.f), + _lineSize(1.f), + _controlLine(false), + _enableControl(true), + _enableLine(true), + _enableRender(true) {} + + void TrajectoryPregenerated::initialize() { + this->update(0.0); + if(!this->_program.usable()) { + Source vert("res/shaders/scene/Trajectory.vert", Source::Categorie::VERTEX); + Source frag("res/shaders/scene/Trajectory.frag", Source::Categorie::FRAGMENT); + + this->_program << vert; + this->_program << frag; + + this->_program.link(); + + vert.release(); + frag.release(); + } + } + + void TrajectoryPregenerated::update(double) { + std::vector<float> traj; + for(auto & point : this->_generator->getControlPoint()) { + traj.push_back(static_cast<float>(point.x)); + traj.push_back(static_cast<float>(point.y)); + traj.push_back(static_cast<float>(point.z)); + + traj.push_back(0.25f); + traj.push_back(0.25f); + traj.push_back(0.25f); + } + + for(auto & point : this->_generator->getPath()) { + traj.push_back(static_cast<float>(point.x)); + traj.push_back(static_cast<float>(point.y)); + traj.push_back(static_cast<float>(point.z)); + + traj.push_back(1.f); + traj.push_back(1.f); + traj.push_back(1.f); + } + this->_vbo.set(traj); + } + + void TrajectoryPregenerated::render(const Camera & camera, double current_time) { + if(this->_enableRender) { + glEnable(GL_LINE_SMOOTH); + glLineWidth(this->_lineSize); + this->_vao.bind(); + + glEnable(GL_PROGRAM_POINT_SIZE); + this->_program.use(); + this->_program.setUniform("uProj", camera.getViewFrustum().getProjectionMatrix()); + this->_program.setUniform("uView", camera.getViewMatrix()); + this->_program.setUniform("uModel", this->_generator->getModel()); + this->_program.setUniform("uColor", this->_color); + this->_program.setUniform("uPointSize", this->_pointSize); + + + GLsizei raw = static_cast<GLsizei>(this->_generator->getControlPoint().size()); + GLsizei total = static_cast<GLsizei>(this->_vbo.vertices()); + + if(this->_enableLine) { + glDrawArrays(GL_LINE_STRIP, raw, total - raw); + } + + if(this->_enableControl) { + glDrawArrays(this->_controlLine ? GL_LINE_STRIP : GL_POINTS, 0, static_cast<GLsizei>(this->_generator->getControlPoint().size())); + } + } + } + + void TrajectoryPregenerated::destroy() { + + } +} \ No newline at end of file diff --git a/ParticleGenerator/src/Scene/Scenes/TrajectoryPregenerated.hpp b/ParticleGenerator/src/Scene/Scenes/TrajectoryPregenerated.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6f13d8a3f4e4f6269672b53107c8e4889318f484 --- /dev/null +++ b/ParticleGenerator/src/Scene/Scenes/TrajectoryPregenerated.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "../../Renderer/Renderer.hpp" +#include "../../Particle/generator/PathPregeneratedGenerator.hpp" +#include "../../Interface/Scene/Trajectory.hpp" +#include "../Scene.hpp" + +namespace pg::scene { + class TrajectoryPregenerated : public Scene { + private: + particle::PathPregeneratedGenerator * _generator; + VertexArray _vao; + VerticeBuffer _vbo; + Program _program; + double _increment; + + glm::vec4 _color; + float _pointSize; + float _lineSize; + bool _controlLine; + bool _enableControl; + bool _enableLine; + bool _enableRender; + + public: + TrajectoryPregenerated(particle::PathPregeneratedGenerator *, double = 0.1f); + + inline particle::PathPregeneratedGenerator * getGenerator() const {return this->_generator;} + inline double getIncrement() const {return this->_increment;} + inline const glm::vec4 & getColor() const {return this->_color;} + inline float getPointSize() const {return this->_pointSize;} + inline bool isConrolLineEnable() const {return this->_controlLine;} + inline bool isRenderingEnable() const {return this->_enableRender;} + + void initialize(); + void render(const Camera &, double); + void update(double); + void destroy(); + + friend class interface::Trajectory; + }; +} \ No newline at end of file diff --git a/ParticleGenerator/src/main.cpp b/ParticleGenerator/src/main.cpp index ecdda9055ff7de0682746b77d2ebae38f339ee25..73ca2cb174541f8a4fb23fedc3b50aa523409a40 100644 --- a/ParticleGenerator/src/main.cpp +++ b/ParticleGenerator/src/main.cpp @@ -14,6 +14,7 @@ #include "Scene/Scenes/PhysicSprite.hpp" #include "Scene/Scenes/MultyPath.hpp" #include "Scene/Scenes/MeshGeneratorModel.hpp" +#include "Scene/Scenes/PathPregenerated.hpp" #include "Interface/Manager.hpp" @@ -84,6 +85,7 @@ int main(int argc, const char * argv[]) { pg::scene::Path path(&bezier, ctrlPoints); pg::scene::MultyPath multyPath(ctrlPoints); pg::scene::MeshGeneratorModel meshGeneratorModel; + pg::scene::PathPregenerated pathPregenerated(&bezier, ctrlPoints); pg::Manager manager(window); pg::interface::Manager imanager(window, manager); @@ -94,6 +96,7 @@ int main(int argc, const char * argv[]) { manager.add(&meshGenerator); manager.add(&multyPath); manager.add(&meshGeneratorModel); + manager.add(&pathPregenerated); while(window.isOpen()) { double current_time = glfwGetTime();