From 3527144b94b61ba46134e635dd05294c14980b87 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 1 May 2024 12:08:03 +0200 Subject: [PATCH] Fixed another memory / pointer bug, but there is still one left... -also some minor fixes --- wled00/FX.cpp | 22 ++++++++----- wled00/FXparticleSystem.cpp | 61 ++++++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 50c4b122cd..c0fc30c747 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -8078,9 +8078,9 @@ uint16_t mode_particlefireworks(void) numRockets = min(PartSys->numSources, (uint8_t)NUMBEROFSOURCES); for (j = 0; j < numRockets; j++) { - PartSys->sources[j].source.ttl = 500 * j; // first rocket starts immediately, others follow soon - PartSys->sources[j].source.vy = -1; // at negative speed, no particles are emitted and if rocket dies, it will be relaunched - } + PartSys->sources[j].source.ttl = 500 * j; // first rocket starts immediately, others follow soon + PartSys->sources[j].source.vy = -1; // at negative speed, no particles are emitted and if rocket dies, it will be relaunched + } } else PartSys = reinterpret_cast(SEGMENT.data); // if not first call, just set the pointer to the PS @@ -8167,6 +8167,14 @@ uint16_t mode_particlefireworks(void) } else { + /* + if( PartSys->sources[j].source.vy < 0) //explosion is ongoing + { + if(i < (emitparticles>>2)) //set 1/4 of particles to larger size + PartSys->sources[j].size = 50+random16(140); + else + PartSys->sources[j].size = 0; + }*/ PartSys->sprayEmit(PartSys->sources[j]); if ((j % 3) == 0) { @@ -8353,7 +8361,7 @@ uint16_t mode_particlefire(void) } uint32_t spread = (PartSys->maxX >> 5) * (SEGMENT.custom3 + 1); //fire around segment center (in subpixel points) - numFlames = min((uint32_t)PartSys->numSources, (1 + ((spread / PS_P_RADIUS) << 1))); // number of flames used depends on spread with, good value is (fire width in pixel) * 2 + numFlames = min((uint32_t)PartSys->numSources, (2 + ((spread / PS_P_RADIUS) << 1))); // number of flames used depends on spread with, good value is (fire width in pixel) * 2 uint32_t percycle = numFlames*2/3;// / 2; // maximum number of particles emitted per cycle (TODO: for ESP826 maybe use flames/2) // percycle = map(SEGMENT.intensity,0,255, 2, (numFlames*3) / 2); //TODO: does this give better flames or worse? @@ -8420,7 +8428,7 @@ uint16_t mode_particlefire(void) return FRAMETIME; } -static const char _data_FX_MODE_PARTICLEFIRE[] PROGMEM = "PS Fire@Speed,Intensity,Base Heat,Wind,Spread,Smooth,Cylinder,Turbulence;;!;2;pal=35,sx=110,c1=110,c2=50,o1=1"; +static const char _data_FX_MODE_PARTICLEFIRE[] PROGMEM = "PS Fire@Speed,Intensity,Base Heat,Wind,Spread,Smooth,Cylinder,Turbulence;;!;2;pal=35,sx=110,c1=110,c2=50,c3=31,o1=1"; /* PS Ballpit: particles falling down, user can enable these three options: X-wraparound, side bounce, ground bounce @@ -8791,8 +8799,8 @@ uint16_t mode_particlebox(void) xgravity = ((int16_t)inoise8(SEGMENT.aux0) - 127); ygravity = ((int16_t)inoise8(SEGMENT.aux0 + 10000) - 127); // scale the gravity force - xgravity = (xgravity * SEGMENT.custom1) / 50; - ygravity = (ygravity * SEGMENT.custom1) / 50; + xgravity = (xgravity * SEGMENT.custom1) / 128; + ygravity = (ygravity * SEGMENT.custom1) / 128; } else //go in a circle { diff --git a/wled00/FXparticleSystem.cpp b/wled00/FXparticleSystem.cpp index 57f5094ea5..05037efb9b 100644 --- a/wled00/FXparticleSystem.cpp +++ b/wled00/FXparticleSystem.cpp @@ -320,7 +320,7 @@ void ParticleSystem::particleMoveUpdate(PSparticle &part, PSsettings &options, P { if(advancedproperties->size > 0) usesize = true; //note: variable eases out of frame checking below - particleHardRadius = max(PS_P_MINHARDRADIUS, (int)particlesize + advancedproperties->size); + particleHardRadius = max(PS_P_MINHARDRADIUS, (int)particlesize + (advancedproperties->size)); } //if wall collisions are enabled, bounce them before they reach the edge, it looks much nicer if the particle is not half out of view if (options.bounceX) @@ -340,7 +340,7 @@ void ParticleSystem::particleMoveUpdate(PSparticle &part, PSsettings &options, P bool isleaving = true; if(usesize) //using individual particle size { - if (((newX > -particleHardRadius) || (newX < maxX + particleHardRadius))) // large particle is not yet leaving the view - note: this is not pixel perfect but good enough + if (((newX > -particleHardRadius) && (newX < maxX + particleHardRadius))) // large particle is not yet leaving the view - note: this is not pixel perfect but good enough isleaving = false; } @@ -719,14 +719,8 @@ void ParticleSystem::ParticleSys_render(bool firemode, uint32_t fireintensity) baseRGB = (CRGB)baseHSV; //convert back to RGB } } - - if(renderbuffer) //set buffer to zero if it exists - { - memset(renderbuffer[0], 0, 100 * sizeof(CRGB)); // renderbuffer is 10x10 pixels. note: passing the buffer and setting it zero here is faster than creating a new buffer for every particle - } - - renderParticle(framebuffer, i, brightness, baseRGB, renderbuffer); + renderParticle(framebuffer, i, brightness, baseRGB, renderbuffer); } if(particlesize > 0) @@ -793,7 +787,27 @@ void ParticleSystem::renderParticle(CRGB **framebuffer, uint32_t particleindex, if(advPartProps[particleindex].size > 0) { if(renderbuffer) - advancedrender = true; + { + advancedrender = true; + //memset(renderbuffer[0], 0, 100 * sizeof(CRGB)); //clear the buffer, renderbuffer is 10x10 pixels + //memset seems to do something bad... trying to set it manually -> was probably a bug in the access below... TODO: remove this + + for(int i = 0; i<10;i++) //this works fine but is slower + { + for(int j = 0; j<10;j++) + { + renderbuffer[i][j] = BLACK; //note: this is way slower than memset (but safer) + } + } + + //faster: the memory block is 300bytes, or 75*32bit + /* + uint32_t* datablock = reinterpret_cast(renderbuffer[0]); + for(int i = 0; i<75;i++) + { + datablock[i] = 0; //note: this is almost as fast as memset but also not safe(?) + }*/ + } else return; //cannot render without buffer, advanced size particles are allowed out of frame } @@ -871,8 +885,6 @@ void ParticleSystem::renderParticle(CRGB **framebuffer, uint32_t particleindex, if (pxlbrightness[3] >= 0) pxlbrightness[3] = (precal1 * precal3) >> PS_P_SURFACE; // top left value equal to ((PS_P_RADIUS-dx) * dy * brightess) >> PS_P_SURFACE - - if(advancedrender) { //render particle to a bigger size @@ -885,6 +897,7 @@ void ParticleSystem::renderParticle(CRGB **framebuffer, uint32_t particleindex, fast_color_add(renderbuffer[4][5], color, pxlbrightness[3]); //TODO: make this a loop somehow? needs better coordinate handling... uint32_t rendersize = 4; uint32_t offset = 3; //offset to zero coordinate to write/read data in renderbuffer + //TODO: add asymmetrical size support blur2D(renderbuffer, rendersize, rendersize, advPartProps[particleindex].size, advPartProps[particleindex].size, true, offset, offset, true); //blur to 4x4 if (advPartProps[particleindex].size > 64) { @@ -915,20 +928,26 @@ void ParticleSystem::renderParticle(CRGB **framebuffer, uint32_t particleindex, { xfb = xfb_orig + xrb; if(xfb > maxXpixel) + { if (particlesettings.wrapX) // wrap x to the other side if required xfb = xfb % (maxXpixel + 1); else continue; + } + for(uint32_t yrb = offset; yrb < rendersize+offset; yrb++) { yfb = yfb_orig + yrb; if(yfb > maxYpixel) - if (particlesettings.wrapY) // wrap y to the other side if required - yfb = yfb % (maxYpixel + 1); - else - continue; + { + if (particlesettings.wrapY) // wrap y to the other side if required + yfb = yfb % (maxYpixel + 1); + else + continue; + } + //if(xfb < maxXpixel +1 && yfb < maxYpixel +1) - fast_color_add(framebuffer[xfb][yfb], renderbuffer[xrb][yrb]); //TODO: this is just a test, need to render to correct coordinates with out of frame checking + fast_color_add(framebuffer[xfb][yfb], renderbuffer[xrb][yrb]); } } } @@ -1364,7 +1383,7 @@ int32_t ParticleSystem::limitSpeed(int32_t speed) // allocate memory for the 2D array in one contiguous block and set values to zero CRGB **ParticleSystem::allocate2Dbuffer(uint32_t cols, uint32_t rows) { - CRGB ** array2D = (CRGB **)malloc(cols * sizeof(CRGB *) + cols * rows * sizeof(CRGB)); + CRGB ** array2D = (CRGB **)calloc(cols, sizeof(CRGB *) + rows * sizeof(CRGB)); if (array2D == NULL) DEBUG_PRINT(F("PS buffer alloc failed")); else @@ -1375,7 +1394,7 @@ CRGB **ParticleSystem::allocate2Dbuffer(uint32_t cols, uint32_t rows) { array2D[i] = start + i * rows; } - memset(start, 0, cols * rows * sizeof(CRGB)); // set all values to zero + //memset(start, 0, cols * rows * sizeof(CRGB)); // set all values to zero (TODO: remove, not needed if calloc is used) } return array2D; } @@ -1405,8 +1424,8 @@ void ParticleSystem::updatePSpointers(bool isadvanced) particles = reinterpret_cast(this + 1); // pointer to particle array at data+sizeof(ParticleSystem) if(isadvanced) { - sources = reinterpret_cast(particles + numParticles); // pointer to source(s) - advPartProps = reinterpret_cast(sources + numParticles); + sources = reinterpret_cast(particles + numParticles); // pointer to source(s) + advPartProps = reinterpret_cast(sources + numParticles); } else {