Skip to content

Commit 462cd76

Browse files
committed
Fixed a bug with number of particles active getting truncated prematurely.
Limited supported flags to BLEND_ADD and BLENDMODE_NONE. Decoupled image index caclucations from draw function. Format, refactors and simplifications.
1 parent 894b133 commit 462cd76

File tree

13 files changed

+353
-264
lines changed

13 files changed

+353
-264
lines changed

src/data_block.c

Lines changed: 81 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ alloc_and_init_lifetimes(DataBlock *block, Emitter *emitter)
120120
return 1;
121121
}
122122

123+
int
124+
alloc_and_init_animation_indices(DataBlock *block, Emitter *emitter)
125+
{
126+
block->animation_indices = PyMem_New(int, emitter->emission_number);
127+
128+
return block->animation_indices != NULL;
129+
}
130+
123131
int
124132
find_first_leq_zero(const float *restrict arr, int size)
125133
{
@@ -148,47 +156,48 @@ recalculate_particle_count(DataBlock *block)
148156
int index = find_first_leq_zero(block->lifetimes.data, block->particles_count);
149157

150158
/* If all particles are alive the index will be -1, so just return */
151-
if (index == -1 && block->particles_count == block->lifetimes.capacity)
159+
if (index == -1)
152160
return;
153161

154-
if (index == 0) {
155-
block->particles_count = 0;
156-
block->ended = true;
157-
return;
158-
}
162+
block->particles_count = index;
159163

160-
block->particles_count = index + 1;
164+
if (!index)
165+
block->ended = true;
161166
}
162167

163168
void
164169
UDB_no_acceleration(DataBlock *block, float dt)
165170
{
166171
float *restrict positions_x = block->positions_x.data;
167172
float *restrict positions_y = block->positions_y.data;
173+
float *restrict lifetimes = block->lifetimes.data;
168174
float const *restrict velocities_x = block->velocities_x.data;
169175
float const *restrict velocities_y = block->velocities_y.data;
170-
float *restrict lifetimes = block->lifetimes.data;
176+
float const *restrict max_lifetimes = block->max_lifetimes.data;
177+
int *restrict indices = block->animation_indices;
171178

172179
for (int i = 0; i < block->particles_count; i++) {
173180
positions_x[i] += velocities_x[i] * dt;
174181
positions_y[i] += velocities_y[i] * dt;
175182

176183
lifetimes[i] -= dt;
184+
indices[i] =
185+
(int)((1.0f - lifetimes[i] / max_lifetimes[i]) * block->num_frames);
177186
}
178-
179-
recalculate_particle_count(block);
180187
}
181188

182189
void
183190
UDB_all(DataBlock *block, float dt)
184191
{
185-
float *positions_x = block->positions_x.data;
186-
float *positions_y = block->positions_y.data;
187-
float *velocities_x = block->velocities_x.data;
188-
float *velocities_y = block->velocities_y.data;
189-
float const *accelerations_x = block->accelerations_x.data;
190-
float const *accelerations_y = block->accelerations_y.data;
192+
float *restrict positions_x = block->positions_x.data;
193+
float *restrict positions_y = block->positions_y.data;
194+
float *restrict velocities_x = block->velocities_x.data;
195+
float *restrict velocities_y = block->velocities_y.data;
191196
float *restrict lifetimes = block->lifetimes.data;
197+
float const *restrict accelerations_x = block->accelerations_x.data;
198+
float const *restrict accelerations_y = block->accelerations_y.data;
199+
float const *restrict max_lifetimes = block->max_lifetimes.data;
200+
int *restrict indices = block->animation_indices;
192201

193202
for (int i = 0; i < block->particles_count; i++) {
194203
velocities_x[i] += accelerations_x[i] * dt;
@@ -197,9 +206,9 @@ UDB_all(DataBlock *block, float dt)
197206
positions_y[i] += velocities_y[i] * dt;
198207

199208
lifetimes[i] -= dt;
209+
indices[i] =
210+
(int)((1.0f - lifetimes[i] / max_lifetimes[i]) * block->num_frames);
200211
}
201-
202-
recalculate_particle_count(block);
203212
}
204213

205214
void
@@ -210,38 +219,42 @@ UDB_acceleration_x(DataBlock *block, float dt)
210219
float *restrict velocities_x = block->velocities_x.data;
211220
float const *restrict velocities_y = block->velocities_y.data;
212221
float const *restrict accelerations_x = block->accelerations_x.data;
222+
float const *restrict max_lifetimes = block->max_lifetimes.data;
213223
float *restrict lifetimes = block->lifetimes.data;
224+
int *restrict indices = block->animation_indices;
214225

215226
for (int i = 0; i < block->particles_count; i++) {
216227
velocities_x[i] += accelerations_x[i] * dt;
217228
positions_x[i] += velocities_x[i] * dt;
218229
positions_y[i] += velocities_y[i] * dt;
219230

220231
lifetimes[i] -= dt;
232+
indices[i] =
233+
(int)((1.0f - lifetimes[i] / max_lifetimes[i]) * block->num_frames);
221234
}
222-
223-
recalculate_particle_count(block);
224235
}
225236

226237
void
227238
UDB_acceleration_y(DataBlock *block, float dt)
228239
{
229240
float *restrict positions_x = block->positions_x.data;
230241
float *restrict positions_y = block->positions_y.data;
231-
float const *restrict velocities_x = block->velocities_x.data;
232242
float *restrict velocities_y = block->velocities_y.data;
233-
float const *restrict accelerations_y = block->accelerations_y.data;
234243
float *restrict lifetimes = block->lifetimes.data;
244+
float const *restrict max_lifetimes = block->max_lifetimes.data;
245+
float const *restrict velocities_x = block->velocities_x.data;
246+
float const *restrict accelerations_y = block->accelerations_y.data;
247+
int *restrict indices = block->animation_indices;
235248

236249
for (int i = 0; i < block->particles_count; i++) {
237250
velocities_y[i] += accelerations_y[i] * dt;
238251
positions_x[i] += velocities_x[i] * dt;
239252
positions_y[i] += velocities_y[i] * dt;
240253

241254
lifetimes[i] -= dt;
255+
indices[i] =
256+
(int)((1.0f - lifetimes[i] / max_lifetimes[i]) * block->num_frames);
242257
}
243-
244-
recalculate_particle_count(block);
245258
}
246259

247260
void
@@ -304,18 +317,55 @@ init_data_block(DataBlock *block, Emitter *emitter, vec2 position)
304317
if (!alloc_and_init_positions(block, emitter, position) ||
305318
!alloc_and_init_velocities(block, emitter) ||
306319
!alloc_and_init_accelerations(block, emitter) ||
307-
!alloc_and_init_lifetimes(block, emitter))
320+
!alloc_and_init_lifetimes(block, emitter) ||
321+
!alloc_and_init_animation_indices(block, emitter))
308322
return 0;
309323

310324
choose_and_set_update_function(block, emitter);
311325

312326
return 1;
313327
}
314328

329+
void
330+
update_indices_scalar(DataBlock *block)
331+
{
332+
float const *restrict lifetimes = block->lifetimes.data;
333+
float const *restrict max_lifetimes = block->max_lifetimes.data;
334+
int *restrict indices = block->animation_indices;
335+
336+
for (int i = 0; i < block->particles_count; i++)
337+
indices[i] =
338+
(int)((1.0f - lifetimes[i] / max_lifetimes[i]) * block->num_frames);
339+
}
340+
341+
void
342+
update_indices(DataBlock *block)
343+
{
344+
#if !defined(__EMSCRIPTEN__)
345+
if (_Has_AVX2()) {
346+
update_indices_avx2(block);
347+
return;
348+
}
349+
350+
#if ENABLE_SSE_NEON
351+
if (_HasSSE_NEON()) {
352+
update_indices_sse2(block);
353+
return;
354+
}
355+
#endif /* ENABLE_SSE_NEON */
356+
#endif /* __EMSCRIPTEN__ */
357+
358+
update_indices_scalar(block);
359+
}
360+
315361
void
316362
update_data_block(DataBlock *block, float dt)
317363
{
318364
block->updater(block, dt);
365+
366+
recalculate_particle_count(block);
367+
368+
update_indices(block);
319369
}
320370

321371
int
@@ -324,17 +374,13 @@ draw_data_block(DataBlock *block, pgSurfaceObject *dest, const int blend_flag)
324374
pgSurfaceObject *src_obj;
325375
float const *positions_x = block->positions_x.data;
326376
float const *positions_y = block->positions_y.data;
327-
float const *lifetimes = block->lifetimes.data;
328-
float const *max_lifetimes = block->max_lifetimes.data;
329-
const int num_frames = block->num_frames;
330377
PyObject **animation = PySequence_Fast_ITEMS(block->animation);
378+
int const *indices = block->animation_indices;
379+
const int max_ix = block->num_frames - 1;
331380

332381
for (int i = 0; i < block->particles_count; i++) {
333-
334-
int img_ix = (int)((1.0f - lifetimes[i] / max_lifetimes[i]) * num_frames);
335-
img_ix = clamp_int(img_ix, 0, num_frames - 1);
336-
337-
src_obj = (pgSurfaceObject *)animation[img_ix];
382+
const int index = clamp_int(indices[i], 0, max_ix);
383+
src_obj = (pgSurfaceObject *)animation[index];
338384
if (!src_obj) {
339385
PyErr_SetString(PyExc_RuntimeError, "Surface is not initialized");
340386
return 0;
@@ -364,4 +410,5 @@ dealloc_data_block(DataBlock *block)
364410
float_array_free(&block->accelerations_y);
365411
float_array_free(&block->lifetimes);
366412
float_array_free(&block->max_lifetimes);
367-
}
413+
PyMem_Free(block->animation_indices);
414+
}

src/effect_instance.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#include "include/effect_instance.h"
22

33
int
4-
init_effect_instance(EffectInstance *instance, ParticleEffect *effect, vec2 position) {
4+
init_effect_instance(EffectInstance *instance, ParticleEffect *effect, vec2 position)
5+
{
56
instance->position = position;
67
instance->blocks_count = effect->emitters_count;
78
instance->ended = false;
@@ -17,7 +18,7 @@ init_effect_instance(EffectInstance *instance, ParticleEffect *effect, vec2 posi
1718

1819
/* Initialize each data block, one per emitter */
1920
for (Py_ssize_t i = 0; i < effect->emitters_count; i++) {
20-
Emitter *emitter = &((EmitterObject *) emitter_objs[i])->emitter;
21+
Emitter *emitter = &((EmitterObject *)emitter_objs[i])->emitter;
2122
DataBlock *db = &instance->p_data[i];
2223
if (!init_data_block(db, emitter, position))
2324
return 0;
@@ -27,7 +28,8 @@ init_effect_instance(EffectInstance *instance, ParticleEffect *effect, vec2 posi
2728
}
2829

2930
void
30-
update_effect_instance(EffectInstance *instance, float dt) {
31+
update_effect_instance(EffectInstance *instance, float dt)
32+
{
3133
int active_blocks = 0;
3234

3335
for (Py_ssize_t i = 0; i < instance->blocks_count; i++) {
@@ -45,16 +47,19 @@ update_effect_instance(EffectInstance *instance, float dt) {
4547
}
4648

4749
int
48-
draw_effect_instance(EffectInstance *instance, pgSurfaceObject *dest) {
50+
draw_effect_instance(EffectInstance *instance, pgSurfaceObject *dest)
51+
{
4952
for (Py_ssize_t i = 0; i < instance->blocks_count; i++)
50-
if (!draw_data_block(&instance->p_data[i], dest, instance->p_data[i].blend_mode))
53+
if (!draw_data_block(&instance->p_data[i], dest,
54+
instance->p_data[i].blend_mode))
5155
return 0;
5256

5357
return 1;
5458
}
5559

5660
void
57-
dealloc_effect_instance(EffectInstance *instance) {
61+
dealloc_effect_instance(EffectInstance *instance)
62+
{
5863
for (Py_ssize_t i = 0; i < instance->blocks_count; i++)
5964
dealloc_data_block(&instance->p_data[i]);
6065

0 commit comments

Comments
 (0)