4747
4848ParticleSystem::ParticleSystem (uint16_t width, uint16_t height, uint16_t numberofparticles, uint16_t numberofsources)
4949{
50- Serial.println (" PS Constructor" );
50+ // Serial.println("PS Constructor");
5151 numSources = numberofsources;
5252 numParticles = numberofparticles; // set number of particles in the array
5353 usedParticles = numberofparticles; // use all particles by default
@@ -69,7 +69,7 @@ ParticleSystem::ParticleSystem(uint16_t width, uint16_t height, uint16_t numbero
6969 Serial.println(particles[i].y);
7070 }
7171 }*/
72- Serial.println (" PS Constructor done" );
72+ // Serial.println("PS Constructor done");
7373}
7474
7575// update function applies gravity, moves the particles, handles collisions and renders the particles
@@ -285,9 +285,12 @@ void ParticleSystem::particleMoveUpdate(PSparticle &part, PSsettings &options)
285285 {
286286 if (newY < PS_P_RADIUS) // bounce at bottom
287287 {
288- part.vy = -part.vy ; // invert speed
289- part.vy = (part.vy * wallHardness) / 255 ; // reduce speed as energy is lost on non-hard surface
290- newY = PS_P_RADIUS;
288+ if (part.vy < -10 )
289+ {
290+ part.vy = -part.vy ; // invert speed
291+ part.vy = ((int32_t )part.vy * wallHardness) / 255 ; // reduce speed as energy is lost on non-hard surface
292+ newY = PS_P_RADIUS;
293+ }
291294 }
292295 else
293296 {
@@ -299,7 +302,7 @@ void ParticleSystem::particleMoveUpdate(PSparticle &part, PSsettings &options)
299302 else
300303 {
301304 part.vy = -part.vy ; // invert speed
302- part.vy = (part.vy * wallHardness) / 255 ; // reduce speed as energy is lost on non-hard surface
305+ part.vy = (( int32_t ) part.vy * wallHardness) / 255 ; // reduce speed as energy is lost on non-hard surface
303306 newY = maxY - PS_P_RADIUS;
304307 }
305308 }
@@ -341,8 +344,8 @@ void ParticleSystem::applyForce(PSparticle *part, uint32_t numparticles, int8_t
341344 uint8_t ycounter = (*counter) >> 4 ; // upper four bits
342345
343346 // velocity increase
344- int32_t dvx = calcForce_dV (xforce, &xcounter);
345- int32_t dvy = calcForce_dV (yforce, &ycounter);
347+ int32_t dvx = calcForce_dv (xforce, &xcounter);
348+ int32_t dvy = calcForce_dv (yforce, &ycounter);
346349
347350 // save counter values back
348351 *counter |= xcounter & 0x0F ; // write lower four bits, make sure not to write more than 4 bits
@@ -352,30 +355,18 @@ void ParticleSystem::applyForce(PSparticle *part, uint32_t numparticles, int8_t
352355 int32_t i = 0 ;
353356 if (dvx != 0 )
354357 {
355- if (numparticles == 1 ) // for single particle, skip the for loop to make it faster
358+ for (i = 0 ; i < numparticles; i++)
356359 {
357- part[0 ].vx = part[0 ].vx + dvx > PS_P_MAXSPEED ? PS_P_MAXSPEED : part[0 ].vx + dvx; // limit the force, this is faster than min or if/else
358- }
359- else
360- {
361- for (i = 0 ; i < numparticles; i++)
362- {
363- // note: not checking if particle is dead is faster as most are usually alive and if few are alive, rendering is faster so no speed penalty
364- part[i].vx = part[i].vx + dvx > PS_P_MAXSPEED ? PS_P_MAXSPEED : part[i].vx + dvx;
365- }
360+ // note: not checking if particle is dead is faster as most are usually alive and if few are alive, rendering is faster so no speed penalty
361+ part[i].vx = limitSpeed ((int32_t )particles[i].vx + dvx);
366362 }
367363 }
368364 if (dvy != 0 )
369365 {
370- if (numparticles == 1 ) // for single particle, skip the for loop to make it faster
371- part[0 ].vy = part[0 ].vy + dvy > PS_P_MAXSPEED ? PS_P_MAXSPEED : part[0 ].vy + dvy;
372- else
366+ for (i = 0 ; i < numparticles; i++)
373367 {
374- for (i = 0 ; i < numparticles; i++)
375- {
376- part[i].vy = part[i].vy + dvy > PS_P_MAXSPEED ? PS_P_MAXSPEED : part[i].vy + dvy;
377- }
378- }
368+ part[i].vy = limitSpeed ((int32_t )particles[i].vy + dvy);
369+ }
379370 }
380371}
381372
@@ -386,8 +377,8 @@ void ParticleSystem::applyForce(PSparticle *part, uint32_t numparticles, int8_t
386377 for (uint i = 0 ; i < numparticles; i++)
387378 {
388379 // note: not checking if particle is dead is faster as most are usually alive and if few are alive, rendering is faster so no speed penalty
389- part[i].vx = part[i].vx + xforce > PS_P_MAXSPEED ? PS_P_MAXSPEED : part[i]. vx + xforce ;
390- part[i].vy = part[i].vy + yforce > PS_P_MAXSPEED ? PS_P_MAXSPEED : part[i]. vy + yforce ;
380+ part[i].vx = limitSpeed (( int32_t ) part[i].vx + ( int32_t ) xforce) ;
381+ part[i].vy = limitSpeed (( int32_t ) part[i].vy + ( int32_t ) yforce) ;
391382 }
392383}
393384
@@ -415,27 +406,17 @@ void ParticleSystem::applyAngleForce(PSparticle *part, uint32_t numparticles, ui
415406// apply gravity to a group of particles
416407// faster than apply force since direction is always down and counter is fixed for all particles
417408// caller needs to provide a 8bit counter that holds its value between calls
418- // force is in 4.4 fixed point notation so force=16 means apply v+1 each frame default of 8 is every other frame (gives good results), force above 127 are VERY strong
419- void ParticleSystem::applyGravity (PSparticle *part, uint32_t numarticles, uint8_t force, uint8_t *counter)
409+ // force is in 3.4 fixed point notation so force=16 means apply v+1 each frame default of 8 is every other frame (gives good results)
410+ // positive force means down
411+ void ParticleSystem::applyGravity (PSparticle *part, uint32_t numarticles, int8_t force, uint8_t *counter)
420412{
421- int32_t dv; // velocity increase
422- if (force > 15 )
423- dv = (force >> 4 ); // apply the 4 MSBs
424- else
425- dv = 1 ;
426-
427- *counter += force;
428-
429- if (*counter > 15 )
430- {
431- *counter -= 16 ;
432- // apply force to all used particles
433- for (uint32_t i = 0 ; i < numarticles; i++)
434- {
435- // note: not checking if particle is dead is faster as most are usually alive and if few are alive, rendering is fast anyways
436- particles[i].vy = particles[i].vy - dv > PS_P_MAXSPEED ? PS_P_MAXSPEED : particles[i].vy - dv; // limit the force, this is faster than min or if/else
437- }
413+ int32_t dv = calcForce_dv (force, counter);
414+ for (uint32_t i = 0 ; i < numarticles; i++)
415+ {
416+ // note: not checking if particle is dead is faster as most are usually alive and if few are alive, rendering is fast anyways
417+ part[i].vy = limitSpeed ((int32_t )particles[i].vy - dv);
438418 }
419+
439420}
440421
441422// apply gravity using PS global gforce
@@ -445,6 +426,7 @@ void ParticleSystem::applyGravity(PSparticle *part, uint32_t numarticles, uint8_
445426}
446427
447428// apply gravity to single particle using system settings (use this for sources)
429+ // function does not increment gravity counter, if gravity setting is disabled, this cannot be used
448430void ParticleSystem::applyGravity (PSparticle *part)
449431{
450432 int32_t dv; // velocity increase
@@ -454,8 +436,8 @@ void ParticleSystem::applyGravity(PSparticle *part)
454436 dv = 1 ;
455437
456438 if (gforcecounter + gforce > 15 ) // counter is updated in global update when applying gravity
457- {
458- part->vy = part->vy - dv > PS_P_MAXSPEED ? PS_P_MAXSPEED : part-> vy - dv; // limit the force, this is faster than min or if/else
439+ {
440+ part->vy = limitSpeed (( int32_t ) part->vy - dv);
459441 }
460442}
461443
@@ -1093,11 +1075,11 @@ int32_t ParticleSystem::wraparound(int32_t p, int32_t maxvalue)
10931075
10941076// calculate the delta speed (dV) value and update the counter for force calculation (is used several times, function saves on codesize)
10951077// force is in 3.4 fixedpoint notation, +/-127
1096- int32_t ParticleSystem::calcForce_dV (int8_t force, uint8_t * counter)
1078+ int32_t ParticleSystem::calcForce_dv (int8_t force, uint8_t * counter)
10971079{
10981080 // for small forces, need to use a delay counter
10991081 int32_t force_abs = abs (force); // absolute value (faster than lots of if's only 7 instructions)
1100- int32_t dv = 0 ;
1082+ int32_t dv;
11011083 // for small forces, need to use a delay counter, apply force only if it overflows
11021084 if (force_abs < 16 )
11031085 {
@@ -1115,6 +1097,12 @@ int32_t ParticleSystem::calcForce_dV(int8_t force, uint8_t* counter)
11151097 return dv;
11161098}
11171099
1100+ // limit speed to prevent overflows
1101+ int32_t ParticleSystem::limitSpeed (int32_t speed)
1102+ {
1103+ return speed > PS_P_MAXSPEED ? PS_P_MAXSPEED : (speed < -PS_P_MAXSPEED ? -PS_P_MAXSPEED : speed);
1104+ }
1105+
11181106// allocate memory for the 2D array in one contiguous block and set values to zero
11191107CRGB **ParticleSystem::allocate2Dbuffer (uint32_t cols, uint32_t rows)
11201108{
@@ -1207,33 +1195,33 @@ bool allocateParticleSystemMemory(uint16_t numparticles, uint16_t numsources, ui
12071195 requiredmemory += sizeof (PSparticle) * numparticles;
12081196 requiredmemory += sizeof (PSsource) * numsources;
12091197 requiredmemory += additionalbytes;
1210- Serial.print (" allocating: " );
1211- Serial.print (requiredmemory);
1212- Serial.println (" Bytes" );
1213- Serial.print (" allocating for segment at" );
1214- Serial.println ((uintptr_t )SEGMENT.data );
1198+ // Serial.print("allocating: ");
1199+ // Serial.print(requiredmemory);
1200+ // Serial.println("Bytes");
1201+ // Serial.print("allocating for segment at");
1202+ // Serial.println((uintptr_t)SEGMENT.data);
12151203 return (SEGMENT.allocateData (requiredmemory));
12161204}
12171205
12181206// initialize Particle System, allocate additional bytes if needed (pointer to those bytes can be read from particle system class: PSdataEnd)
12191207bool initParticleSystem (ParticleSystem *&PartSys, uint16_t additionalbytes)
12201208{
1221- Serial.println (" PS init function" );
1209+ // Serial.println("PS init function");
12221210 uint32_t numparticles = calculateNumberOfParticles ();
12231211 uint32_t numsources = calculateNumberOfSources ();
12241212 if (!allocateParticleSystemMemory (numparticles, numsources, additionalbytes))
12251213 {
12261214 DEBUG_PRINT (F (" PS init failed: memory depleted" ));
12271215 return false ;
12281216 }
1229- Serial.print (" segment.data ptr" );
1230- Serial.println ((uintptr_t )(SEGMENT.data ));
1217+ // Serial.print("segment.data ptr");
1218+ // Serial.println((uintptr_t)(SEGMENT.data));
12311219 uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth () : 1 ;
12321220 uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight () : SEGMENT.virtualLength ();
1233- Serial.println (" calling constructor" );
1221+ // Serial.println("calling constructor");
12341222 PartSys = new (SEGMENT.data ) ParticleSystem (cols, rows, numparticles, numsources); // particle system constructor TODO: why does VS studio thinkt this is bad?
1235- Serial.print (" PS pointer at " );
1236- Serial.println ((uintptr_t )PartSys);
1223+ // Serial.print("PS pointer at ");
1224+ // Serial.println((uintptr_t)PartSys);
12371225 return true ;
12381226}
12391227
0 commit comments