diff --git a/ParticleGenerator/res/config/imgui.ini b/ParticleGenerator/res/config/imgui.ini index 66570e980fd9b91b81d11036729f9fe88dd0631c..95c0d993f74668de113b95e11920c341a443c429 100644 --- a/ParticleGenerator/res/config/imgui.ini +++ b/ParticleGenerator/res/config/imgui.ini @@ -3,11 +3,10 @@ Pos=60,60 Size=400,400 [Window][Dear ImGui Demo] -Pos=926,43 +Pos=1131,67 Size=550,680 -Collapsed=1 [Window][Particle Generator] -Pos=60,60 -Size=141,81 +Pos=65,78 +Size=455,596 diff --git a/ParticleGenerator/src/Interface/Scene/MeshGenerator.cpp b/ParticleGenerator/src/Interface/Scene/MeshGenerator.cpp index aeff43f665a9d239e1c23aad0b9a35799436866e..e35b3f4c72cd89b86ba02d6a92a57aa5c40e5e0a 100644 --- a/ParticleGenerator/src/Interface/Scene/MeshGenerator.cpp +++ b/ParticleGenerator/src/Interface/Scene/MeshGenerator.cpp @@ -28,6 +28,10 @@ namespace pg::interface { ImGui::SameLine(); ImGui::ColorEdit4("Color : ", &this->parent()->_color[0]); + ImGui::SeparatorText("Position"); + ImGui::DragFloat3("Position", &this->parent()->_meshPosition[0]); + ImGui::DragFloat3("Rotation", &this->parent()->_meshRotation[0]); + ImGui::SeparatorText("Generators"); if(!this->parent()->_generators.empty()) { diff --git a/ParticleGenerator/src/Particle/Particle.hpp b/ParticleGenerator/src/Particle/Particle.hpp index 0d0ef5529442f86b1be98bcc1a82684ae9dedfef..54dce2f121c1941d12732d756f79599802325453 100644 --- a/ParticleGenerator/src/Particle/Particle.hpp +++ b/ParticleGenerator/src/Particle/Particle.hpp @@ -5,6 +5,8 @@ #include <CurveTools/CPU/CurveGenerator.hpp> +#include <glm/mat4x4.hpp> + namespace pg::particle { class Particle @@ -14,6 +16,8 @@ namespace pg::particle ct::Point m_position; public: + glm::mat4 _model = glm::mat4(1.f); + Particle(const ct::Point& position = ct::Point()); Particle(size_t born, const ct::Point& position = ct::Point()); virtual ~Particle() = default; diff --git a/ParticleGenerator/src/Particle/Physics.cpp b/ParticleGenerator/src/Particle/Physics.cpp index f2fff0f0676df019d44e1fc1464e428435f2cd52..dd67108cdbdbcf411defaeccfc3c6e19100e034c 100644 --- a/ParticleGenerator/src/Particle/Physics.cpp +++ b/ParticleGenerator/src/Particle/Physics.cpp @@ -1,5 +1,7 @@ #include "Physics.hpp" +#include <glm/gtc/matrix_transform.hpp> + namespace pg::particle { Physics::Physics(size_t birth, const ct::Point& position, const glm::dvec3& velocity) : Particle(birth, position), m_velocity(velocity), m_acceleration(ct::Point()), m_friction(ct::Point()) {} @@ -11,6 +13,7 @@ namespace pg::particle { m_acceleration -= static_cast<glm::dvec3>(m_friction) * m_velocity; m_velocity += m_acceleration; - this->translate(this->m_velocity); + //this->translate(this->m_velocity); + this->_model = glm::translate(this->_model, glm::vec3(this->m_velocity)); } } \ No newline at end of file diff --git a/ParticleGenerator/src/Particle/generator/Generator.hpp b/ParticleGenerator/src/Particle/generator/Generator.hpp index ae234afe8f41e00aa4375b72831a4506d762fcb8..8f290d40bec1490098cfa81d50ce5a7ba2dcf9b9 100644 --- a/ParticleGenerator/src/Particle/generator/Generator.hpp +++ b/ParticleGenerator/src/Particle/generator/Generator.hpp @@ -3,6 +3,9 @@ #include <memory> #include "../Particle.hpp" +#define GLM_ENABLE_EXPERIMENTAL +#include <glm/gtx/rotate_vector.hpp> + namespace pg::particle { template <typename T> @@ -13,6 +16,8 @@ namespace pg::particle { glm::vec3 m_rotation; public: + glm::mat4 _model = glm::mat4(1.f); + Generator(const glm::vec3& position = glm::vec3(0.f), float positionVariation = 0.0) : m_position(position), m_positionVariation(positionVariation), m_rotation(0.0) {} diff --git a/ParticleGenerator/src/Particle/generator/PhysicsGenerator.cpp b/ParticleGenerator/src/Particle/generator/PhysicsGenerator.cpp index ed0665858ff87e38e3a51bad7375d8a1dccddf29..6c39ba54c226faabbcb3ba1251c0bf4579222b3a 100644 --- a/ParticleGenerator/src/Particle/generator/PhysicsGenerator.cpp +++ b/ParticleGenerator/src/Particle/generator/PhysicsGenerator.cpp @@ -45,7 +45,7 @@ namespace pg::particle for (size_t i = 0; i < count; ++i) { Physics * particle = new Physics(birth, this->getPosition()); - particle->translate({p(randomEngine), p(randomEngine), p(randomEngine)}); + //particle->translate({p(randomEngine), p(randomEngine), p(randomEngine)}); glm::vec3 velocityVariation = {vx(randomEngine), vy(randomEngine), vz(randomEngine)}; glm::vec3 accelerationVariation = {ax(randomEngine), ay(randomEngine), az(randomEngine)}; @@ -71,6 +71,9 @@ namespace pg::particle particle->setAcceleration(realAcceleration); particle->setFriction(realFriction); + particle->_model = this->_model; + particle->_model = glm::translate(particle->_model, {p(randomEngine), p(randomEngine), p(randomEngine)}); + particles.push_back(std::unique_ptr<Physics>(particle)); } diff --git a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp index 2c8daad45a60a8010caa6527b33328770b600c88..a01bf0597c9f6cc61b6b46bc6be34f25fc93e39e 100644 --- a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp +++ b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp @@ -100,7 +100,13 @@ namespace pg::scene { this->_meshProgram.use(); - this->_meshProgram.setUniform("uModel", glm::mat4(1.f)); + glm::mat4 model = glm::mat4(1.f); + model = glm::rotate(model, glm::radians(this->_meshRotation.z), {0.f, 0.f, 1.f}); + model = glm::rotate(model, glm::radians(this->_meshRotation.y), {0.f, 1.f, 0.f}); + model = glm::rotate(model, glm::radians(this->_meshRotation.x), {1.f, 0.f, 0.f}); + model = glm::translate(model, this->_meshPosition); + + this->_meshProgram.setUniform("uModel", model); this->_meshProgram.setUniform("uView", VIEW_MATRIX); this->_meshProgram.setUniform("uProj", PROJECTION_MATRIX); @@ -118,10 +124,10 @@ namespace pg::scene { while(particle_accumulator < this->_particles.size()) { std::vector<glm::mat4> models; for(size_t i = 0; i < this->_particles.size() && i < 1024; i++) { - glm::mat4 model = glm::mat4(1.0); + //glm::mat4 model = glm::mat4(1.0); if(i + particle_accumulator < this->_particles.size()) { - model = glm::translate(model, glm::vec3(this->_particles[particle_accumulator + i]->getPosition())); - models.push_back(model); + //model = glm::translate(model, glm::vec3(this->_particles[particle_accumulator + i]->getPosition())); + models.push_back(this->_particles[particle_accumulator + i]->_model); } } @@ -186,10 +192,22 @@ namespace pg::scene { void MeshGenerator::spawn(int count, double current_time) { for(auto & generator : this->_generators) { + //? ##### + generator._model = glm::mat4(1.f); + + generator._model = glm::rotate(generator._model, glm::radians(this->_meshRotation.z), {0.f, 0.f, 1.f}); + generator._model = glm::rotate(generator._model, glm::radians(this->_meshRotation.y), {0.f, 1.f, 0.f}); + generator._model = glm::rotate(generator._model, glm::radians(this->_meshRotation.x), {1.f, 0.f, 0.f}); + + generator._model = glm::translate(generator._model, generator.getPosition() + this->_meshPosition); + //? ##### + + if((count + this->_particles.size()) <= this->getMaxParticles()) { std::vector<std::unique_ptr<particle::Physics>> newParticles = 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())); } + } } diff --git a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp index 82ef60d06dfe518ed6979e435de9018020298e5c..d5382bcae02c6ee70b73af9ba1f42ddac79e2898 100644 --- a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp +++ b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp @@ -29,7 +29,8 @@ namespace pg::scene { interface::MeshGenerator _interface; - public: + public: + MeshGenerator(); virtual ~MeshGenerator() = default; diff --git a/ParticleGenerator/src/Scene/Scenes/MeshGeneratorModel.cpp b/ParticleGenerator/src/Scene/Scenes/MeshGeneratorModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3ed710cd0c442293dbe0c89075b498b477dcf09 --- /dev/null +++ b/ParticleGenerator/src/Scene/Scenes/MeshGeneratorModel.cpp @@ -0,0 +1,206 @@ +#include "MeshGeneratorModel.hpp" + +#include "../../Mesh/Model.hpp" + +#define GLM_ENABLE_EXPERIMENTAL +#include <glm/gtx/normal.hpp> +#include <glm/gtc/matrix_transform.hpp> + +namespace pg::scene { + MeshGeneratorModel::MeshGeneratorModel() + : SceneParticle(16384), + _mesh(), + _meshProgram(), + _meshPosition(0.f), + _meshRotation(0.f), + _generators(), + _meshParticle(), + _meshParticleTexture(), + _meshParticleProgram(), + _ubo(0), + _color(1.f) {} + + void MeshGeneratorModel::initialize() { + if(!this->_mesh.isGenerated()) { + this->changeMesh("res/models/sphere.obj"); + } + + if(!this->_meshParticle.isGenerated()) { + this->changeMeshParticle("res/models/sphere.obj"); + } + + if(!this->_meshProgram.usable()) { + Source vert("res/shaders/scene/Color.vert", Source::Categorie::VERTEX); + Source frag("res/shaders/scene/Color.frag", Source::Categorie::FRAGMENT); + + this->_meshProgram << vert; + this->_meshProgram << frag; + + this->_meshProgram.link(); + + vert.release(); + frag.release(); + } + + this->_meshParticleTexture.load("res/textures/smoke1.png"); + + if(!this->_meshParticleProgram.usable()) { + Source vert("res/shaders/scene/Texture-Fat.vert", Source::Categorie::VERTEX); + Source frag("res/shaders/scene/Texture.frag", Source::Categorie::FRAGMENT); + + this->_meshParticleProgram << vert; + this->_meshParticleProgram << frag; + + this->_meshParticleProgram.link(); + + vert.release(); + frag.release(); + } + + { + 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->_meshParticleProgram.id(), "uModels_t"); + glBindBufferBase(GL_UNIFORM_BUFFER, uniforme_index, this->_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + this->_particles.reserve(16384); + this->setSpawnCount(1); + this->setSpawnFrequence(3000); + this->setLifetime(3); + } + + void MeshGeneratorModel::update(double current_time) { + static auto start = std::chrono::high_resolution_clock::now(); + auto end = std::chrono::high_resolution_clock::now(); + + if(!this->isFreezeEnable()) { + particle::Particle::purge(this->_particles, static_cast<size_t>(current_time), this->getLifetime()); + if(duration_cast<std::chrono::milliseconds>(end - start).count() >= this->getSpawnFrequence()) { + 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 MeshGeneratorModel::render(const Camera & camera, double current_time) { + const glm::mat4 VIEW_MATRIX = camera.getViewMatrix(); + const glm::mat4 PROJECTION_MATRIX = camera.getViewFrustum().getProjectionMatrix(); + + // -------- + + this->_meshProgram.use(); + + this->_meshProgram.setUniform("uModel", glm::mat4(1.f)); + this->_meshProgram.setUniform("uView", VIEW_MATRIX); + this->_meshProgram.setUniform("uProj", PROJECTION_MATRIX); + + this->_meshProgram.setUniform("uColor", glm::vec4(0.6f, 0.2f, 0.4f, 1.f)); + + pg::error::OpenGLError::check(); + + this->_mesh.draw(); + + pg::error::OpenGLError::check(); + + // -------- + + size_t particle_accumulator = 0; + while(particle_accumulator < this->_particles.size()) { + std::vector<glm::mat4> models; + for(size_t i = 0; i < this->_particles.size() && i < 1024; i++) { + glm::mat4 model = glm::mat4(1.0); + if(i + particle_accumulator < this->_particles.size()) { + model = glm::translate(model, glm::vec3(this->_particles[particle_accumulator + i]->getPosition())); + models.push_back(model); + } + } + + glBindBuffer(GL_UNIFORM_BUFFER, this->_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, models.size() * sizeof(glm::mat4), models.data()); + + pg::error::OpenGLError::check(); + + this->_meshParticleTexture.bind(0); + this->_meshParticleProgram.use(); + + this->_meshParticleProgram.setUniform("uView", VIEW_MATRIX); + this->_meshParticleProgram.setUniform("uProj", PROJECTION_MATRIX); + this->_meshParticleProgram.setUniform("uSlot", 0); + this->_meshParticleProgram.setUniform("uColor", this->_color); + + pg::error::OpenGLError::check(); + + if(this->isRenderEnable()) { + this->_meshParticle.draw(this->_particles.size()); + } + + pg::error::OpenGLError::check(); + + particle_accumulator += 1024; + } + + // -------- + } + + void MeshGeneratorModel::destroy() { + glDeleteBuffers(1, &this->_ubo); + this->_particles.clear(); + } + + void MeshGeneratorModel::changeMesh(const std::string & path) { + this->_particles.clear(); + this->_generators.clear(); + Model model(path); + + MeshGeometry geometry = model.getMeshGeometry(); + this->_mesh.generate(geometry.vertices, geometry.indices); + + auto & vertices = geometry.vertices; + auto & indices = geometry.indices; + + for(size_t i = 0; i < geometry.indices.size(); i+= 3) { + particle::PhysicsGenerator generator; + glm::vec3 & p1 = vertices[indices[i]].position, p2 = vertices[indices[i+1]].position, p3 = vertices[indices[i+2]].position; + + glm::vec3 baricenter = (p1 + p2 + p3) / 3.f; + generator.setPosition(baricenter); + + glm::vec3 normal = glm::triangleNormal(p1, p2, p3); + generator.setVelocity(glm::normalize(normal) / 50.f); + + generator.setPositionVariation(0.5f); + this->_generators.push_back(generator); + } + } + + void MeshGeneratorModel::changeMeshParticle(const std::string & path) { + Model model(path); + MeshGeometry geometry = model.getMeshGeometry(); + this->_meshParticle.generate(geometry.vertices, geometry.indices); + } + + void MeshGeneratorModel::spawn(int count, double current_time) { + for(auto & generator : this->_generators) { + if((count + this->_particles.size()) <= this->getMaxParticles()) { + std::vector<std::unique_ptr<particle::Physics>> newParticles = 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())); + } + } + } + + void MeshGeneratorModel::changeTexture(const std::string & path) { + this->_meshParticleTexture.load(path); + } +} \ No newline at end of file diff --git a/ParticleGenerator/src/Scene/Scenes/MeshGeneratorModel.hpp b/ParticleGenerator/src/Scene/Scenes/MeshGeneratorModel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..811943c3b15cb455ee9e21549c835dbb125c5e0f --- /dev/null +++ b/ParticleGenerator/src/Scene/Scenes/MeshGeneratorModel.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "../Scene.hpp" + +#include <vector> +#include <memory> + +#include "../../Mesh/Mesh.hpp" +#include "../../Mesh/Billboard.hpp" +#include "../../Renderer/Renderer.hpp" +#include "../../Particle/generator/PhysicsGenerator.hpp" + +namespace pg::scene { + class MeshGeneratorModel : public SceneParticle { + private: + Mesh _mesh; + Program _meshProgram; + glm::vec3 _meshPosition; + glm::vec3 _meshRotation; + + std::vector<particle::PhysicsGenerator> _generators; + Mesh _meshParticle; + Material _meshParticleTexture; + Program _meshParticleProgram; + GLuint _ubo; + glm::vec4 _color; + + public: + MeshGeneratorModel(); + virtual ~MeshGeneratorModel() = default; + + virtual void initialize(); + virtual void update(double); + virtual void render(const Camera &, double); + virtual void destroy(); + + virtual std::string name() const {return "Mesh Generator Model Scene";}; + + void changeMesh(const std::string &); + void changeMeshParticle(const std::string &); + void changeTexture(const std::string &); + + void spawn(int count, double current_time); + }; +} \ No newline at end of file diff --git a/ParticleGenerator/src/main.cpp b/ParticleGenerator/src/main.cpp index 87505251309600816c7e06ffa943522cf4460279..ecdda9055ff7de0682746b77d2ebae38f339ee25 100644 --- a/ParticleGenerator/src/main.cpp +++ b/ParticleGenerator/src/main.cpp @@ -13,6 +13,7 @@ #include "Scene/Scenes/Grid.hpp" #include "Scene/Scenes/PhysicSprite.hpp" #include "Scene/Scenes/MultyPath.hpp" +#include "Scene/Scenes/MeshGeneratorModel.hpp" #include "Interface/Manager.hpp" @@ -82,6 +83,7 @@ int main(int argc, const char * argv[]) { pg::scene::MeshGenerator meshGenerator; pg::scene::Path path(&bezier, ctrlPoints); pg::scene::MultyPath multyPath(ctrlPoints); + pg::scene::MeshGeneratorModel meshGeneratorModel; pg::Manager manager(window); pg::interface::Manager imanager(window, manager); @@ -91,6 +93,7 @@ int main(int argc, const char * argv[]) { manager.add(&physicSprite); manager.add(&meshGenerator); manager.add(&multyPath); + manager.add(&meshGeneratorModel); while(window.isOpen()) { double current_time = glfwGetTime();