1 // SuperTuxKart - a fun racing game with go-kart 2 // Copyright (C) 2017 SuperTuxKart-Team 3 // 4 // This program is free software; you can redistribute it and/or 5 // modify it under the terms of the GNU General Public License 6 // as published by the Free Software Foundation; either version 3 7 // of the License, or (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 18 #ifndef HEADER_CPU_PARTICLE_MANAGER_HPP 19 #define HEADER_CPU_PARTICLE_MANAGER_HPP 20 21 #ifndef SERVER_ONLY 22 23 #include "graphics/gl_headers.hpp" 24 #include "utils/constants.hpp" 25 #include "utils/mini_glm.hpp" 26 #include "utils/no_copy.hpp" 27 #include "utils/singleton.hpp" 28 29 #include <dimension2d.h> 30 #include <IBillboardSceneNode.h> 31 #include <vector3d.h> 32 #include <SColor.h> 33 34 #include <cassert> 35 #include <string> 36 #include <memory> 37 #include <unordered_map> 38 #include <unordered_set> 39 #include <vector> 40 41 using namespace irr; 42 43 struct CPUParticle 44 { 45 core::vector3df m_position; 46 video::SColor m_color_lifetime; 47 short m_size[2]; 48 // ------------------------------------------------------------------------ CPUParticleCPUParticle49 CPUParticle(const core::vector3df& position, 50 const core::vector3df& color_from, 51 const core::vector3df& color_to, float lf_time, float size) 52 : m_position(position) 53 { 54 core::vector3df ret = color_from + (color_to - color_from) * lf_time; 55 m_color_lifetime.setRed(core::clamp((int)(ret.X * 255.0f), 0, 255)); 56 m_color_lifetime.setBlue(core::clamp((int)(ret.Y * 255.0f), 0, 255)); 57 m_color_lifetime.setGreen(core::clamp((int)(ret.Z * 255.0f), 0, 255)); 58 m_color_lifetime.setAlpha(core::clamp((int)(lf_time * 255.0f), 0, 255)); 59 m_size[0] = MiniGLM::toFloat16(size); 60 m_size[1] = m_size[0]; 61 } 62 // ------------------------------------------------------------------------ CPUParticleCPUParticle63 CPUParticle(scene::IBillboardSceneNode* node) 64 { 65 m_position = node->getAbsolutePosition(); 66 video::SColor unused_bottom; 67 node->getColor(m_color_lifetime, unused_bottom); 68 m_size[0] = MiniGLM::toFloat16(node->getSize().Width); 69 m_size[1] = MiniGLM::toFloat16(node->getSize().Height); 70 } 71 }; 72 73 74 class STKParticle; 75 class Material; 76 77 class CPUParticleManager : public Singleton<CPUParticleManager>, NoCopy 78 { 79 private: 80 struct GLParticle : public NoCopy 81 { 82 GLuint m_vao; 83 GLuint m_vbo; 84 unsigned m_size; 85 // -------------------------------------------------------------------- 86 GLParticle(bool flips); 87 // -------------------------------------------------------------------- ~GLParticleCPUParticleManager::GLParticle88 ~GLParticle() 89 { 90 glDeleteVertexArrays(1, &m_vao); 91 glDeleteBuffers(1, &m_vbo); 92 } 93 }; 94 95 std::unordered_map<std::string, std::vector<STKParticle*> > 96 m_particles_queue; 97 98 std::unordered_map<std::string, std::vector<scene::IBillboardSceneNode*> > 99 m_billboards_queue; 100 101 std::unordered_map<std::string, std::vector<CPUParticle> > 102 m_particles_generated; 103 104 std::unordered_map<std::string, std::unique_ptr<GLParticle> > 105 m_gl_particles; 106 107 std::unordered_map<std::string, Material*> m_material_map; 108 109 std::unordered_set<std::string> m_flips_material; 110 111 static GLuint m_particle_quad; 112 113 // ------------------------------------------------------------------------ isFlipsMaterial(const std::string & name)114 bool isFlipsMaterial(const std::string& name) 115 { return m_flips_material.find(name) != m_flips_material.end(); } 116 117 public: 118 // ------------------------------------------------------------------------ 119 CPUParticleManager(); 120 // ------------------------------------------------------------------------ ~CPUParticleManager()121 ~CPUParticleManager() 122 { 123 glDeleteBuffers(1, &m_particle_quad); 124 m_particle_quad = 0; 125 } 126 // ------------------------------------------------------------------------ 127 void addParticleNode(STKParticle* node); 128 // ------------------------------------------------------------------------ 129 void addBillboardNode(scene::IBillboardSceneNode* node); 130 // ------------------------------------------------------------------------ 131 void generateAll(); 132 // ------------------------------------------------------------------------ 133 void uploadAll(); 134 // ------------------------------------------------------------------------ 135 void drawAll(); 136 // ------------------------------------------------------------------------ reset()137 void reset() 138 { 139 for (auto& p : m_particles_queue) 140 { 141 p.second.clear(); 142 } 143 for (auto& p : m_billboards_queue) 144 { 145 p.second.clear(); 146 } 147 for (auto& p : m_particles_generated) 148 { 149 p.second.clear(); 150 } 151 } 152 // ------------------------------------------------------------------------ cleanMaterialMap()153 void cleanMaterialMap() 154 { 155 m_material_map.clear(); 156 m_flips_material.clear(); 157 } 158 159 }; 160 161 #endif 162 163 #endif 164