Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
-removed wrap_update function, now integrated into move_update
-added more 'out of bounds' checking in fire functions, may speed it up a little
  • Loading branch information
DedeHai committed Mar 10, 2024
1 parent b99a62f commit 9c6d6f1
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 87 deletions.
6 changes: 3 additions & 3 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8503,7 +8503,7 @@ uint16_t mode_particlefire(void)
// add wind, using perlin noise
int8_t windspeed = (int8_t)(inoise8(SEGMENT.aux0, particles[i].y >> 2) - 127) / ((271 - SEGMENT.custom2) >> 4);
particles[i].vx = windspeed;
FireParticle_update(&particles[i], SEGMENT.check1, false); // update particle, use X-wrapping if check 1 is set by user
FireParticle_update(&particles[i], SEGMENT.check1); // update particle, use X-wrapping if check 1 is set by user
}
}

Expand Down Expand Up @@ -9441,8 +9441,8 @@ uint16_t mode_particlespray(void)
Particle_Gravity_update(&particles[i], SEGMENT.check2, SEGMENT.check2 == 0, true, hardness);
else //bounce particles
{
if(SEGMENT.check2) //wrap x
Particle_Wrap_update(&particles[i], true, false);
if(SEGMENT.check2) //wrap x
Particle_Move_update(&particles[i], true, true, false);
else //bounce
Particle_Bounce_update(&particles[i], hardness);
}
Expand Down
125 changes: 44 additions & 81 deletions wled00/FXparticleSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void Particle_attractor(PSparticle *particle, PSparticle *attractor, uint8_t *co
}

// particle moves, decays and dies, if killoutofbounds is set, out of bounds particles are set to ttl=0
void Particle_Move_update(PSparticle *part, bool killoutofbounds)
void Particle_Move_update(PSparticle *part, bool killoutofbounds, bool wrapX, bool wrapY)
{
// Matrix dimension
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
Expand All @@ -182,21 +182,42 @@ void Particle_Move_update(PSparticle *part, bool killoutofbounds)

part->outofbounds = 0; // reset out of bounds (in case particle was created outside the matrix and is now moving into view)

// check if particle is out of bounds
if ((part->y <= 0) || (part->y >= PS_MAX_Y))
// apply velocity
int32_t newX, newY;
newX = part->x + (int16_t)part->vx;
newY = part->y + (int16_t)part->vy;

part->outofbounds = 0; // reset out of bounds (in case particle was created outside the matrix and is now moving into view)
// x direction, handle wraparound
if (wrapX)
{
newX = newX % (PS_MAX_X + 1);
if (newX < 0)
newX = PS_MAX_X - newX;
}
else if ((part->x <= 0) || (part->x >= PS_MAX_X)) // check if particle is out of bounds
{
if (killoutofbounds)
part->ttl = 0;
else
part->outofbounds = 1;
}
if ((part->x <= 0) || (part->x >= PS_MAX_X))
part->x = newX; // set new position

if (wrapY)
{
newY = newY % (PS_MAX_Y + 1);
if (newY < 0)
newY = PS_MAX_Y - newY;
}
else if ((part->y <= 0) || (part->y >= PS_MAX_Y)) // check if particle is out of bounds
{
if(killoutofbounds)
if (killoutofbounds)
part->ttl = 0;
else
part->outofbounds = 1;
}
part->y = newY; // set new position
}

}
Expand Down Expand Up @@ -246,57 +267,6 @@ void Particle_Bounce_update(PSparticle *part, const uint8_t hardness)

}

// particle moves, decays and dies (age or out of matrix), if wrap is set, pixels leaving the matrix reappear on other side
//TODO: this is just move update with wrap, could make one function out of it
void Particle_Wrap_update(PSparticle *part, bool wrapX, bool wrapY)
{
// Matrix dimension
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength();

// particle box dimensions
const uint16_t PS_MAX_X(cols * PS_P_RADIUS - 1);
const uint16_t PS_MAX_Y(rows * PS_P_RADIUS - 1);

if (part->ttl > 0)
{
// age
part->ttl--;

// apply velocity
int32_t newX, newY;
newX = part->x + (int16_t)part->vx;
newY = part->y + (int16_t)part->vy;

part->outofbounds = 0; // reset out of bounds (in case particle was created outside the matrix and is now moving into view)
// x direction, handle wraparound
if (wrapX)
{
newX = newX % (PS_MAX_X + 1);
if (newX < 0)
newX = PS_MAX_X - newX;
}
else if ((part->x <= 0) || (part->x >= PS_MAX_X)) // check if particle is out of bounds
{
part->outofbounds = 1;
}
part->x = newX; // set new position

if (wrapY)
{
newY = newY % (PS_MAX_Y + 1);
if (newY < 0)
newY = PS_MAX_Y - newY;
}
else if ((part->y <= 0) || (part->y >= PS_MAX_Y)) // check if particle is out of bounds
{
part->outofbounds = 1;
}
part->y = newY; // set new position
}

}

// particle moves, gravity force is applied and ages, if wrapX is set, pixels leaving in x direction reappear on other side, hardness is surface hardness for bouncing (127 means 50% speed lost each bounce)
void Particle_Gravity_update(PSparticle *part, bool wrapX, bool bounceX, bool bounceY, const uint8_t hardness)
{
Expand Down Expand Up @@ -534,7 +504,7 @@ void ParticleSys_render(PSparticle *particles, uint32_t numParticles, bool wrapX

// update & move particle, wraps around left/right if wrapX is true, wrap around up/down if wrapY is true
// particles move upwards faster if ttl is high (i.e. they are hotter)
void FireParticle_update(PSparticle *part, bool wrapX, bool wrapY)
void FireParticle_update(PSparticle *part, bool wrapX)
{
// Matrix dimension
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
Expand All @@ -551,8 +521,9 @@ void FireParticle_update(PSparticle *part, bool wrapX, bool wrapY)

// apply velocity
part->x = part->x + (int16_t)part->vx;
part->y = part->y + (int16_t)part->vy + (part->ttl >> 4); // younger particles move faster upward as they are hotter, used for fire //TODO: need to make this optional?
part->y = part->y + (int16_t)part->vy + (part->ttl >> 4); // younger particles move faster upward as they are hotter, used for fire

part->outofbounds = 0;
// check if particle is out of bounds, wrap around to other side if wrapping is enabled
// x-direction
if ((part->x < 0) || (part->x > PS_MAX_X))
Expand All @@ -565,23 +536,18 @@ void FireParticle_update(PSparticle *part, bool wrapX, bool wrapY)
}
else
{
part->ttl = 0; // todo: for round flame display, particles need to go modulo
part->ttl = 0;
}
}

// y-direction
if ((part->y < -(PS_P_RADIUS << 4)) || (part->y > PS_MAX_Y))
{ // position up to 8 pixels the matrix is allowed, used in fire for wider flames
if (wrapY)
{
part->y = part->y % (PS_MAX_Y + 1);
if (part->y < 0)
part->y = PS_MAX_Y - part->y;
}
else
{
part->ttl = 0; // todo: for round flame display, particles need to go modulo
}
{ // position up to 8 pixels below the matrix is allowed, used for wider flames at the bottom
part->ttl = 0;
}
else if (part->y < 0)
{
part->outofbounds = 1;
}
}
}
Expand All @@ -594,23 +560,20 @@ void ParticleSys_renderParticleFire(PSparticle *particles, uint32_t numParticles
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength();


int32_t x, y;
uint8_t dx, dy;
uint32_t tempVal;
uint32_t i;

// go over particles and update matrix cells on the way
// note: some pixels (the x+1 ones) can be out of bounds, it is probably faster than to check that for every pixel as this only happens on the right border (and nothing bad happens as this is checked down the road)
for (i = 0; i < numParticles; i++)
{
if (particles[i].ttl == 0)
if (particles[i].ttl == 0 || particles[i].outofbounds)
{
continue;
}

//TODO: no more using simple particles, can use the out of bounds here

// simple particles do not have 'out of bound' parameter, need to check if particle is within matrix boundaries
dx = (uint8_t)((uint16_t)particles[i].x % (uint16_t)PS_P_RADIUS);
dy = (uint8_t)((uint16_t)particles[i].y % (uint16_t)PS_P_RADIUS);

Expand Down Expand Up @@ -639,8 +602,8 @@ void ParticleSys_renderParticleFire(PSparticle *particles, uint32_t numParticles
dy = dy - (PS_P_RADIUS >> 1);
}

if (wrapX)
{ // wrap it to the other side if required
if (wrapX)
{
if (x < 0)
{ // left half of particle render is out of frame, wrap it
x = cols - 1;
Expand All @@ -649,7 +612,7 @@ void ParticleSys_renderParticleFire(PSparticle *particles, uint32_t numParticles

// calculate brightness values for all six pixels representing a particle using linear interpolation
// bottom left
if (x < cols && y < rows)
if (x < cols && x >=0 && y < rows && y >=0)
{
tempVal = (((uint32_t)((PS_P_RADIUS)-dx) * ((PS_P_RADIUS)-dy) * (uint32_t)particles[i].ttl) >> PS_P_SURFACE);
PartMatrix_addHeat(x, y, tempVal);
Expand All @@ -662,7 +625,7 @@ void ParticleSys_renderParticleFire(PSparticle *particles, uint32_t numParticles
if (x >= cols)
x = x % cols; // in case the right half of particle render is out of frame, wrap it (note: on microcontrollers with hardware division, the if statement is not really needed)
}
if (x < cols && y < rows)
if (x < cols && y < rows && y >= 0)
{
tempVal = (((uint32_t)dx * ((PS_P_RADIUS)-dy) * (uint32_t)particles[i].ttl) >> PS_P_SURFACE);
PartMatrix_addHeat(x, y, tempVal);
Expand All @@ -673,7 +636,7 @@ void ParticleSys_renderParticleFire(PSparticle *particles, uint32_t numParticles
if (x < cols && y < rows)
{
tempVal = (((uint32_t)dx * dy * (uint32_t)particles[i].ttl) >> PS_P_SURFACE); //
PartMatrix_addHeat(x, y, tempVal);
PartMatrix_addHeat(x, y, tempVal);
PartMatrix_addHeat(x + 1, y, tempVal); // shift particle by 1 pixel to the right and add heat again (makes flame wider without using more particles)
}
// top left
Expand All @@ -685,7 +648,7 @@ void ParticleSys_renderParticleFire(PSparticle *particles, uint32_t numParticles
x = cols - 1;
}
}
if (x < cols && y < rows)
if (x < cols && x >= 0 && y < rows)
{
tempVal = (((uint32_t)((PS_P_RADIUS)-dx) * dy * (uint32_t)particles[i].ttl) >> PS_P_SURFACE);
PartMatrix_addHeat(x, y, tempVal);
Expand Down
5 changes: 2 additions & 3 deletions wled00/FXparticleSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,11 @@ void Emitter_Flame_emit(PSpointsource *emitter, PSparticle *part);
void Emitter_Fountain_emit(PSpointsource *emitter, PSparticle *part);
void Emitter_Angle_emit(PSpointsource *emitter, PSparticle *part, uint8_t angle, uint8_t speed);
void Particle_attractor(PSparticle *particle, PSparticle *attractor, uint8_t *counter, uint8_t strength, bool swallow);
void Particle_Move_update(PSparticle *part, bool killoutofbounds = false);
void Particle_Move_update(PSparticle *part, bool killoutofbounds = false, bool wrapX = false, bool wrapY = false);
void Particle_Bounce_update(PSparticle *part, const uint8_t hardness);
void Particle_Wrap_update(PSparticle *part, bool wrapX, bool wrapY);
void Particle_Gravity_update(PSparticle *part, bool wrapX, bool bounceX, bool bounceY, const uint8_t hardness);
void ParticleSys_render(PSparticle *particles, uint32_t numParticles, bool wrapX, bool wrapY);
void FireParticle_update(PSparticle *part, bool wrapX = false, bool WrapY = false);
void FireParticle_update(PSparticle *part, bool wrapX = false);
void ParticleSys_renderParticleFire(PSparticle *particles, uint32_t numParticles, bool wrapX);
void PartMatrix_addHeat(uint8_t col, uint8_t row, uint16_t heat);
void detectCollisions(PSparticle *particles, uint32_t numparticles, uint8_t hardness);
Expand Down

0 comments on commit 9c6d6f1

Please sign in to comment.