From f322c5fc3cb8c6fb74b536fa56dfec6771b56cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9au?= <theau.baton@etu.univ-amu.fr> Date: Mon, 20 May 2024 16:54:24 +0200 Subject: [PATCH] Start interface for MesgGenerator Scene --- .../Scene/MeshGeneratorInterface.cpp | 53 ++++++++ .../Scene/MeshGeneratorInterface.hpp | 37 ++++++ .../src/Scene/Scenes/MeshGenerator.cpp | 121 +++++++++++------- .../src/Scene/Scenes/MeshGenerator.hpp | 12 +- 4 files changed, 176 insertions(+), 47 deletions(-) create mode 100644 ParticleGenerator/src/Interface/Scene/MeshGeneratorInterface.cpp create mode 100644 ParticleGenerator/src/Interface/Scene/MeshGeneratorInterface.hpp diff --git a/ParticleGenerator/src/Interface/Scene/MeshGeneratorInterface.cpp b/ParticleGenerator/src/Interface/Scene/MeshGeneratorInterface.cpp new file mode 100644 index 0000000..19c74a6 --- /dev/null +++ b/ParticleGenerator/src/Interface/Scene/MeshGeneratorInterface.cpp @@ -0,0 +1,53 @@ +#include "MeshGeneratorInterface.hpp" + +#include <imgui.h> +#include "../../Scene/Scenes/MeshGenerator.hpp" +#include "../../tfd/tinyfiledialogs.h" + +namespace pg { + MeshGeneratorInterface::MeshGeneratorInterface(scene::MeshGenerator * scene, size_t max) + : _scene(scene), + _max(max), + _spawnFrequence(2500), + _spawnCount(1), + _lifetime(2), + _enableRender(true), + _enableSpawn(true) { + + } + + void MeshGeneratorInterface::render(double current_time) { + ImGui::Text("Particles Number : %i / %i.", this->_scene->_particles.size(), this->_max); + ImGui::SameLine(); + if(ImGui::Button("Spawn")) { + this->_scene->spawn(1, current_time); + } + + ImGui::SameLine(); + if(ImGui::Button("Clear")) { + this->_scene->_particles.clear(); + } + + ImGui::Text("Particles Batchs : %i", static_cast<int>(this->_scene->_particles.size() / 1024) + 1); + ImGui::Separator(); + ImGui::Checkbox("Enable Rendering", &this->_enableRender); + ImGui::Checkbox("Enable Spawning", &this->_enableSpawn); + ImGui::Separator(); + ImGui::InputInt("Lifetime (s)", &this->_lifetime, 1, 2); + ImGui::InputInt("Spawn Frequence (ms)", &this->_spawnFrequence, 100, 500); + ImGui::SliderInt("Spawning Number", &this->_spawnCount, 1, static_cast<int>(this->_max)); + + ImGui::SeparatorText("Model"); + if(ImGui::Button("Change Model")) { + char const * imagePatterns[1] = {"*.obj"}; + std::string path = tinyfd_openFileDialog("Model Browser", "", 1, imagePatterns, "Model File", false); + this->_scene->changeMesh(path); + } + + if(ImGui::CollapsingHeader("Global Genrator Parameter")) { + if(ImGui::Button("Apply")) { + + } + } + } +} \ No newline at end of file diff --git a/ParticleGenerator/src/Interface/Scene/MeshGeneratorInterface.hpp b/ParticleGenerator/src/Interface/Scene/MeshGeneratorInterface.hpp new file mode 100644 index 0000000..8c584af --- /dev/null +++ b/ParticleGenerator/src/Interface/Scene/MeshGeneratorInterface.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "../Interface.hpp" + +namespace pg { + namespace scene { + class MeshGenerator; + } + + class MeshGeneratorInterface : public Interface { + private: + scene::MeshGenerator * _scene; + + size_t _max; + int _spawnFrequence; + int _spawnCount; + int _lifetime; + + bool _enableRender; + bool _enableSpawn; + + public: + MeshGeneratorInterface(scene::MeshGenerator *, size_t max = 1024); + + inline size_t getMaxParticle() const {return this->_max;} + + inline int getSpawnFrequence() const {return this->_spawnFrequence;} + inline int getSpawnCount() const {return this->_spawnCount;} + inline int getLifeTime() const {return this->_lifetime;} + + inline bool isRenderEnable() {return this->_enableRender;} + inline bool isSpawnEnable() {return this->_enableSpawn;} + + virtual void render(double); + inline std::string title() const {return "Mesh Generator Scene Interface";} + }; +} \ No newline at end of file diff --git a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp index 48065d5..0f49055 100644 --- a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp +++ b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp @@ -17,30 +17,12 @@ namespace pg::scene { _billboard(), _billboardTexture(), _billboardProgram(), - _ubo(0) {} + _ubo(0), + _interface(this, 8192) {} void MeshGenerator::initialize() { if(!this->_mesh.isGenerated()) { - Model model("res/models/sphere.obj"); - - 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) { - PhysicsParticleGenerator 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); - - this->_generators.push_back(generator); - } + this->changeMesh("res/models/sphere.obj"); } if(!this->_meshProgram.usable()) { @@ -81,20 +63,19 @@ namespace pg::scene { glBindBufferBase(GL_UNIFORM_BUFFER, uniforme_index, this->_ubo); glBindBuffer(GL_UNIFORM_BUFFER, 0); } + + this->_particles.reserve(this->_interface.getMaxParticle()); } void MeshGenerator::update(double current_time) { static auto start = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now(); - pg::Particle::purge(this->_particles, static_cast<size_t>(current_time), 2); - if(duration_cast<std::chrono::milliseconds>(end - start).count() >= 2500) { + pg::Particle::purge(this->_particles, static_cast<size_t>(current_time), this->_interface.getLifeTime()); + if(duration_cast<std::chrono::milliseconds>(end - start).count() >= this->_interface.getSpawnFrequence()) { start = std::chrono::high_resolution_clock::now(); - for(auto & generator : this->_generators) { - if((1 + this->_particles.size()) <= 1024) { - std::vector<std::unique_ptr<pg::Particle>> newParticles = generator.generate(1, static_cast<size_t>(current_time)); - this->_particles.insert(this->_particles.begin(), std::make_move_iterator(newParticles.begin()), std::make_move_iterator(newParticles.end())); - } + if(this->_interface.isSpawnEnable()) { + this->spawn(this->_interface.getSpawnCount(), current_time); } } @@ -127,31 +108,40 @@ namespace pg::scene { // -------- - std::vector<glm::mat4> models; - for(auto & particle : this->_particles) { - glm::mat4 model = glm::mat4(1.0); - model = glm::translate(model, glm::vec3(particle->getPosition())); - models.push_back(model); - } + 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()); + glBindBuffer(GL_UNIFORM_BUFFER, this->_ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, models.size() * sizeof(glm::mat4), models.data()); - pg::error::OpenGLError::check(); + pg::error::OpenGLError::check(); - this->_billboardTexture.bind(0); - this->_billboardProgram.use(); + this->_billboardTexture.bind(0); + this->_billboardProgram.use(); - this->_billboardProgram.setUniform("uView", VIEW_MATRIX); - this->_billboardProgram.setUniform("uProj", PROJECTION_MATRIX); - this->_billboardProgram.setUniform("uSlot", 0); - this->_billboardProgram.setUniform("uColor", glm::vec4(1.f, 1.f, 1.f, 1.f)); + this->_billboardProgram.setUniform("uView", VIEW_MATRIX); + this->_billboardProgram.setUniform("uProj", PROJECTION_MATRIX); + this->_billboardProgram.setUniform("uSlot", 0); + this->_billboardProgram.setUniform("uColor", glm::vec4(1.f, 1.f, 1.f, 1.f)); - pg::error::OpenGLError::check(); + pg::error::OpenGLError::check(); - this->_billboard.draw(this->_particles.size()); + if(this->_interface.isRenderEnable()) { + this->_billboard.draw(this->_particles.size()); + } - pg::error::OpenGLError::check(); + pg::error::OpenGLError::check(); + + particle_accumulator += 1024; + } // -------- } @@ -161,4 +151,43 @@ namespace pg::scene { this->_billboard.destroy(); this->_particles.clear(); } + + void MeshGenerator::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) { + PhysicsParticleGenerator 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 MeshGenerator::spawn(size_t count, double current_time) { + for(auto & generator : this->_generators) { + if((count + this->_particles.size()) <= this->_interface.getMaxParticle()) { + std::vector<std::unique_ptr<pg::Particle>> 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 MeshGenerator::changeTexture(const std::string & path) { + this->_billboardTexture.load(path); + } } \ No newline at end of file diff --git a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp index dae803e..77e980c 100644 --- a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp +++ b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp @@ -9,6 +9,7 @@ #include "../../Mesh/Billboard.hpp" #include "../../Renderer/Renderer.hpp" #include "../../Particle/generator/PhysicsParticleGenerator.hpp" +#include "../../Interface/Scene/MeshGeneratorInterface.hpp" namespace pg::scene { class MeshGenerator : public Scene { @@ -25,6 +26,8 @@ namespace pg::scene { Program _billboardProgram; GLuint _ubo; + MeshGeneratorInterface _interface; + public: MeshGenerator(); @@ -34,7 +37,14 @@ namespace pg::scene { virtual void destroy(); virtual std::string name() const {return "Mesh Generator Scene";}; - virtual Interface * interface() {return nullptr;}; + virtual Interface * interface() {return &this->_interface;} + + void changeMesh(const std::string &); + void changeTexture(const std::string &); + + void spawn(size_t count, double current_time); + + friend class pg::MeshGeneratorInterface; }; } \ No newline at end of file -- GitLab