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 SERVER_ONLY
19 
20 #ifndef HEADER_STK_PARTICLE_HPP
21 #define HEADER_STK_PARTICLE_HPP
22 
23 #include "graphics/gl_headers.hpp"
24 #include "../lib/irrlicht/source/Irrlicht/CParticleSystemSceneNode.h"
25 #include <cassert>
26 #include <vector>
27 
28 using namespace irr;
29 
30 struct CPUParticle;
31 
32 class STKParticle : public scene::CParticleSystemSceneNode
33 {
34 private:
35     // ------------------------------------------------------------------------
36     struct HeightMapData
37     {
38         const std::vector<std::vector<float> > m_array;
39         const float m_x;
40         const float m_z;
41         const float m_x_len;
42         const float m_z_len;
43         // --------------------------------------------------------------------
HeightMapDataSTKParticle::HeightMapData44         HeightMapData(std::vector<std::vector<float> >& array,
45                       float track_x, float track_z, float track_x_len,
46                       float track_z_len)
47             : m_array(std::move(array)), m_x(track_x), m_z(track_z),
48               m_x_len(track_x_len), m_z_len(track_z_len) {}
49     };
50     // ------------------------------------------------------------------------
51     struct ParticleData
52     {
53         core::vector3df m_position;
54         float m_lifetime;
55         core::vector3df m_direction;
56         float m_size;
57     };
58     // ------------------------------------------------------------------------
59     HeightMapData* m_hm;
60 
61     std::vector<ParticleData> m_particles_generating, m_initial_particles;
62 
63     core::vector3df m_color_from, m_color_to;
64 
65     float m_size_increase_factor;
66 
67     bool m_first_execution, m_randomize_initial_y, m_flips, m_pre_generating;
68 
69     /** Previous frame particles emitter source matrix */
70     core::matrix4 m_previous_frame_matrix;
71 
72     /** Maximum count of particles. */
73     unsigned m_max_count;
74 
75     static std::vector<float> m_flips_data;
76 
77     static GLuint m_flips_buffer;
78 
79     // ------------------------------------------------------------------------
80     void generateParticlesFromPointEmitter(scene::IParticlePointEmitter*);
81     // ------------------------------------------------------------------------
82     void generateParticlesFromBoxEmitter(scene::IParticleBoxEmitter*);
83     // ------------------------------------------------------------------------
84     void generateParticlesFromSphereEmitter(scene::IParticleSphereEmitter*);
85     // ------------------------------------------------------------------------
86     void stimulateHeightMap(float, unsigned int, std::vector<CPUParticle>*);
87     // ------------------------------------------------------------------------
88     void stimulateNormal(float, unsigned int, std::vector<CPUParticle>*);
89 
90 public:
91     // ------------------------------------------------------------------------
92     STKParticle(bool randomize_initial_y = false,
93         ISceneNode* parent = 0, s32 id = -1,
94         const core::vector3df& position = core::vector3df(0, 0, 0),
95         const core::vector3df& rotation = core::vector3df(0, 0, 0),
96         const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
97     // ------------------------------------------------------------------------
~STKParticle()98     ~STKParticle()
99     {
100         delete m_hm;
101     }
102     // ------------------------------------------------------------------------
setColorFrom(float r,float g,float b)103     void setColorFrom(float r, float g, float b)
104     {
105         m_color_from.X = r;
106         m_color_from.Y = g;
107         m_color_from.Z = b;
108     }
109     // ------------------------------------------------------------------------
setColorTo(float r,float g,float b)110     void setColorTo(float r, float g, float b)
111     {
112         m_color_to.X = r;
113         m_color_to.Y = g;
114         m_color_to.Z = b;
115     }
116     // ------------------------------------------------------------------------
117     virtual void setEmitter(scene::IParticleEmitter* emitter);
118     // ------------------------------------------------------------------------
119     virtual void OnRegisterSceneNode();
120     // ------------------------------------------------------------------------
setIncreaseFactor(float val)121     void setIncreaseFactor(float val)         { m_size_increase_factor = val; }
122     // ------------------------------------------------------------------------
setHeightmap(std::vector<std::vector<float>> & array,float track_x,float track_z,float track_x_len,float track_z_len)123     void setHeightmap(std::vector<std::vector<float> >& array, float track_x,
124                       float track_z, float track_x_len, float track_z_len)
125     {
126         m_hm = new HeightMapData(array, track_x, track_z, track_x_len,
127             track_z_len);
128     }
129     // ------------------------------------------------------------------------
130     void generate(std::vector<CPUParticle>* out);
131     // ------------------------------------------------------------------------
setFlips()132     void setFlips()                                         { m_flips = true; }
133     // ------------------------------------------------------------------------
getFlips() const134     bool getFlips() const                                   { return m_flips; }
135     // ------------------------------------------------------------------------
getMaxCount() const136     unsigned getMaxCount() const                        { return m_max_count; }
137     // ------------------------------------------------------------------------
setPreGenerating(bool val)138     void setPreGenerating(bool val)                 { m_pre_generating = val; }
139     // ------------------------------------------------------------------------
140     static void updateFlips(unsigned maximum_particle_count);
141     // ------------------------------------------------------------------------
destroyFlipsBuffer()142     static void destroyFlipsBuffer()
143     {
144         if (m_flips_buffer != 0)
145         {
146             glDeleteBuffers(1, &m_flips_buffer);
147             m_flips_buffer = 0;
148         }
149         m_flips_data.clear();
150     }
151     // ------------------------------------------------------------------------
getFlipsBuffer()152     static GLuint getFlipsBuffer()
153     {
154         assert(m_flips_buffer != 0);
155         return m_flips_buffer;
156     }
157 };
158 
159 #endif
160 
161 #endif  // !SERVER_ONLY
162