Pyrogenesis  trunk
ParticleEmitter.h
Go to the documentation of this file.
1 /* Copyright (C) 2023 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef INCLUDED_PARTICLEEMITTER
19 #define INCLUDED_PARTICLEEMITTER
20 
21 #include "graphics/ModelAbstract.h"
23 #include "maths/Quaternion.h"
26 #include "renderer/VertexArray.h"
27 
28 #include <map>
29 
30 /**
31  * Simulation state for a single particle.
32  */
33 struct SParticle
34 {
37  float angle;
38  float angleSpeed;
39  float size;
42  float age;
43  float maxAge;
44 };
45 
46 typedef std::shared_ptr<CParticleEmitter> CParticleEmitterPtr;
47 
48 /**
49  * Particle emitter.
50  *
51  * Emitters store particle data in two forms:
52  * * m_Particles contains the raw data used for the CPU particle simulation.
53  * * m_VertexArray contains the data required for rendering.
54  * Particles are rendered as billboard quads, so the vertex array contains four vertices
55  * per particle with different UV coordinates. The billboard position computation is
56  * performed by a vertex shader.
57  *
58  * The number of particles is a constant for the entire life of the emitter,
59  * to simplify the updating and rendering.
60  * m_Particles acts like a ring buffer, so we don't have to worry about dynamically
61  * allocating particles. If particles have variable lifetimes, they'll exist in the
62  * array with alpha=0 until they're overwritten by a new particle after the maximum
63  * lifetime.
64  *
65  * (It's quite likely this could be made more efficient, if the overhead of any added
66  * complexity is not high.)
67  */
69 {
70 public:
72 
73  /**
74  * Set the position to be used for emission of new particles.
75  */
76  void SetPosition(const CVector3D& pos)
77  {
78  m_Pos = pos;
79  }
80 
82  {
83  return m_Pos;
84  }
85 
86  /**
87  * Set the rotation to be used for emission of new particles (note: depends on particles).
88  */
89  void SetRotation(const CQuaternion& rot)
90  {
91  m_Rot = rot;
92  }
93 
94  const CQuaternion& GetRotation() const
95  {
96  return m_Rot;
97  }
98 
99  /**
100  * Get the bounding box of the center points of particles at their current positions.
101  */
102  const CBoundingBoxAligned& GetParticleBounds() const { return m_ParticleBounds; }
103 
104  /**
105  * Push a new particle onto the ring buffer. (May overwrite an old particle.)
106  */
107  void AddParticle(const SParticle& particle);
108 
109  /**
110  * Update particle and vertex array data. Must be called before RenderArray.
111  *
112  * If frameNumber is the same as the previous call to UpdateArrayData,
113  * then the function will do no work and return immediately.
114  */
115  void UpdateArrayData(int frameNumber);
116 
117  /**
118  * Make the vertex data available for subsequent binding and rendering.
119  */
120  void PrepareForRendering();
121 
122  /**
123  * Upload the vertex data to the backend.
124  */
125  void UploadData(
126  Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
127 
128  /**
129  * Bind rendering state (textures and blend modes).
130  */
131  void Bind(
132  Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
134 
135  /**
136  * Draw the vertex array.
137  */
138  void RenderArray(
139  Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
140 
141  /**
142  * Stop this emitter emitting new particles, and pass responsibility for rendering
143  * to the CParticleManager. This should be called before dropping the last std::shared_ptr
144  * to this object so that it will carry on rendering (until all particles have dissipated)
145  * even when it's no longer attached to a model.
146  * @param self the std::shared_ptr you're about to drop
147  */
148  void Unattach(const CParticleEmitterPtr& self);
149 
150  void SetEntityVariable(const std::string& name, float value);
151 
153 
154  /// Whether this emitter is still emitting new particles
155  bool m_Active;
156 
159 
160  std::map<std::string, float> m_EntityVariables;
161 
162  std::vector<SParticle> m_Particles;
164 
167 
168 private:
169  /// Bounding box of the current particle center points
171 
173 
179 
180  Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
181 
183 };
184 
185 /**
186  * Particle emitter model, for attaching emitters as props on other models.
187  */
189 {
190 public:
193 
194  /// Dynamic cast
196  {
197  return this;
198  }
199 
200  virtual CModelAbstract* Clone() const;
201 
203  {
204  }
205 
206  virtual void SetEntityVariable(const std::string& name, float value);
207 
208  virtual void CalcBounds();
209  virtual void ValidatePosition();
210  virtual void InvalidatePosition();
211  virtual void SetTransform(const CMatrix3D& transform);
212 
215 };
216 
217 #endif // INCLUDED_PARTICLEEMITTER
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
Definition: code_annotation.h:38
float maxAge
Definition: ParticleEmitter.h:43
CParticleEmitterPtr m_Emitter
Definition: ParticleEmitter.h:214
bool m_Active
Whether this emitter is still emitting new particles.
Definition: ParticleEmitter.h:155
Particle emitter.
Definition: ParticleEmitter.h:68
const CQuaternion & GetRotation() const
Definition: ParticleEmitter.h:94
const CBoundingBoxAligned & GetParticleBounds() const
Get the bounding box of the center points of particles at their current positions.
Definition: ParticleEmitter.h:102
float size
Definition: ParticleEmitter.h:39
IVertexInputLayout stores precompiled list of vertex attributes.
Definition: IShaderProgram.h:73
void SetPosition(const CVector3D &pos)
Set the position to be used for emission of new particles.
Definition: ParticleEmitter.h:76
Definition: Vector3D.h:30
std::shared_ptr< CParticleEmitterType > CParticleEmitterTypePtr
Definition: ParticleEmitterType.h:123
std::vector< SParticle > m_Particles
Definition: ParticleEmitter.h:162
float sizeGrowthRate
Definition: ParticleEmitter.h:40
CVector3D pos
Definition: ParticleEmitter.h:35
A VertexArray that is specialised to handle 16-bit array indices.
Definition: VertexArray.h:219
Definition: Matrix3D.h:33
std::shared_ptr< CParticleEmitter > CParticleEmitterPtr
Definition: ParticleEmitter.h:46
float m_EmissionRoundingError
Definition: ParticleEmitter.h:166
Definition: VertexArray.h:140
VertexArray m_VertexArray
Definition: ParticleEmitter.h:174
virtual CModelParticleEmitter * ToCModelParticleEmitter()
Dynamic cast.
Definition: ParticleEmitter.h:195
CVector3D velocity
Definition: ParticleEmitter.h:36
VertexArray::Attribute m_AttributeAxis
Definition: ParticleEmitter.h:176
Definition: SColor.h:30
VertexArray::Attribute m_AttributeUV
Definition: ParticleEmitter.h:177
VertexArray::Attribute m_AttributeColor
Definition: ParticleEmitter.h:178
Definition: VertexArray.h:137
IShaderProgram is a container for multiple shaders of different types.
Definition: IShaderProgram.h:80
float angle
Definition: ParticleEmitter.h:37
intptr_t ssize_t
Definition: wposix_types.h:82
VertexIndexArray m_IndexArray
Definition: ParticleEmitter.h:172
CVector3D GetPosition() const
Definition: ParticleEmitter.h:81
void SetRotation(const CQuaternion &rot)
Set the rotation to be used for emission of new particles (note: depends on particles).
Definition: ParticleEmitter.h:89
Definition: Quaternion.h:25
Abstract base class for graphical objects that are used by units, or as props attached to other CMode...
Definition: ModelAbstract.h:37
Definition: BoundingBoxAligned.h:33
virtual void SetTerrainDirty(ssize_t i0, ssize_t j0, ssize_t i1, ssize_t j1)
Called when terrain has changed in the given inclusive bounds.
Definition: ParticleEmitter.h:202
float m_LastUpdateTime
Definition: ParticleEmitter.h:165
CVector3D m_Pos
Definition: ParticleEmitter.h:157
CBoundingBoxAligned m_ParticleBounds
Bounding box of the current particle center points.
Definition: ParticleEmitter.h:170
Particle emitter model, for attaching emitters as props on other models.
Definition: ParticleEmitter.h:188
SColor4ub color
Definition: ParticleEmitter.h:41
int m_LastFrameNumber
Definition: ParticleEmitter.h:182
std::map< std::string, float > m_EntityVariables
Definition: ParticleEmitter.h:160
float age
Definition: ParticleEmitter.h:42
CQuaternion m_Rot
Definition: ParticleEmitter.h:158
Definition: IDeviceCommandContext.h:40
VertexArray::Attribute m_AttributePos
Definition: ParticleEmitter.h:175
size_t m_NextParticleIdx
Definition: ParticleEmitter.h:163
Simulation state for a single particle.
Definition: ParticleEmitter.h:33
float angleSpeed
Definition: ParticleEmitter.h:38
CParticleEmitterTypePtr m_Type
Definition: ParticleEmitter.h:213
CParticleEmitterTypePtr m_Type
Definition: ParticleEmitter.h:152