From 0d311e6876cefa05a19c223b6e2ae80d7581e091 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 15:48:44 +0200
Subject: [PATCH] Add mesh generator scene

---
 .../src/Scene/Scenes/MeshGenerator.cpp        | 164 ++++++++++++++++++
 .../src/Scene/Scenes/MeshGenerator.hpp        |  40 +++++
 ParticleGenerator/src/main.cpp                |   4 +
 3 files changed, 208 insertions(+)
 create mode 100644 ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp
 create mode 100644 ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp

diff --git a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp
new file mode 100644
index 0000000..48065d5
--- /dev/null
+++ b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.cpp
@@ -0,0 +1,164 @@
+#include "MeshGenerator.hpp"
+
+#include "../../Mesh/Model.hpp"
+
+#define GLM_ENABLE_EXPERIMENTAL
+#include <glm/gtx/normal.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+namespace pg::scene {
+    MeshGenerator::MeshGenerator()
+    : _mesh(),
+      _meshProgram(),
+      _meshPosition(0.f),
+      _meshRotation(0.f),
+      _generators(),
+      _particles(),
+      _billboard(),
+      _billboardTexture(),
+      _billboardProgram(),
+      _ubo(0) {}
+
+    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);
+            }
+        }
+
+        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->_billboard.initialize();
+        this->_billboardTexture.load("res/textures/smoke1.png");
+
+        if(!this->_billboardProgram.usable()) {
+            Source vert("res/shaders/scene/Billboard.vert", Source::Categorie::VERTEX);
+            Source frag("res/shaders/scene/Billboard.frag", Source::Categorie::FRAGMENT);
+
+            this->_billboardProgram << vert;
+            this->_billboardProgram << frag;
+
+            this->_billboardProgram.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->_billboardProgram.id(), "uModels_t");
+			glBindBufferBase(GL_UNIFORM_BUFFER, uniforme_index, this->_ubo);
+			glBindBuffer(GL_UNIFORM_BUFFER, 0);
+		}
+    }
+
+    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) {
+            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(duration_cast<std::chrono::milliseconds>(end - start).count() >= 10) {
+            for(auto& particle : this->_particles) {
+                particle->update(0.0);
+            }
+        }
+    }
+
+    void MeshGenerator::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();
+
+        // --------
+
+        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);
+        }
+
+        glBindBuffer(GL_UNIFORM_BUFFER, this->_ubo);
+        glBufferSubData(GL_UNIFORM_BUFFER, 0, models.size() * sizeof(glm::mat4), models.data());
+
+        pg::error::OpenGLError::check();
+
+        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));
+
+        pg::error::OpenGLError::check();
+
+        this->_billboard.draw(this->_particles.size());
+
+        pg::error::OpenGLError::check();
+
+        // --------
+    }
+
+    void MeshGenerator::destroy() {
+        glDeleteBuffers(1, &this->_ubo);
+        this->_billboard.destroy();
+        this->_particles.clear();
+    }
+}
\ No newline at end of file
diff --git a/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp
new file mode 100644
index 0000000..dae803e
--- /dev/null
+++ b/ParticleGenerator/src/Scene/Scenes/MeshGenerator.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "Scene.hpp"
+
+#include <vector>
+#include <memory>
+
+#include "../../Mesh/Mesh.hpp"
+#include "../../Mesh/Billboard.hpp"
+#include "../../Renderer/Renderer.hpp"
+#include "../../Particle/generator/PhysicsParticleGenerator.hpp"
+
+namespace pg::scene {
+    class MeshGenerator : public Scene {
+        private:
+            Mesh _mesh;
+            Program _meshProgram;
+            glm::vec3 _meshPosition;
+            glm::vec3 _meshRotation;
+
+            std::vector<PhysicsParticleGenerator> _generators;
+            std::vector<std::unique_ptr<Particle>> _particles;
+            Billboard _billboard;
+            Material _billboardTexture;
+            Program _billboardProgram;
+            GLuint _ubo;
+
+        public:
+            MeshGenerator();
+
+            virtual void initialize();
+            virtual void update(double);
+            virtual void render(const Camera &, double);
+            virtual void destroy();
+
+            virtual std::string name() const {return "Mesh Generator Scene";};
+            virtual Interface * interface() {return nullptr;};
+
+    };
+}
\ No newline at end of file
diff --git a/ParticleGenerator/src/main.cpp b/ParticleGenerator/src/main.cpp
index 9b1757e..b7616f4 100644
--- a/ParticleGenerator/src/main.cpp
+++ b/ParticleGenerator/src/main.cpp
@@ -8,6 +8,7 @@
 #include "Scene/Scenes/Physic.hpp"
 #include "Scene/Scenes/Path.hpp"
 #include "Scene/Scenes/Mesh.hpp"
+#include "Scene/Scenes/MeshGenerator.hpp"
 
 #include "Interface/GlobalInterface.hpp"
 
@@ -79,13 +80,16 @@ int main(int argc, const char * argv[]) {
         };
 
         pg::scene::Physic physicScene;
+        pg::scene::MeshGenerator meshGeneratorScene;
         pg::scene::Path pathScene(&bezier, ctrlPoints);
         pg::scene::Mesh meshScene(&bezier, ctrlPoints);
+        
 
         pg::Manager manager(window, &physicScene);
         manager.add(physicScene);
         manager.add(pathScene);
         manager.add(meshScene);
+        manager.add(meshGeneratorScene);
 
 
         pg::GlobalInterface interface(window, manager, "Particle Generator Settings");
-- 
GitLab