forked from smooth80/defold
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathparticle_private.h
291 lines (263 loc) · 9.79 KB
/
particle_private.h
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
// Copyright 2020 The Defold Foundation
// Licensed under the Defold License version 1.0 (the "License"); you may not use
// this file except in compliance with the License.
//
// You may obtain a copy of the License, together with FAQs at
// https://www.defold.com/license
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef DM_PARTICLE_PRIVATE_H
#define DM_PARTICLE_PRIVATE_H
#include <dlib/configfile.h>
#include <dlib/index_pool.h>
#include <dlib/transform.h>
#include "particle/particle_ddf.h"
namespace dmParticle
{
/// Number of samples per property (spline => linear segments)
static const uint32_t PROPERTY_SAMPLE_COUNT = 64;
struct EmitterPrototype;
struct Prototype;
/**
* Key when sorting particles, based on life time with additional index for stable sort
*/
union SortKey
{
struct
{
uint32_t m_Index : 16; // Index is used to ensure stable sort
uint32_t m_LifeTime : 16; // Quantified relative life time
};
uint32_t m_Key;
};
/**
* Representation of a particle.
*
* TODO Separate source state from current (chaining modifiers)
*/
struct Particle
{
#define GET_SET(property, type)\
inline type Get##property() const { return m_##property; }\
inline void Set##property(type v) { m_##property = v; }\
GET_SET(Position, Point3)
GET_SET(SourceRotation, Quat)
GET_SET(Rotation, Quat)
GET_SET(Velocity, Vector3)
GET_SET(TimeLeft, float)
GET_SET(MaxLifeTime, float)
GET_SET(ooMaxLifeTime, float)
GET_SET(SpreadFactor, float)
GET_SET(SourceSize, float)
GET_SET(Scale, Vector3)
GET_SET(SourceColor, Vector4)
GET_SET(Color, Vector4)
GET_SET(SortKey, SortKey)
#undef GET_SET
/// Position, which is defined in emitter space or world space depending on how the emitter which spawned the particles is tweaked.
Point3 m_Position;
/// Rotation, which is defined in emitter space or world space depending on how the emitter which spawned the particles is tweaked.
Quat m_SourceRotation;
Quat m_Rotation;
/// Velocity of the particle
Vector3 m_Velocity;
/// Time left before the particle dies.
float m_TimeLeft;
/// The duration of this particle.
float m_MaxLifeTime;
/// Inverted duration.
float m_ooMaxLifeTime;
/// Factor used for spread
float m_SpreadFactor;
/// Particle source size
float m_SourceSize;
/// Particle source stretch factor
float m_SourceStretchFactorX;
float m_SourceStretchFactorY;
// Particle color
Vector4 m_SourceColor;
Vector4 m_Color;
/// Particle scale
Vector3 m_Scale;
// Sorting
SortKey m_SortKey;
/// Particle stretch factor
float m_StretchFactorX;
float m_StretchFactorY;
/// Particle angular velocity
float m_SourceAngularVelocity;
};
/**
* Representation of an emitter.
*/
struct Emitter
{
Emitter()
{
memset(this, 0, sizeof(Emitter));
}
AnimationData m_AnimationData;
/// Particle buffer.
dmArray<Particle> m_Particles;
dmArray<RenderConstant> m_RenderConstants;
Vector3 m_Velocity;
Point3 m_LastPosition;
dmhash_t m_Id;
EmitterRenderData m_RenderData;
/// Vertex index of the render data for the particles spawned by this emitter.
uint32_t m_VertexIndex;
/// Number of vertices of the render data for the particles spawned by this emitter.
uint32_t m_VertexCount;
/// Used to see when the emitter should stop spawning particles.
float m_Timer;
/// The amount of particles to spawn. It is accumulated over frames to handle spawn rates below the timestep.
float m_ParticlesToSpawn;
/// Seed used to ensure a deterministic simulation
uint32_t m_OriginalSeed;
uint32_t m_Seed;
/// Which state the emitter is currently in
EmitterState m_State;
/// Duration with spread applied, calculated on emitter creation.
float m_Duration;
/// Start delay with spread applied, calculated on emitter creation.
float m_StartDelay;
/// Particle spawn rate spread, randomized on emitter creation and used for the duration of the emitter.
float m_SpawnRateSpread;
/// If the user has been warned that all particles cannot be rendered.
uint16_t m_RenderWarning : 1;
/// If the user has been warned that the emitters animation could not be fetched
uint16_t m_FetchAnimWarning : 1;
uint16_t m_LastPositionSet : 1;
/// If this emitter is retiring, if set it means that a looping instance should act like a once instance
uint16_t m_Retiring : 1;
/// If this emitter needs to be rehashed
uint16_t m_ReHash : 1;
};
struct Instance
{
Instance()
: m_Emitters()
, m_NumAwakeEmitters(0)
, m_Prototype(0x0)
, m_EmitterStateChangedData()
, m_PlayTime(0.0f)
, m_VersionNumber(0)
, m_ScaleAlongZ(0)
{
m_WorldTransform.SetIdentity();
}
/// Emitter buffer
dmArray<Emitter> m_Emitters;
/// Number of awake emitters
uint32_t m_NumAwakeEmitters;
/// World transform of the emitter.
dmTransform::TransformS1 m_WorldTransform;
/// DDF resource.
Prototype* m_Prototype;
/// Emitter state changed callback
EmitterStateChangedData m_EmitterStateChangedData;
/// Used when reloading to fast forward new emitters
float m_PlayTime;
/// Version number used to check that the handle is still valid.
uint16_t m_VersionNumber;
/// Whether the scale of the world transform should be used along Z.
uint16_t m_ScaleAlongZ : 1;
};
/**
* Representation of a context to hold a set of emitters.
*/
struct Context
{
Context(uint32_t max_instance_count, uint32_t max_particle_count)
: m_MaxParticleCount(max_particle_count)
, m_NextVersionNumber(1)
, m_InstanceSeeding(0)
{
memset(&m_Stats, 0, sizeof(m_Stats));
m_Instances.SetCapacity(max_instance_count);
m_Instances.SetSize(max_instance_count);
if (max_instance_count > 0)
{
memset(&m_Instances.Front(), 0, max_instance_count * sizeof(Instance*));
}
m_InstanceIndexPool.SetCapacity(max_instance_count);
}
~Context()
{
}
/// Instance buffer.
dmArray<Instance*> m_Instances;
/// Index pool used to index the instance buffer.
dmIndexPool16 m_InstanceIndexPool;
/// Maximum number of particles allowed
uint32_t m_MaxParticleCount;
/// Version number used to create new handles.
uint16_t m_NextVersionNumber;
/// Instance seeding to avoid same frame instances to look the same.
uint16_t m_InstanceSeeding;
/// Stats
Stats m_Stats;
};
struct LinearSegment
{
float m_X;
float m_Y;
float m_K;
};
struct Property
{
LinearSegment m_Segments[PROPERTY_SAMPLE_COUNT];
float m_Spread;
};
struct ModifierPrototype
{
Property m_Properties[dmParticleDDF::MODIFIER_KEY_COUNT];
};
/**
* Representation of an emitter resource.
*
* NOTE The size of the properties-arrays is roughly 10 kB.
*/
struct EmitterPrototype
{
EmitterPrototype()
: m_TileSource(0)
, m_Material(0)
{
}
/// Emitter properties
Property m_Properties[dmParticleDDF::EMITTER_KEY_COUNT];
/// Particle properties
Property m_ParticleProperties[dmParticleDDF::PARTICLE_KEY_COUNT];
dmArray<ModifierPrototype> m_Modifiers;
dmhash_t m_Animation;
/// Tile source to use when rendering particles.
void* m_TileSource;
/// Material to use when rendering particles.
void* m_Material;
/// Blend mode
dmParticleDDF::BlendMode m_BlendMode;
/// The max life time possible of a particle (used for quantizing particle life time when sorting)
float m_MaxParticleLifeTime;
};
/**
* Representation of an instance resource.
*/
struct Prototype
{
Prototype()
: m_Emitters()
, m_DDF(0x0)
{
}
/// Emitter prototypes
dmArray<EmitterPrototype> m_Emitters;
/// DDF structure read from the resource.
dmParticleDDF::ParticleFX* m_DDF;
};
void UpdateRenderData(HParticleContext context, HInstance instance, uint32_t emitter_index);
}
#endif // DM_PARTICLE_PRIVATE_H