Skip to content

Commit

Permalink
collision binning bugfix, made particles less sticky, update to water…
Browse files Browse the repository at this point in the history
…fall

- updated waterfall intensity and blurring
  • Loading branch information
DedeHai committed Jan 6, 2025
1 parent e273053 commit ffb17c3
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 7 deletions.
8 changes: 4 additions & 4 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8170,8 +8170,8 @@ uint16_t mode_particlewaterfall(void) {

PartSys->setGravity(); // enable with default gforce
PartSys->setKillOutOfBounds(true); // out of bounds particles dont return (except on top, taken care of by gravity setting)
PartSys->setMotionBlur(170); // anable motion blur
PartSys->setSmearBlur(45); // enable 2D blurring (smearing)
PartSys->setMotionBlur(180); // anable motion blur
PartSys->setSmearBlur(30); // enable 2D blurring (smearing)
for (i = 0; i < PartSys->numSources; i++) {
PartSys->sources[i].source.hue = i*90;
PartSys->sources[i].source.collide = true; // seeded particles will collide
Expand Down Expand Up @@ -8207,7 +8207,7 @@ uint16_t mode_particlewaterfall(void) {
PartSys->sources[i].source.hue += 1 + hw_random16(SEGMENT.custom1>>1); // change hue of spray source
}

if (SEGMENT.call % (9 - (SEGMENT.intensity >> 5)) == 0 && SEGMENT.intensity > 0) { // every nth frame, emit particles, do not emit if intensity is zero
if (SEGMENT.call % (12 - (SEGMENT.intensity >> 5)) == 0 && SEGMENT.intensity > 0) { // every nth frame, emit particles, do not emit if intensity is zero
for (i = 0; i < numSprays; i++) {
PartSys->sources[i].vy = -SEGMENT.speed >> 3; // emitting speed, down
//PartSys->sources[i].source.x = map(SEGMENT.custom3, 0, 31, 0, (PartSys->maxXpixel - numSprays * 2) * PS_P_RADIUS) + i * PS_P_RADIUS * 2; // emitter position
Expand All @@ -8224,7 +8224,7 @@ uint16_t mode_particlewaterfall(void) {
PartSys->update(); // update and render
return FRAMETIME;
}
static const char _data_FX_MODE_PARTICLEWATERFALL[] PROGMEM = "PS Waterfall@Speed,Intensity,Variation,Collide,Position,Cylinder,Walls,Ground;;!;2;pal=9,sx=15,ix=200,c1=32,c2=160,c3=17,o3=1";
static const char _data_FX_MODE_PARTICLEWATERFALL[] PROGMEM = "PS Waterfall@Speed,Intensity,Variation,Collide,Position,Cylinder,Walls,Ground;;!;2;pal=9,sx=15,ix=200,c1=32,c2=160,o3=1";

/*
Particle Box, applies gravity to particles in either a random direction or random but only downwards (sloshing)
Expand Down
6 changes: 3 additions & 3 deletions wled00/FXparticleSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,14 +841,15 @@ void ParticleSystem2D::renderParticle(const uint32_t particleindex, const uint32
// detect collisions in an array of particles and handle them
// uses binning by dividing the frame into slices in x direction which is efficient if using gravity in y direction (but less efficient for FX that use forces in x direction)
// 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
void ParticleSystem2D::handleCollisions() {
int32_t collDistSq = particleHardRadius << 1;
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
// if they are, collisionStartIdx is increased so each particle collides at least every second frame (which still gives decent collisions)
constexpr uint32_t BIN_WIDTH = 6 * PS_P_RADIUS; // width of a bin in sub-pixels
uint32_t maxBinParticles = (usedParticles + 1) / 2; // assume no more than half of the particles are in the same bin
uint32_t numBins = (maxX + 1) / BIN_WIDTH; // number of bins in x direction
uint32_t numBins = (maxX + (BIN_WIDTH -1)) / BIN_WIDTH; // number of bins in x direction
uint16_t binIndices[maxBinParticles]; // creat array on stack for indices, 2kB max for 1024 particles (ESP32_MAXPARTICLES/2)
uint32_t binParticleCount; // number of particles in the current bin
uint32_t nextFrameStartIdx = 0; // index of the first particle in the next frame (set if bin overflow)
Expand Down Expand Up @@ -937,8 +938,7 @@ void ParticleSystem2D::collideParticles(PSparticle *particle1, PSparticle *parti
particle2->vx -= ximpulse;
particle2->vy -= yimpulse;

// TODO: this makes them way too sticky. maybe apply friction only every x frames? could do (SEGMENT.call & 0x03) == 0 or even 0x07
if (collisionHardness < surfacehardness) { // if particles are soft, they become 'sticky' i.e. apply some friction (they do pile more nicely and stop sloshing around)
if (collisionHardness < surfacehardness && (SEGMENT.call & 0x03) == 0) { // if particles are soft, they become 'sticky' i.e. apply some friction (they do pile more nicely and stop sloshing around)
const uint32_t coeff = collisionHardness + (255 - PS_P_MINSURFACEHARDNESS); // Note: could call applyFriction, but this is faster and speed is key here
particle1->vx = ((int32_t)particle1->vx * coeff) / 255;
particle1->vy = ((int32_t)particle1->vy * coeff) / 255;
Expand Down

0 comments on commit ffb17c3

Please sign in to comment.