File: ParticleEmitter.h

package info (click to toggle)
0ad 0.0.23.1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 78,292 kB
  • sloc: cpp: 245,166; ansic: 200,249; python: 13,754; sh: 6,104; perl: 4,620; makefile: 977; xml: 810; java: 533; ruby: 229; erlang: 46; pascal: 30; sql: 21; tcl: 4
file content (210 lines) | stat: -rw-r--r-- 5,620 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* Copyright (C) 2011 Wildfire Games.
 * This file is part of 0 A.D.
 *
 * 0 A.D. is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * 0 A.D. is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef INCLUDED_PARTICLEEMITTER
#define INCLUDED_PARTICLEEMITTER

#include "graphics/ModelAbstract.h"
#include "graphics/ParticleEmitterType.h"
#include "graphics/Texture.h"
#include "maths/Quaternion.h"
#include "renderer/VertexArray.h"

#include <map>

/**
 * Simulation state for a single particle.
 */
struct SParticle
{
	CVector3D pos;
	CVector3D velocity;
	float angle;
	float angleSpeed;
	float size;
	float sizeGrowthRate;
	SColor4ub color;
	float age;
	float maxAge;
};

typedef shared_ptr<CParticleEmitter> CParticleEmitterPtr;

/**
 * Particle emitter.
 *
 * Emitters store particle data in two forms:
 *  * m_Particles contains the raw data used for the CPU particle simulation.
 *  * m_VertexArray contains the data required for rendering.
 * Particles are rendered as billboard quads, so the vertex array contains four vertices
 * per particle with different UV coordinates. The billboard position computation is
 * performed by a vertex shader.
 *
 * The number of particles is a constant for the entire life of the emitter,
 * to simplify the updating and rendering.
 * m_Particles acts like a ring buffer, so we don't have to worry about dynamically
 * allocating particles. If particles have variable lifetimes, they'll exist in the
 * array with alpha=0 until they're overwritten by a new particle after the maximum
 * lifetime.
 *
 * (It's quite likely this could be made more efficient, if the overhead of any added
 * complexity is not high.)
 */
class CParticleEmitter
{
public:
	CParticleEmitter(const CParticleEmitterTypePtr& type);

	/**
	 * Set the position to be used for emission of new particles.
	 */
	void SetPosition(const CVector3D& pos)
	{
		m_Pos = pos;
	}

	CVector3D GetPosition() const
	{
		return m_Pos;
	}

	/**
	 * Set the rotation to be used for emission of new particles (note: depends on particles).
	 */
	void SetRotation(const CQuaternion& rot)
	{
		m_Rot = rot;
	}

	CQuaternion GetRotation() const
	{
		return m_Rot;
	}

	/**
	 * Get the bounding box of the center points of particles at their current positions.
	 */
	CBoundingBoxAligned GetParticleBounds() { return m_ParticleBounds; }

	/**
	 * Push a new particle onto the ring buffer. (May overwrite an old particle.)
	 */
	void AddParticle(const SParticle& particle);

	/**
	 * Update particle and vertex array data. Must be called before RenderArray.
	 *
	 * If frameNumber is the same as the previous call to UpdateArrayData,
	 * then the function will do no work and return immediately.
	 */
	void UpdateArrayData(int frameNumber);

	/**
	 * Make the vertex data available for subsequent binding and rendering.
	 */
	void PrepareForRendering();

	/**
	 * Bind rendering state (textures and blend modes).
	 */
	void Bind(const CShaderProgramPtr& shader);

	/**
	 * Draw the vertex array.
	 */
	void RenderArray(const CShaderProgramPtr& shader);

	/**
	 * Stop this emitter emitting new particles, and pass responsibility for rendering
	 * to the CParticleManager. This should be called before dropping the last shared_ptr
	 * to this object so that it will carry on rendering (until all particles have dissipated)
	 * even when it's no longer attached to a model.
	 * @param self the shared_ptr you're about to drop
	 */
	void Unattach(const CParticleEmitterPtr& self);

	void SetEntityVariable(const std::string& name, float value);

	CParticleEmitterTypePtr m_Type;

	/// Whether this emitter is still emitting new particles
	bool m_Active;

	CVector3D m_Pos;
	CQuaternion m_Rot;

	std::map<std::string, float> m_EntityVariables;

	std::vector<SParticle> m_Particles;
	size_t m_NextParticleIdx;

	float m_LastUpdateTime;
	float m_EmissionRoundingError;

private:
	/// Bounding box of the current particle center points
	CBoundingBoxAligned m_ParticleBounds;

	VertexIndexArray m_IndexArray;

	VertexArray m_VertexArray;
	VertexArray::Attribute m_AttributePos;
	VertexArray::Attribute m_AttributeAxis;
	VertexArray::Attribute m_AttributeUV;
	VertexArray::Attribute m_AttributeColor;

	int m_LastFrameNumber;
};

/**
 * Particle emitter model, for attaching emitters as props on other models.
 */
class CModelParticleEmitter : public CModelAbstract
{
public:
	CModelParticleEmitter(const CParticleEmitterTypePtr& type);
	~CModelParticleEmitter();

	/// Dynamic cast
	virtual CModelParticleEmitter* ToCModelParticleEmitter()
	{
		return this;
	}

	virtual CModelAbstract* Clone() const;

	virtual void SetDirtyRec(int dirtyflags)
	{
		SetDirty(dirtyflags);
	}

	virtual void SetTerrainDirty(ssize_t UNUSED(i0), ssize_t UNUSED(j0), ssize_t UNUSED(i1), ssize_t UNUSED(j1))
	{
	}

	virtual void SetEntityVariable(const std::string& name, float value);

	virtual void CalcBounds();
	virtual void ValidatePosition();
	virtual void InvalidatePosition();
	virtual void SetTransform(const CMatrix3D& transform);

	CParticleEmitterTypePtr m_Type;
	CParticleEmitterPtr m_Emitter;
};

#endif // INCLUDED_PARTICLEEMITTER