cleanup and minor improvements
- removed local buffer for ESP8266 in 1D system to save on RAM - increased particle brightness in PS Impact - minor tweak in collision binning (might improve speed) - removed comments and some other unused stuff - fixed a few compiler wranings
This commit is contained in:
@@ -9338,7 +9338,7 @@ uint16_t mode_particlefire(void) {
|
|||||||
uint32_t i; // index variable
|
uint32_t i; // index variable
|
||||||
uint32_t numFlames; // number of flames: depends on fire width. for a fire width of 16 pixels, about 25-30 flames give good results
|
uint32_t numFlames; // number of flames: depends on fire width. for a fire width of 16 pixels, about 25-30 flames give good results
|
||||||
|
|
||||||
if (SEGMENT.call == 0) { // initialization TODO: make this a PSinit function, this is needed in every particle FX but first, get this working.
|
if (SEGMENT.call == 0) { // initialization
|
||||||
if (!initParticleSystem2D(PartSys, SEGMENT.virtualWidth(), 4)) //maximum number of source (PS may limit based on segment size); need 4 additional bytes for time keeping (uint32_t lastcall)
|
if (!initParticleSystem2D(PartSys, SEGMENT.virtualWidth(), 4)) //maximum number of source (PS may limit based on segment size); need 4 additional bytes for time keeping (uint32_t lastcall)
|
||||||
return mode_static(); // allocation failed or not 2D
|
return mode_static(); // allocation failed or not 2D
|
||||||
SEGENV.aux0 = hw_random16(); // aux0 is wind position (index) in the perlin noise
|
SEGENV.aux0 = hw_random16(); // aux0 is wind position (index) in the perlin noise
|
||||||
@@ -9430,7 +9430,7 @@ uint16_t mode_particlepit(void) {
|
|||||||
ParticleSystem2D *PartSys = nullptr;
|
ParticleSystem2D *PartSys = nullptr;
|
||||||
|
|
||||||
if (SEGMENT.call == 0) { // initialization
|
if (SEGMENT.call == 0) { // initialization
|
||||||
if (!initParticleSystem2D(PartSys, 1, 0, true, false)) // init, request one source (actually dont really need one TODO: test if using zero sources also works)
|
if (!initParticleSystem2D(PartSys, 0, 0, true, false)) // init
|
||||||
return mode_static(); // allocation failed or not 2D
|
return mode_static(); // allocation failed or not 2D
|
||||||
PartSys->setKillOutOfBounds(true);
|
PartSys->setKillOutOfBounds(true);
|
||||||
PartSys->setGravity(); // enable with default gravity
|
PartSys->setGravity(); // enable with default gravity
|
||||||
@@ -9501,7 +9501,7 @@ uint16_t mode_particlewaterfall(void) {
|
|||||||
uint8_t numSprays;
|
uint8_t numSprays;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
if (SEGMENT.call == 0) { // initialization TODO: make this a PSinit function, this is needed in every particle FX but first, get this working.
|
if (SEGMENT.call == 0) { // initialization
|
||||||
if (!initParticleSystem2D(PartSys, 12)) // init, request 12 sources, no additional data needed
|
if (!initParticleSystem2D(PartSys, 12)) // init, request 12 sources, no additional data needed
|
||||||
return mode_static(); // allocation failed or not 2D
|
return mode_static(); // allocation failed or not 2D
|
||||||
|
|
||||||
@@ -9524,7 +9524,7 @@ uint16_t mode_particlewaterfall(void) {
|
|||||||
else
|
else
|
||||||
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
||||||
if (PartSys == nullptr)
|
if (PartSys == nullptr)
|
||||||
return mode_static(); // something went wrong, no data! (TODO: ask how to handle this so it always works)
|
return mode_static(); // something went wrong, no data!
|
||||||
|
|
||||||
// Particle System settings
|
// Particle System settings
|
||||||
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
|
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
|
||||||
@@ -9653,7 +9653,7 @@ uint16_t mode_particleperlin(void) {
|
|||||||
ParticleSystem2D *PartSys = nullptr;
|
ParticleSystem2D *PartSys = nullptr;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
if (SEGMENT.call == 0) { // initialization TODO: make this a PSinit function, this is needed in every particle FX but first, get this working.
|
if (SEGMENT.call == 0) { // initialization
|
||||||
if (!initParticleSystem2D(PartSys, 1, 0, true)) // init with 1 source and advanced properties
|
if (!initParticleSystem2D(PartSys, 1, 0, true)) // init with 1 source and advanced properties
|
||||||
return mode_static(); // allocation failed or not 2D
|
return mode_static(); // allocation failed or not 2D
|
||||||
|
|
||||||
@@ -9714,20 +9714,19 @@ static const char _data_FX_MODE_PARTICLEPERLIN[] PROGMEM = "PS Fuzzy Noise@Speed
|
|||||||
uint16_t mode_particleimpact(void) {
|
uint16_t mode_particleimpact(void) {
|
||||||
ParticleSystem2D *PartSys = nullptr;
|
ParticleSystem2D *PartSys = nullptr;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
uint8_t MaxNumMeteors;
|
uint32_t numMeteors;
|
||||||
PSsettings2D meteorsettings;
|
PSsettings2D meteorsettings;
|
||||||
meteorsettings.asByte = 0b00101000; // PS settings for meteors: bounceY and gravity enabled
|
meteorsettings.asByte = 0b00101000; // PS settings for meteors: bounceY and gravity enabled
|
||||||
|
|
||||||
if (SEGMENT.call == 0) { // initialization TODO: make this a PSinit function, this is needed in every particle FX but first, get this working.
|
if (SEGMENT.call == 0) { // initialization
|
||||||
if (!initParticleSystem2D(PartSys, NUMBEROFSOURCES)) // init, no additional data needed
|
if (!initParticleSystem2D(PartSys, NUMBEROFSOURCES)) // init, no additional data needed
|
||||||
return mode_static(); // allocation failed or not 2D
|
return mode_static(); // allocation failed or not 2D
|
||||||
PartSys->setKillOutOfBounds(true);
|
PartSys->setKillOutOfBounds(true);
|
||||||
PartSys->setGravity(); // enable default gravity
|
PartSys->setGravity(); // enable default gravity
|
||||||
PartSys->setBounceY(true); // always use ground bounce
|
PartSys->setBounceY(true); // always use ground bounce
|
||||||
PartSys->setWallRoughness(220); // high roughness
|
PartSys->setWallRoughness(220); // high roughness
|
||||||
MaxNumMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES);
|
numMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES);
|
||||||
for (i = 0; i < MaxNumMeteors; i++) {
|
for (i = 0; i < numMeteors; i++) {
|
||||||
// PartSys->sources[i].source.y = 500;
|
|
||||||
PartSys->sources[i].source.ttl = hw_random16(10 * i); // set initial delay for meteors
|
PartSys->sources[i].source.ttl = hw_random16(10 * i); // set initial delay for meteors
|
||||||
PartSys->sources[i].source.vy = 10; // at positive speeds, no particles are emitted and if particle dies, it will be relaunched
|
PartSys->sources[i].source.vy = 10; // at positive speeds, no particles are emitted and if particle dies, it will be relaunched
|
||||||
}
|
}
|
||||||
@@ -9736,7 +9735,7 @@ uint16_t mode_particleimpact(void) {
|
|||||||
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
||||||
|
|
||||||
if (PartSys == nullptr)
|
if (PartSys == nullptr)
|
||||||
return mode_static(); // something went wrong, no data! (TODO: ask how to handle this so it always works)
|
return mode_static(); // something went wrong, no data!
|
||||||
|
|
||||||
// Particle System settings
|
// Particle System settings
|
||||||
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
|
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
|
||||||
@@ -9746,29 +9745,18 @@ uint16_t mode_particleimpact(void) {
|
|||||||
uint8_t hardness = map(SEGMENT.custom2, 0, 255, PS_P_MINSURFACEHARDNESS - 2, 255);
|
uint8_t hardness = map(SEGMENT.custom2, 0, 255, PS_P_MINSURFACEHARDNESS - 2, 255);
|
||||||
PartSys->setWallHardness(hardness);
|
PartSys->setWallHardness(hardness);
|
||||||
PartSys->enableParticleCollisions(SEGMENT.check3, hardness); // enable collisions and set particle collision hardness
|
PartSys->enableParticleCollisions(SEGMENT.check3, hardness); // enable collisions and set particle collision hardness
|
||||||
MaxNumMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES);
|
numMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES);
|
||||||
uint8_t numMeteors = MaxNumMeteors; // TODO: clean this up map(SEGMENT.custom3, 0, 31, 1, MaxNumMeteors); // number of meteors to use for animation
|
|
||||||
|
|
||||||
uint32_t emitparticles; // number of particles to emit for each rocket's state
|
uint32_t emitparticles; // number of particles to emit for each rocket's state
|
||||||
|
|
||||||
for (i = 0; i < numMeteors; i++) {
|
for (i = 0; i < numMeteors; i++) {
|
||||||
// determine meteor state by its speed:
|
// determine meteor state by its speed:
|
||||||
if ( PartSys->sources[i].source.vy < 0) { // moving down, emit sparks
|
if ( PartSys->sources[i].source.vy < 0) // moving down, emit sparks
|
||||||
#ifdef ESP8266
|
|
||||||
emitparticles = 1;
|
emitparticles = 1;
|
||||||
#else
|
|
||||||
emitparticles = 2;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if ( PartSys->sources[i].source.vy > 0) // moving up means meteor is on 'standby'
|
else if ( PartSys->sources[i].source.vy > 0) // moving up means meteor is on 'standby'
|
||||||
emitparticles = 0;
|
emitparticles = 0;
|
||||||
else { // speed is zero, explode!
|
else { // speed is zero, explode!
|
||||||
PartSys->sources[i].source.vy = 10; // set source speed positive so it goes into timeout and launches again
|
PartSys->sources[i].source.vy = 10; // set source speed positive so it goes into timeout and launches again
|
||||||
#ifdef ESP8266
|
emitparticles = map(SEGMENT.intensity, 0, 255, 10, hw_random16(PartSys->usedParticles>>2)); // defines the size of the explosion
|
||||||
emitparticles = hw_random16(SEGMENT.intensity >> 3) + 5; // defines the size of the explosion
|
|
||||||
#else
|
|
||||||
emitparticles = map(SEGMENT.intensity, 0, 255, 10, hw_random16(PartSys->usedParticles>>2)); // defines the size of the explosion !!!TODO: check if this works on ESP8266, drop esp8266 def if it does
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
for (int e = emitparticles; e > 0; e--) {
|
for (int e = emitparticles; e > 0; e--) {
|
||||||
PartSys->sprayEmit(PartSys->sources[i]);
|
PartSys->sprayEmit(PartSys->sources[i]);
|
||||||
@@ -9789,13 +9777,13 @@ uint16_t mode_particleimpact(void) {
|
|||||||
PartSys->sources[i].source.vx = 0;
|
PartSys->sources[i].source.vx = 0;
|
||||||
PartSys->sources[i].sourceFlags.collide = true;
|
PartSys->sources[i].sourceFlags.collide = true;
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
PartSys->sources[i].maxLife = 180;
|
PartSys->sources[i].maxLife = 900;
|
||||||
PartSys->sources[i].minLife = 20;
|
PartSys->sources[i].minLife = 100;
|
||||||
#else
|
#else
|
||||||
PartSys->sources[i].maxLife = 250;
|
PartSys->sources[i].maxLife = 1250;
|
||||||
PartSys->sources[i].minLife = 50;
|
PartSys->sources[i].minLife = 250;
|
||||||
#endif
|
#endif
|
||||||
PartSys->sources[i].source.ttl = hw_random16((512 - (SEGMENT.speed << 1))) + 40; // standby time til next launch (in frames)
|
PartSys->sources[i].source.ttl = hw_random16((768 - (SEGMENT.speed << 1))) + 40; // standby time til next launch (in frames)
|
||||||
PartSys->sources[i].vy = (SEGMENT.custom1 >> 2); // emitting speed y
|
PartSys->sources[i].vy = (SEGMENT.custom1 >> 2); // emitting speed y
|
||||||
PartSys->sources[i].var = (SEGMENT.custom1 >> 2); // speed variation around vx,vy (+/- var)
|
PartSys->sources[i].var = (SEGMENT.custom1 >> 2); // speed variation around vx,vy (+/- var)
|
||||||
}
|
}
|
||||||
@@ -9810,13 +9798,17 @@ uint16_t mode_particleimpact(void) {
|
|||||||
PartSys->sources[i].source.hue = hw_random16(); // random color
|
PartSys->sources[i].source.hue = hw_random16(); // random color
|
||||||
PartSys->sources[i].source.ttl = 500; // long life, will explode at bottom
|
PartSys->sources[i].source.ttl = 500; // long life, will explode at bottom
|
||||||
PartSys->sources[i].sourceFlags.collide = false; // trail particles will not collide
|
PartSys->sources[i].sourceFlags.collide = false; // trail particles will not collide
|
||||||
PartSys->sources[i].maxLife = 60; // spark particle life
|
PartSys->sources[i].maxLife = 300; // spark particle life
|
||||||
PartSys->sources[i].minLife = 20;
|
PartSys->sources[i].minLife = 100;
|
||||||
PartSys->sources[i].vy = -9; // emitting speed (down)
|
PartSys->sources[i].vy = -9; // emitting speed (down)
|
||||||
PartSys->sources[i].var = 3; // speed variation around vx,vy (+/- var)
|
PartSys->sources[i].var = 3; // speed variation around vx,vy (+/- var)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||||
|
if (PartSys->particles[i].ttl > 5) PartSys->particles[i].ttl -= 5; //ttl is linked to brightness, this allows to use higher brightness but still a short spark lifespan
|
||||||
|
}
|
||||||
|
|
||||||
PartSys->update(); // update and render
|
PartSys->update(); // update and render
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
}
|
}
|
||||||
@@ -10220,7 +10212,7 @@ uint16_t mode_particleghostrider(void) {
|
|||||||
// emit two particles
|
// emit two particles
|
||||||
PartSys->angleEmit(PartSys->sources[0], emitangle, speed);
|
PartSys->angleEmit(PartSys->sources[0], emitangle, speed);
|
||||||
PartSys->angleEmit(PartSys->sources[0], emitangle, speed);
|
PartSys->angleEmit(PartSys->sources[0], emitangle, speed);
|
||||||
if (SEGMENT.call % (11 - (SEGMENT.custom2 / 25)) == 0) { // every nth frame, cycle color and emit particles //TODO: make this a segment call % SEGMENT.custom2 for better control
|
if (SEGMENT.call % (11 - (SEGMENT.custom2 / 25)) == 0) { // every nth frame, cycle color and emit particles
|
||||||
PartSys->sources[0].source.hue++;
|
PartSys->sources[0].source.hue++;
|
||||||
}
|
}
|
||||||
if (SEGMENT.custom2 > 190) //fast color change
|
if (SEGMENT.custom2 > 190) //fast color change
|
||||||
@@ -10240,7 +10232,7 @@ uint16_t mode_particleblobs(void) {
|
|||||||
ParticleSystem2D *PartSys = nullptr;
|
ParticleSystem2D *PartSys = nullptr;
|
||||||
|
|
||||||
if (SEGMENT.call == 0) {
|
if (SEGMENT.call == 0) {
|
||||||
if (!initParticleSystem2D(PartSys, 1, 0, true, true)) //init, request one source, no additional bytes, advanced size & size control (actually dont really need one TODO: test if using zero sources also works)
|
if (!initParticleSystem2D(PartSys, 0, 0, true, true)) //init, no additional bytes, advanced size & size control
|
||||||
return mode_static(); // allocation failed or not 2D
|
return mode_static(); // allocation failed or not 2D
|
||||||
PartSys->setBounceX(true);
|
PartSys->setBounceX(true);
|
||||||
PartSys->setBounceY(true);
|
PartSys->setBounceY(true);
|
||||||
@@ -10909,7 +10901,7 @@ uint16_t mode_particleHourglass(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// re-order particles in case collisions flipped particles (highest number index particle is on the "bottom")
|
// re-order particles in case collisions flipped particles (highest number index particle is on the "bottom")
|
||||||
for (int i = 0; i < PartSys->usedParticles - 1; i++) {
|
for (uint32_t i = 0; i < PartSys->usedParticles - 1; i++) {
|
||||||
if (PartSys->particles[i].x < PartSys->particles[i+1].x && PartSys->particleFlags[i].fixed == false && PartSys->particleFlags[i+1].fixed == false) {
|
if (PartSys->particles[i].x < PartSys->particles[i+1].x && PartSys->particleFlags[i].fixed == false && PartSys->particleFlags[i+1].fixed == false) {
|
||||||
std::swap(PartSys->particles[i].x, PartSys->particles[i+1].x);
|
std::swap(PartSys->particles[i].x, PartSys->particles[i+1].x);
|
||||||
}
|
}
|
||||||
@@ -11020,10 +11012,7 @@ uint16_t mode_particleBalance(void) {
|
|||||||
if (SEGMENT.call == 0) { // initialization
|
if (SEGMENT.call == 0) { // initialization
|
||||||
if (!initParticleSystem1D(PartSys, 1, 128)) // init, no additional data needed, use half of max particles
|
if (!initParticleSystem1D(PartSys, 1, 128)) // init, no additional data needed, use half of max particles
|
||||||
return mode_static(); // allocation failed or is single pixel
|
return mode_static(); // allocation failed or is single pixel
|
||||||
//PartSys->setKillOutOfBounds(true);
|
|
||||||
PartSys->setParticleSize(1);
|
PartSys->setParticleSize(1);
|
||||||
SEGENV.aux0 = 0;
|
|
||||||
SEGENV.aux1 = 0; //TODO: really need to set to zero or is it calloc'd?
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PartSys = reinterpret_cast<ParticleSystem1D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
PartSys = reinterpret_cast<ParticleSystem1D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
||||||
@@ -11175,7 +11164,7 @@ uint16_t mode_particleChase(void) {
|
|||||||
globalhuestep = 2; // global hue change to add some color variation
|
globalhuestep = 2; // global hue change to add some color variation
|
||||||
if ((SEGMENT.call & 0x1F) == 0)
|
if ((SEGMENT.call & 0x1F) == 0)
|
||||||
SEGENV.step += *stepdir; // change density
|
SEGENV.step += *stepdir; // change density
|
||||||
for(int32_t i = 0; i < PartSys->usedParticles; i++) {
|
for(uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||||
PartSys->particles[i].hue -= globalhuestep; // shift global hue (both directions)
|
PartSys->particles[i].hue -= globalhuestep; // shift global hue (both directions)
|
||||||
PartSys->particles[i].vx = 1 + (SEGMENT.speed >> 2) + ((int32_t(sin16_t(strip.now >> 1) + 32767) * (SEGMENT.speed >> 2)) >> 16);
|
PartSys->particles[i].vx = 1 + (SEGMENT.speed >> 2) + ((int32_t(sin16_t(strip.now >> 1) + 32767) * (SEGMENT.speed >> 2)) >> 16);
|
||||||
}
|
}
|
||||||
@@ -11347,7 +11336,7 @@ uint16_t mode_particleFire1D(void) {
|
|||||||
PartSys->setColorByAge(true);
|
PartSys->setColorByAge(true);
|
||||||
uint32_t emitparticles = 1;
|
uint32_t emitparticles = 1;
|
||||||
uint32_t j = hw_random16();
|
uint32_t j = hw_random16();
|
||||||
for (uint i = 0; i < 3; i++) { // 3 base flames TODO: check if this is ok or needs adjustments
|
for (uint i = 0; i < 3; i++) { // 3 base flames
|
||||||
if (PartSys->sources[i].source.ttl > 50)
|
if (PartSys->sources[i].source.ttl > 50)
|
||||||
PartSys->sources[i].source.ttl -= 10; // TODO: in 2D making the source fade out slow results in much smoother flames, need to check if it can be done the same
|
PartSys->sources[i].source.ttl -= 10; // TODO: in 2D making the source fade out slow results in much smoother flames, need to check if it can be done the same
|
||||||
else
|
else
|
||||||
@@ -11368,7 +11357,7 @@ uint16_t mode_particleFire1D(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PartSys->sources[j].minLife = PartSys->sources[j].source.ttl + SEGMENT.intensity; // TODO: in 2D, emitted particle ttl depends on source TTL, mimic here the same way? OR: change 2D to the same way it is done here and ditch special fire treatment in emit?
|
PartSys->sources[j].minLife = PartSys->sources[j].source.ttl + SEGMENT.intensity;
|
||||||
PartSys->sources[j].maxLife = PartSys->sources[j].minLife + 50;
|
PartSys->sources[j].maxLife = PartSys->sources[j].minLife + 50;
|
||||||
PartSys->sources[j].v = SEGMENT.speed >> 2;
|
PartSys->sources[j].v = SEGMENT.speed >> 2;
|
||||||
if (SEGENV.call & 0x01) // every second frame
|
if (SEGENV.call & 0x01) // every second frame
|
||||||
@@ -11629,7 +11618,7 @@ uint16_t mode_particleSpringy(void) {
|
|||||||
PartSys->particles[0].x = dxlimit; // limit the spring length
|
PartSys->particles[0].x = dxlimit; // limit the spring length
|
||||||
springforce[0] += ((springlength >> 1) - (PartSys->particles[0].x)) * springK; // first particle anchors to x=0
|
springforce[0] += ((springlength >> 1) - (PartSys->particles[0].x)) * springK; // first particle anchors to x=0
|
||||||
|
|
||||||
for (int32_t i = 1; i < PartSys->usedParticles; i++) {
|
for (uint32_t i = 1; i < PartSys->usedParticles; i++) {
|
||||||
// reorder particles if they are out of order to prevent chaos
|
// reorder particles if they are out of order to prevent chaos
|
||||||
if (PartSys->particles[i].x < PartSys->particles[i-1].x)
|
if (PartSys->particles[i].x < PartSys->particles[i-1].x)
|
||||||
std::swap(PartSys->particles[i].x, PartSys->particles[i-1].x); // swap particle positions to maintain order
|
std::swap(PartSys->particles[i].x, PartSys->particles[i-1].x); // swap particle positions to maintain order
|
||||||
@@ -11650,7 +11639,7 @@ uint16_t mode_particleSpringy(void) {
|
|||||||
}
|
}
|
||||||
// apply spring forces to particles
|
// apply spring forces to particles
|
||||||
bool dampenoscillations = (SEGMENT.call % (9 - (SEGMENT.speed >> 5))) == 0; // dampen oscillation if particles are slow, more damping on stiffer springs
|
bool dampenoscillations = (SEGMENT.call % (9 - (SEGMENT.speed >> 5))) == 0; // dampen oscillation if particles are slow, more damping on stiffer springs
|
||||||
for (int32_t i = 0; i < PartSys->usedParticles; i++) {
|
for (uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||||
springforce[i] = springforce[i] / 64; // scale spring force (cannot use shifts because of negative values)
|
springforce[i] = springforce[i] / 64; // scale spring force (cannot use shifts because of negative values)
|
||||||
int maxforce = 120; // limit spring force
|
int maxforce = 120; // limit spring force
|
||||||
springforce[i] = springforce[i] > maxforce ? maxforce : springforce[i] < -maxforce ? -maxforce : springforce[i]; // limit spring force
|
springforce[i] = springforce[i] > maxforce ? maxforce : springforce[i] < -maxforce ? -maxforce : springforce[i]; // limit spring force
|
||||||
@@ -11667,7 +11656,7 @@ uint16_t mode_particleSpringy(void) {
|
|||||||
PartSys->applyFriction((SEGMENT.intensity >> 2));
|
PartSys->applyFriction((SEGMENT.intensity >> 2));
|
||||||
|
|
||||||
// add a small resetting force so particles return to resting position even under high damping
|
// add a small resetting force so particles return to resting position even under high damping
|
||||||
for (int32_t i = 1; i < PartSys->usedParticles - 1; i++) {
|
for (uint32_t i = 1; i < PartSys->usedParticles - 1; i++) {
|
||||||
int restposition = (springlength >> 1) + i * springlength; // resting position
|
int restposition = (springlength >> 1) + i * springlength; // resting position
|
||||||
int dx = restposition - PartSys->particles[i].x; // distance, always positive
|
int dx = restposition - PartSys->particles[i].x; // distance, always positive
|
||||||
PartSys->applyForce(PartSys->particles[i], dx > 0 ? 1 : (dx < 0 ? -1 : 0), PartSys->advPartProps[i].forcecounter);
|
PartSys->applyForce(PartSys->particles[i], dx > 0 ? 1 : (dx < 0 ? -1 : 0), PartSys->advPartProps[i].forcecounter);
|
||||||
@@ -11717,7 +11706,7 @@ uint16_t mode_particleSpringy(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t i = 0; i < PartSys->usedParticles; i++) {
|
for (uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||||
if (SEGMENT.custom2 == 255) { // map speed to hue
|
if (SEGMENT.custom2 == 255) { // map speed to hue
|
||||||
int speedclr = ((int8_t(abs(PartSys->particles[i].vx))) >> 2) << 4; // scale for greater color variation, dump small values to avoid flickering
|
int speedclr = ((int8_t(abs(PartSys->particles[i].vx))) >> 2) << 4; // scale for greater color variation, dump small values to avoid flickering
|
||||||
//int speed = PartSys->particles[i].vx << 2; // +/- 512
|
//int speed = PartSys->particles[i].vx << 2; // +/- 512
|
||||||
|
|||||||
@@ -775,7 +775,7 @@ __attribute__((optimize("O2"))) void ParticleSystem2D::renderParticle(const uint
|
|||||||
// for code simplicity, no y slicing is done, making very tall matrix configurations less efficient
|
// for code simplicity, no y slicing is done, making very tall matrix configurations less efficient
|
||||||
// note: also tested adding y slicing, it gives diminishing returns, some FX even get slower. FX not using gravity would benefit with a 10% FPS improvement
|
// note: also tested adding y slicing, it gives diminishing returns, some FX even get slower. FX not using gravity would benefit with a 10% FPS improvement
|
||||||
void ParticleSystem2D::handleCollisions() {
|
void ParticleSystem2D::handleCollisions() {
|
||||||
int32_t collDistSq = particleHardRadius << 1; // distance is double the radius note: particleHardRadius is updated when setting global particle size
|
uint32_t collDistSq = particleHardRadius << 1; // distance is double the radius note: particleHardRadius is updated when setting global particle size
|
||||||
collDistSq = collDistSq * collDistSq; // square it for faster comparison (square is one operation)
|
collDistSq = collDistSq * collDistSq; // square it for faster comparison (square is one operation)
|
||||||
// note: partices are binned in x-axis, assumption is that no more than half of the particles are in the same bin
|
// note: partices are binned in x-axis, assumption is that no more than half of the particles are in the same bin
|
||||||
// if they are, collisionStartIdx is increased so each particle collides at least every second frame (which still gives decent collisions)
|
// if they are, collisionStartIdx is increased so each particle collides at least every second frame (which still gives decent collisions)
|
||||||
@@ -798,13 +798,15 @@ void ParticleSystem2D::handleCollisions() {
|
|||||||
|
|
||||||
// fill the binIndices array for this bin
|
// fill the binIndices array for this bin
|
||||||
for (uint32_t i = 0; i < usedParticles; i++) {
|
for (uint32_t i = 0; i < usedParticles; i++) {
|
||||||
if (particles[pidx].ttl > 0 && particleFlags[pidx].outofbounds == 0 && particleFlags[pidx].collide) { // colliding particle
|
if (particles[pidx].ttl > 0) { // is alive
|
||||||
if (particles[pidx].x >= binStart && particles[pidx].x <= binEnd) { // >= and <= to include particles on the edge of the bin (overlap to ensure boarder particles collide with adjacent bins)
|
if (particles[pidx].x >= binStart && particles[pidx].x <= binEnd) { // >= and <= to include particles on the edge of the bin (overlap to ensure boarder particles collide with adjacent bins)
|
||||||
if (binParticleCount >= maxBinParticles) { // bin is full, more particles in this bin so do the rest next frame
|
if(particleFlags[pidx].outofbounds == 0 && particleFlags[pidx].collide) { // particle is in frame and does collide note: checking flags is quite slow and usually these are set, so faster to check here
|
||||||
nextFrameStartIdx = pidx; // bin overflow can only happen once as bin size is at least half of the particles (or half +1)
|
if (binParticleCount >= maxBinParticles) { // bin is full, more particles in this bin so do the rest next frame
|
||||||
break;
|
nextFrameStartIdx = pidx; // bin overflow can only happen once as bin size is at least half of the particles (or half +1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
binIndices[binParticleCount++] = pidx;
|
||||||
}
|
}
|
||||||
binIndices[binParticleCount++] = pidx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pidx++;
|
pidx++;
|
||||||
@@ -834,7 +836,7 @@ void ParticleSystem2D::handleCollisions() {
|
|||||||
|
|
||||||
// handle a collision if close proximity is detected, i.e. dx and/or dy smaller than 2*PS_P_RADIUS
|
// handle a collision if close proximity is detected, i.e. dx and/or dy smaller than 2*PS_P_RADIUS
|
||||||
// takes two pointers to the particles to collide and the particle hardness (softer means more energy lost in collision, 255 means full hard)
|
// takes two pointers to the particles to collide and the particle hardness (softer means more energy lost in collision, 255 means full hard)
|
||||||
__attribute__((optimize("O2"))) void ParticleSystem2D::collideParticles(PSparticle &particle1, PSparticle &particle2, int32_t dx, int32_t dy, const int32_t collDistSq) {
|
__attribute__((optimize("O2"))) void ParticleSystem2D::collideParticles(PSparticle &particle1, PSparticle &particle2, int32_t dx, int32_t dy, const uint32_t collDistSq) {
|
||||||
int32_t distanceSquared = dx * dx + dy * dy;
|
int32_t distanceSquared = dx * dx + dy * dy;
|
||||||
// Calculate relative velocity note: could zero check but that does not improve overall speed but deminish it as that is rarely the case and pushing is still required
|
// Calculate relative velocity note: could zero check but that does not improve overall speed but deminish it as that is rarely the case and pushing is still required
|
||||||
int32_t relativeVx = (int32_t)particle2.vx - (int32_t)particle1.vx;
|
int32_t relativeVx = (int32_t)particle2.vx - (int32_t)particle1.vx;
|
||||||
@@ -1415,6 +1417,12 @@ void ParticleSystem1D::render() {
|
|||||||
CRGB baseRGB;
|
CRGB baseRGB;
|
||||||
uint32_t brightness; // particle brightness, fades if dying
|
uint32_t brightness; // particle brightness, fades if dying
|
||||||
|
|
||||||
|
#ifdef ESP8266 // no local buffer on ESP8266
|
||||||
|
if (motionBlur)
|
||||||
|
SEGMENT.fadeToBlackBy(255 - motionBlur);
|
||||||
|
else
|
||||||
|
SEGMENT.fill(BLACK); // clear the buffer before rendering to it
|
||||||
|
#else
|
||||||
if (motionBlur) { // blurring active
|
if (motionBlur) { // blurring active
|
||||||
for (int32_t x = 0; x <= maxXpixel; x++) {
|
for (int32_t x = 0; x <= maxXpixel; x++) {
|
||||||
fast_color_scale(framebuffer[x], motionBlur);
|
fast_color_scale(framebuffer[x], motionBlur);
|
||||||
@@ -1423,7 +1431,7 @@ void ParticleSystem1D::render() {
|
|||||||
else { // no blurring: clear buffer
|
else { // no blurring: clear buffer
|
||||||
memset(framebuffer, 0, (maxXpixel+1) * sizeof(CRGB));
|
memset(framebuffer, 0, (maxXpixel+1) * sizeof(CRGB));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// go over particles and render them to the buffer
|
// go over particles and render them to the buffer
|
||||||
for (uint32_t i = 0; i < usedParticles; i++) {
|
for (uint32_t i = 0; i < usedParticles; i++) {
|
||||||
if ( particles[i].ttl == 0 || particleFlags[i].outofbounds)
|
if ( particles[i].ttl == 0 || particleFlags[i].outofbounds)
|
||||||
@@ -1444,7 +1452,11 @@ void ParticleSystem1D::render() {
|
|||||||
}
|
}
|
||||||
// apply smear-blur to rendered frame
|
// apply smear-blur to rendered frame
|
||||||
if (smearBlur) {
|
if (smearBlur) {
|
||||||
|
#ifdef ESP8266
|
||||||
|
SEGMENT.blur(smearBlur, true); // no local buffer on ESP8266
|
||||||
|
#else
|
||||||
blur1D(framebuffer, maxXpixel + 1, smearBlur, 0);
|
blur1D(framebuffer, maxXpixel + 1, smearBlur, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// add background color
|
// add background color
|
||||||
@@ -1452,14 +1464,20 @@ void ParticleSystem1D::render() {
|
|||||||
if (bg_color > 0) { //if not black
|
if (bg_color > 0) { //if not black
|
||||||
CRGB bg_color_crgb = bg_color; // convert to CRGB
|
CRGB bg_color_crgb = bg_color; // convert to CRGB
|
||||||
for (int32_t i = 0; i <= maxXpixel; i++) {
|
for (int32_t i = 0; i <= maxXpixel; i++) {
|
||||||
|
#ifdef ESP8266 // no local buffer on ESP8266
|
||||||
|
SEGMENT.addPixelColor(i, bg_color, true);
|
||||||
|
#else
|
||||||
fast_color_add(framebuffer[i], bg_color_crgb);
|
fast_color_add(framebuffer[i], bg_color_crgb);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef ESP8266
|
||||||
// transfer the frame-buffer to segment
|
// transfer the frame-buffer to segment
|
||||||
for (int x = 0; x <= maxXpixel; x++) {
|
for (int x = 0; x <= maxXpixel; x++) {
|
||||||
SEGMENT.setPixelColor(x, framebuffer[x]);
|
SEGMENT.setPixelColor(x, framebuffer[x]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate pixel positions and brightness distribution and render the particle to local buffer or global buffer
|
// calculate pixel positions and brightness distribution and render the particle to local buffer or global buffer
|
||||||
@@ -1471,10 +1489,11 @@ __attribute__((optimize("O2"))) void ParticleSystem1D::renderParticle(const uint
|
|||||||
if (size == 0) { //single pixel particle, can be out of bounds as oob checking is made for 2-pixel particles (and updating it uses more code)
|
if (size == 0) { //single pixel particle, can be out of bounds as oob checking is made for 2-pixel particles (and updating it uses more code)
|
||||||
uint32_t x = particles[particleindex].x >> PS_P_RADIUS_SHIFT_1D;
|
uint32_t x = particles[particleindex].x >> PS_P_RADIUS_SHIFT_1D;
|
||||||
if (x <= (uint32_t)maxXpixel) { //by making x unsigned there is no need to check < 0 as it will overflow
|
if (x <= (uint32_t)maxXpixel) { //by making x unsigned there is no need to check < 0 as it will overflow
|
||||||
if (framebuffer)
|
#ifdef ESP8266 // no local buffer on ESP8266
|
||||||
fast_color_add(framebuffer[x], color, brightness);
|
SEGMENT.addPixelColor(x, color.scale8(brightness), true);
|
||||||
else
|
#else
|
||||||
SEGMENT.addPixelColor(x, color.scale8(brightness), true);
|
fast_color_add(framebuffer[x], color, brightness);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1536,10 +1555,11 @@ __attribute__((optimize("O2"))) void ParticleSystem1D::renderParticle(const uint
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (framebuffer)
|
#ifdef ESP8266 // no local buffer on ESP8266
|
||||||
fast_color_add(framebuffer[xfb], renderbuffer[xrb]);
|
SEGMENT.addPixelColor(xfb, renderbuffer[xrb], true);
|
||||||
else
|
#else
|
||||||
SEGMENT.addPixelColor(xfb, renderbuffer[xrb]);
|
fast_color_add(framebuffer[xfb], renderbuffer[xrb]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // standard rendering (2 pixels per particle)
|
else { // standard rendering (2 pixels per particle)
|
||||||
@@ -1558,10 +1578,11 @@ __attribute__((optimize("O2"))) void ParticleSystem1D::renderParticle(const uint
|
|||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < 2; i++) {
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
if (pxlisinframe[i]) {
|
if (pxlisinframe[i]) {
|
||||||
if (framebuffer)
|
#ifdef ESP8266 // no local buffer on ESP8266
|
||||||
fast_color_add(framebuffer[pixco[i]], color, pxlbrightness[i]);
|
SEGMENT.addPixelColor(pixco[i], color.scale8((uint8_t)pxlbrightness[i]), true);
|
||||||
else
|
#else
|
||||||
SEGMENT.addPixelColor(pixco[i], color.scale8((uint8_t)pxlbrightness[i]), true);
|
fast_color_add(framebuffer[pixco[i]], color, pxlbrightness[i]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1570,10 +1591,10 @@ __attribute__((optimize("O2"))) void ParticleSystem1D::renderParticle(const uint
|
|||||||
|
|
||||||
// detect collisions in an array of particles and handle them
|
// detect collisions in an array of particles and handle them
|
||||||
void ParticleSystem1D::handleCollisions() {
|
void ParticleSystem1D::handleCollisions() {
|
||||||
int32_t collisiondistance = particleHardRadius << 1;
|
uint32_t collisiondistance = particleHardRadius << 1;
|
||||||
// note: partices are binned by position, assumption is that no more than half of the particles are in the same bin
|
// note: partices are binned by position, assumption is that no more than half of the particles are in the same bin
|
||||||
// if they are, collisionStartIdx is increased so each particle collides at least every second frame (which still gives decent collisions)
|
// if they are, collisionStartIdx is increased so each particle collides at least every second frame (which still gives decent collisions)
|
||||||
constexpr int BIN_WIDTH = 32 * PS_P_RADIUS_1D; // width of each bin, a compromise between speed and accuracy (lareger bins are faster but collapse more)
|
constexpr int BIN_WIDTH = 32 * PS_P_RADIUS_1D; // width of each bin, a compromise between speed and accuracy (larger bins are faster but collapse more)
|
||||||
int32_t overlap = particleHardRadius << 1; // overlap bins to include edge particles to neighbouring bins
|
int32_t overlap = particleHardRadius << 1; // overlap bins to include edge particles to neighbouring bins
|
||||||
if (advPartProps) //may be using individual particle size
|
if (advPartProps) //may be using individual particle size
|
||||||
overlap += 256; // add 2 * max radius (approximately)
|
overlap += 256; // add 2 * max radius (approximately)
|
||||||
@@ -1590,13 +1611,15 @@ void ParticleSystem1D::handleCollisions() {
|
|||||||
|
|
||||||
// fill the binIndices array for this bin
|
// fill the binIndices array for this bin
|
||||||
for (uint32_t i = 0; i < usedParticles; i++) {
|
for (uint32_t i = 0; i < usedParticles; i++) {
|
||||||
if (particles[pidx].ttl > 0 && particleFlags[pidx].outofbounds == 0 && particleFlags[pidx].collide) { // colliding particle
|
if (particles[pidx].ttl > 0) { // alivee
|
||||||
if (particles[pidx].x >= binStart && particles[pidx].x <= binEnd) { // >= and <= to include particles on the edge of the bin (overlap to ensure boarder particles collide with adjacent bins)
|
if (particles[pidx].x >= binStart && particles[pidx].x <= binEnd) { // >= and <= to include particles on the edge of the bin (overlap to ensure boarder particles collide with adjacent bins)
|
||||||
if (binParticleCount >= maxBinParticles) { // bin is full, more particles in this bin so do the rest next frame
|
if(particleFlags[pidx].outofbounds == 0 && particleFlags[pidx].collide) { // particle is in frame and does collide note: checking flags is quite slow and usually these are set, so faster to check here
|
||||||
nextFrameStartIdx = pidx; // bin overflow can only happen once as bin size is at least half of the particles (or half +1)
|
if (binParticleCount >= maxBinParticles) { // bin is full, more particles in this bin so do the rest next frame
|
||||||
break;
|
nextFrameStartIdx = pidx; // bin overflow can only happen once as bin size is at least half of the particles (or half +1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
binIndices[binParticleCount++] = pidx;
|
||||||
}
|
}
|
||||||
binIndices[binParticleCount++] = pidx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pidx++;
|
pidx++;
|
||||||
@@ -1622,7 +1645,7 @@ void ParticleSystem1D::handleCollisions() {
|
|||||||
}
|
}
|
||||||
// handle a collision if close proximity is detected, i.e. dx and/or dy smaller than 2*PS_P_RADIUS
|
// handle a collision if close proximity is detected, i.e. dx and/or dy smaller than 2*PS_P_RADIUS
|
||||||
// takes two pointers to the particles to collide and the particle hardness (softer means more energy lost in collision, 255 means full hard)
|
// takes two pointers to the particles to collide and the particle hardness (softer means more energy lost in collision, 255 means full hard)
|
||||||
__attribute__((optimize("O2"))) void ParticleSystem1D::collideParticles(PSparticle1D &particle1, const PSparticleFlags1D &particle1flags, PSparticle1D &particle2, const PSparticleFlags1D &particle2flags, const int32_t dx, const uint32_t dx_abs, const int32_t collisiondistance) {
|
__attribute__((optimize("O2"))) void ParticleSystem1D::collideParticles(PSparticle1D &particle1, const PSparticleFlags1D &particle1flags, PSparticle1D &particle2, const PSparticleFlags1D &particle2flags, const int32_t dx, const uint32_t dx_abs, const uint32_t collisiondistance) {
|
||||||
int32_t dv = particle2.vx - particle1.vx;
|
int32_t dv = particle2.vx - particle1.vx;
|
||||||
int32_t dotProduct = (dx * dv); // is always negative if moving towards each other
|
int32_t dotProduct = (dx * dv); // is always negative if moving towards each other
|
||||||
|
|
||||||
@@ -1710,11 +1733,15 @@ void ParticleSystem1D::updatePSpointers(bool isadvanced) {
|
|||||||
particleFlags = reinterpret_cast<PSparticleFlags1D *>(this + 1); // pointer to particle flags
|
particleFlags = reinterpret_cast<PSparticleFlags1D *>(this + 1); // pointer to particle flags
|
||||||
particles = reinterpret_cast<PSparticle1D *>(particleFlags + numParticles); // pointer to particles
|
particles = reinterpret_cast<PSparticle1D *>(particleFlags + numParticles); // pointer to particles
|
||||||
sources = reinterpret_cast<PSsource1D *>(particles + numParticles); // pointer to source(s)
|
sources = reinterpret_cast<PSsource1D *>(particles + numParticles); // pointer to source(s)
|
||||||
|
#ifdef ESP8266 // no local buffer on ESP8266
|
||||||
|
PSdataEnd = reinterpret_cast<uint8_t *>(sources + numSources);
|
||||||
|
#else
|
||||||
framebuffer = reinterpret_cast<CRGB *>(sources + numSources); // pointer to framebuffer
|
framebuffer = reinterpret_cast<CRGB *>(sources + numSources); // pointer to framebuffer
|
||||||
// align pointer after framebuffer to 4bytes
|
// align pointer after framebuffer to 4bytes
|
||||||
uintptr_t p = reinterpret_cast<uintptr_t>(framebuffer + (maxXpixel+1));
|
uintptr_t p = reinterpret_cast<uintptr_t>(framebuffer + (maxXpixel+1));
|
||||||
p = (p + 3) & ~0x03; // align to 4-byte boundary
|
p = (p + 3) & ~0x03; // align to 4-byte boundary
|
||||||
PSdataEnd = reinterpret_cast<uint8_t *>(p); // pointer to first available byte after the PS for FX additional data
|
PSdataEnd = reinterpret_cast<uint8_t *>(p); // pointer to first available byte after the PS for FX additional data
|
||||||
|
#endif
|
||||||
if (isadvanced) {
|
if (isadvanced) {
|
||||||
advPartProps = reinterpret_cast<PSadvancedParticle1D *>(PSdataEnd);
|
advPartProps = reinterpret_cast<PSadvancedParticle1D *>(PSdataEnd);
|
||||||
PSdataEnd = reinterpret_cast<uint8_t *>(advPartProps + numParticles);
|
PSdataEnd = reinterpret_cast<uint8_t *>(advPartProps + numParticles);
|
||||||
@@ -1770,7 +1797,9 @@ bool allocateParticleSystemMemory1D(const uint32_t numparticles, const uint32_t
|
|||||||
requiredmemory += sizeof(PSparticleFlags1D) * numparticles;
|
requiredmemory += sizeof(PSparticleFlags1D) * numparticles;
|
||||||
requiredmemory += sizeof(PSparticle1D) * numparticles;
|
requiredmemory += sizeof(PSparticle1D) * numparticles;
|
||||||
requiredmemory += sizeof(PSsource1D) * numsources;
|
requiredmemory += sizeof(PSsource1D) * numsources;
|
||||||
|
#ifndef ESP8266 // no local buffer on ESP8266
|
||||||
requiredmemory += sizeof(CRGB) * SEGMENT.virtualLength();
|
requiredmemory += sizeof(CRGB) * SEGMENT.virtualLength();
|
||||||
|
#endif
|
||||||
requiredmemory += additionalbytes + 3; // add 3 to ensure room for stuffing bytes to make it 4 byte aligned
|
requiredmemory += additionalbytes + 3; // add 3 to ensure room for stuffing bytes to make it 4 byte aligned
|
||||||
if (isadvanced)
|
if (isadvanced)
|
||||||
requiredmemory += sizeof(PSadvancedParticle1D) * numparticles;
|
requiredmemory += sizeof(PSadvancedParticle1D) * numparticles;
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ private:
|
|||||||
//paricle physics applied by system if flags are set
|
//paricle physics applied by system if flags are set
|
||||||
void applyGravity(); // applies gravity to all particles
|
void applyGravity(); // applies gravity to all particles
|
||||||
void handleCollisions();
|
void handleCollisions();
|
||||||
[[gnu::hot]] void collideParticles(PSparticle &particle1, PSparticle &particle2, const int32_t dx, const int32_t dy, const int32_t collDistSq);
|
[[gnu::hot]] void collideParticles(PSparticle &particle1, PSparticle &particle2, const int32_t dx, const int32_t dy, const uint32_t collDistSq);
|
||||||
void fireParticleupdate();
|
void fireParticleupdate();
|
||||||
//utility functions
|
//utility functions
|
||||||
void updatePSpointers(const bool isadvanced, const bool sizecontrol); // update the data pointers to current segment data space
|
void updatePSpointers(const bool isadvanced, const bool sizecontrol); // update the data pointers to current segment data space
|
||||||
@@ -356,14 +356,16 @@ private:
|
|||||||
//paricle physics applied by system if flags are set
|
//paricle physics applied by system if flags are set
|
||||||
void applyGravity(); // applies gravity to all particles
|
void applyGravity(); // applies gravity to all particles
|
||||||
void handleCollisions();
|
void handleCollisions();
|
||||||
[[gnu::hot]] void collideParticles(PSparticle1D &particle1, const PSparticleFlags1D &particle1flags, PSparticle1D &particle2, const PSparticleFlags1D &particle2flags, const int32_t dx, const uint32_t dx_abs, const int32_t collisiondistance);
|
[[gnu::hot]] void collideParticles(PSparticle1D &particle1, const PSparticleFlags1D &particle1flags, PSparticle1D &particle2, const PSparticleFlags1D &particle2flags, const int32_t dx, const uint32_t dx_abs, const uint32_t collisiondistance);
|
||||||
|
|
||||||
//utility functions
|
//utility functions
|
||||||
void updatePSpointers(const bool isadvanced); // update the data pointers to current segment data space
|
void updatePSpointers(const bool isadvanced); // update the data pointers to current segment data space
|
||||||
//void updateSize(PSadvancedParticle *advprops, PSsizeControl *advsize); // advanced size control
|
//void updateSize(PSadvancedParticle *advprops, PSsizeControl *advsize); // advanced size control
|
||||||
[[gnu::hot]] void bounce(int8_t &incomingspeed, int8_t ¶llelspeed, int32_t &position, const uint32_t maxposition); // bounce on a wall
|
[[gnu::hot]] void bounce(int8_t &incomingspeed, int8_t ¶llelspeed, int32_t &position, const uint32_t maxposition); // bounce on a wall
|
||||||
// note: variables that are accessed often are 32bit for speed
|
// note: variables that are accessed often are 32bit for speed
|
||||||
|
#ifndef ESP8266
|
||||||
CRGB *framebuffer; // local frame buffer for rendering
|
CRGB *framebuffer; // local frame buffer for rendering
|
||||||
|
#endif
|
||||||
PSsettings1D particlesettings; // settings used when updating particles
|
PSsettings1D particlesettings; // settings used when updating particles
|
||||||
uint32_t numParticles; // total number of particles allocated by this system
|
uint32_t numParticles; // total number of particles allocated by this system
|
||||||
uint32_t emitIndex; // index to count through particles to emit so searching for dead pixels is faster
|
uint32_t emitIndex; // index to count through particles to emit so searching for dead pixels is faster
|
||||||
|
|||||||
Reference in New Issue
Block a user