@@ -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+
123131int
124132find_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
163168void
164169UDB_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
182189void
183190UDB_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
205214void
@@ -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
226237void
227238UDB_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
247260void
@@ -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+
315361void
316362update_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
321371int
@@ -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+ }
0 commit comments