From 50082043ef4c3870446df7ce0ead46c6532201c1 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Fri, 27 Dec 2019 20:58:06 +0100 Subject: [PATCH 1/5] add exploding fireworks --- wled00/FX.cpp | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 12 +++-- 2 files changed, 131 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c862a085..207ce1ff 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2348,3 +2348,125 @@ uint16_t WS2812FX::mode_candle() return FRAMETIME; } + + +/* + * Exploding fireworks effect + * adapted from: http://www.anirama.com/1000leds/1d-fireworks/ + */ +#define NUM_SPARKS 60 // max number (could be NUM_LEDS / 2); +uint16_t WS2812FX::mode_exploding_fireworks(void) +{ + if (SEGENV.aux1==0) { // manage states using params + flare(); + } else { + explode(); + } + + return FRAMETIME; +} + +static float sparkPos[NUM_SPARKS]; +static float sparkVel[NUM_SPARKS]; +static float sparkCol[NUM_SPARKS]; +static float flarePos; +static float flareVel; +static float brightness; + +void WS2812FX::flare() { + float gravity = -0.02 - (SEGMENT.speed/10000.0); // m/s/s + + if (SEGENV.aux0 == 0) { //use aux0 for initialization flag + flarePos = 0; + flareVel = float(random16(150, 190)) / (75+SEGMENT.intensity/4); // trial and error to get reasonable range + brightness = 1; +Serial.printf("%3.1f %3.3f %3d",flareVel,gravity,SEGMENT.intensity); +Serial.println(""); + // initialize launch sparks + for (int i = 0; i < 5; i++) { + sparkPos[i] = 0; + sparkVel[i] = (float(random8(100,255)) / 255.0) * (flareVel/ 3.0); // random around 20% of flare velocity + sparkCol[i] = sparkVel[i] * 1000.0; + sparkCol[i] = constrain(sparkCol[i], 0, 255); + } + SEGENV.aux0=1; + } + + // launch + if (flareVel >= -.3) { + // sparks + for (int i = 0; i < 5; i++) { + sparkPos[i] += sparkVel[i]; + sparkPos[i] = constrain(sparkPos[i], 0, SEGLEN-1); + sparkVel[i] += gravity; + sparkCol[i] += -.8; + sparkCol[i] = constrain(sparkCol[i], 0, 255); + + CRGB color = HeatColor(sparkCol[i]); + setPixelColor(SEGMENT.stop - int(sparkPos[i]),color.red,color.green,color.blue); + } + // flare + fade_out(255); + setPixelColor(SEGMENT.stop - int(flarePos),brightness*255,brightness*255,brightness*255); + + flarePos += flareVel; + flarePos = constrain(flarePos, 0, SEGLEN-1); + flareVel += gravity; + brightness *= .975; + } else { + SEGENV.aux0=0; // allow next state to init + SEGENV.aux1=1; // ready to explode + } +} + +/* + * Explode! + * + * Explosion happens where the flare ended. + * Size is proportional to the height. + */ +void WS2812FX::explode() { + int nSparks = flarePos / 2; // works out to look about right + nSparks = constrain(nSparks,0,NUM_SPARKS); + static float dying_gravity; + float gravity = -0.02 - (SEGMENT.speed/10000.0); + float c1=120; + float c2=50; + + // initialize sparks + if (SEGENV.aux0==0) { + for (int i = 0; i < nSparks; i++) { + sparkPos[i] = flarePos; + sparkVel[i] = (float(random16(0, 20000)) / 10000.0) - 1.0; // from -1 to 1 + sparkCol[i] = abs(sparkVel[i] * 500.0); // set colors before scaling velocity to keep them bright + sparkCol[i] = constrain(sparkCol[i], 0, 255); + sparkVel[i] *= flarePos / SEGLEN; // proportional to height + } + sparkCol[0] = 255; // this will be our known spark + dying_gravity = gravity; + SEGENV.aux0=1; + } + + if (sparkCol[0] > c2/10 ) {//&& sparkPos[0] > 0) { // as long as our known spark is lit, work with all the sparks + fade_out(255); + for (int i = 0; i < nSparks; i++) { + sparkPos[i] += sparkVel[i]; + sparkPos[i] = constrain(sparkPos[i], 0, SEGLEN-1); + sparkVel[i] += dying_gravity; + sparkCol[i] *= .97; + sparkCol[i] = constrain(sparkCol[i], 0, 255); // red cross dissolve + + if(sparkCol[i] > c1) { // fade white to yellow + setPixelColor(SEGMENT.stop - sparkPos[i],255, 255, (255 * (sparkCol[i] - c1)) / (255 - c1)); + } else if (sparkCol[i] < c2) { // fade from red to black + setPixelColor(SEGMENT.stop - sparkPos[i],(255 * sparkCol[i]) / c2, 0, 0); + } else { // fade from yellow to red + setPixelColor(SEGMENT.stop - sparkPos[i],255, (255 * (sparkCol[i] - c2)) / (c1 - c2), 0); + } + } + dying_gravity *= .995; // as sparks burn out they fall slower + } else { + SEGENV.aux0=0; + SEGENV.aux1=0; + } +} \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 9ba70357..7fa1a848 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 89 +#define MODE_COUNT 90 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -175,6 +175,7 @@ #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_GLITTER 87 #define FX_MODE_CANDLE 88 +#define FX_MODE_EXPLODING_FIREWORKS 89 class WS2812FX { @@ -321,6 +322,8 @@ class WS2812FX { _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; _mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter; _mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle; + _mode[FX_MODE_EXPLODING_FIREWORKS] = &WS2812FX::mode_exploding_fireworks; + _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -359,6 +362,8 @@ class WS2812FX { resetSegments(), setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), + flare(void), + explode(void), show(void); bool @@ -503,7 +508,8 @@ class WS2812FX { mode_spots(void), mode_spots_fade(void), mode_glitter(void), - mode_candle(void); + mode_candle(void), + mode_exploding_fireworks(void); private: @@ -577,7 +583,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks 1D" ])====="; From ce5839ce27d5e7a6cd5deaeeb8e0dd5ad888fc60 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Fri, 27 Dec 2019 22:20:34 +0100 Subject: [PATCH 2/5] remove debug message --- wled00/FX.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 207ce1ff..af0974b0 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2380,8 +2380,7 @@ void WS2812FX::flare() { flarePos = 0; flareVel = float(random16(150, 190)) / (75+SEGMENT.intensity/4); // trial and error to get reasonable range brightness = 1; -Serial.printf("%3.1f %3.3f %3d",flareVel,gravity,SEGMENT.intensity); -Serial.println(""); + // initialize launch sparks for (int i = 0; i < 5; i++) { sparkPos[i] = 0; From eb251050a526b00cde387fdbe9696fbd8f747a7f Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Mon, 30 Dec 2019 00:22:28 +0100 Subject: [PATCH 3/5] fix exploding firworks controls to match the slider direction to the effect --- wled00/FX.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index af0974b0..7e920352 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2378,7 +2378,7 @@ void WS2812FX::flare() { if (SEGENV.aux0 == 0) { //use aux0 for initialization flag flarePos = 0; - flareVel = float(random16(150, 190)) / (75+SEGMENT.intensity/4); // trial and error to get reasonable range + flareVel = float(random16(150, 190)) / (75+(255-SEGMENT.intensity)/4); // trial and error to get reasonable range brightness = 1; // initialize launch sparks @@ -2428,10 +2428,10 @@ void WS2812FX::explode() { int nSparks = flarePos / 2; // works out to look about right nSparks = constrain(nSparks,0,NUM_SPARKS); static float dying_gravity; - float gravity = -0.02 - (SEGMENT.speed/10000.0); + float gravity = -0.02 - ((255-SEGMENT.speed)/10000.0); float c1=120; float c2=50; - + // initialize sparks if (SEGENV.aux0==0) { for (int i = 0; i < nSparks; i++) { From cdef7a53a43c5c223539f85de010dc01a4e26407 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Fri, 3 Jan 2020 17:47:06 +0100 Subject: [PATCH 4/5] Fireworks 1D working --- wled00/FX.cpp | 224 +++++++++++++++++++++++++------------------------- wled00/FX.h | 2 - 2 files changed, 114 insertions(+), 112 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c93f8305..6051a155 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2605,118 +2605,122 @@ uint16_t WS2812FX::mode_starburst(void) { * Exploding fireworks effect * adapted from: http://www.anirama.com/1000leds/1d-fireworks/ */ -#define NUM_SPARKS 60 // max number (could be NUM_LEDS / 2); + +//each needs 12 byte +typedef struct Spark { + float pos; + float vel; + float col; +} spark; + uint16_t WS2812FX::mode_exploding_fireworks(void) { - if (SEGENV.aux1==0) { // manage states using params - flare(); - } else { - explode(); - } + //allocate segment data + uint16_t numSparks = 2 + (SEGLEN >> 1); + if (numSparks > 80) numSparks = 80; + uint16_t dataSize = sizeof(spark) * numSparks; + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + fill(BLACK); + + Spark* sparks = reinterpret_cast(SEGENV.data); + Spark* flare = sparks; //first spark is flare data + + float gravity = -0.02 - (SEGMENT.speed/10000.0); // m/s/s + + if (SEGENV.aux1 == 0) { //FLARE + if (SEGENV.aux0 == 0) { //init flare + flare->pos = 0; + flare->vel = float(random16(150, 190)) / (75+(255-SEGMENT.intensity)/4); // trial and error to get reasonable range + //flare->vel = 2; + flare->col = 1; //brightness + + // initialize launch sparks + for (int i = 1; i < min(6, numSparks); i++) { + sparks[i].pos = 0; + sparks[i].vel = (float(random8(100,255)) / 255.0) * (flare->vel/ 3.0); // random around 20% of flare velocity + sparks[i].col = sparks[i].vel * 1000.0; + sparks[i].col = constrain(sparks[i].col, 0, 255); + } + SEGENV.aux0 = 1; + } + + // launch + if (flare->vel > -.3) { + // sparks + for (int i = 1; i < min(6, numSparks); i++) { + sparks[i].pos += sparks[i].vel; + sparks[i].pos = constrain(sparks[i].pos, 0, SEGLEN-1); + sparks[i].vel += gravity; + sparks[i].col -= 0.8; + sparks[i].col = constrain(sparks[i].col, 0, 255); + + CRGB color = HeatColor(sparks[i].col); + setPixelColor(SEGMENT.start + int(sparks[i].pos),color.red,color.green,color.blue); + } + // flare + //fade_out(255); + setPixelColor(SEGMENT.start + int(flare->pos),flare->col*255,flare->col*255,flare->col*255); + + flare->pos += flare->vel; + flare->pos = constrain(flare->pos, 0, SEGLEN-1); + flare->vel += gravity; + flare->col *= .975; + } else { + SEGENV.aux0 = 0; // allow next state to init + SEGENV.aux1 = 1; // ready to explode + } + } else { + /* + * Explode! + * + * Explosion happens where the flare ended. + * Size is proportional to the height. + */ + int nSparks = flare->pos / 2; // works out to look about right + nSparks = constrain(nSparks, 0, numSparks); + static float dying_gravity; + //gravity = -0.02 - ((255-SEGMENT.speed)/10000.0); + + // initialize sparks + if (SEGENV.aux0==0) { + for (int i = 1; i < nSparks; i++) { + sparks[i].pos = flare->pos; + sparks[i].vel = (float(random16(0, 20000)) / 10000.0) - 1.0; // from -1 to 1 + sparks[i].col = abs(sparks[i].vel * 500.0); // set colors before scaling velocity to keep them bright + sparks[i].col = constrain(sparks[i].col, 0, 255); + sparks[i].vel *= flare->pos / SEGLEN; // proportional to height + } + sparks[1].col = 255; // this will be our known spark + dying_gravity = gravity; + SEGENV.aux0 = 1; + } + + float c1 = 120; + float c2 = 50; + + if (sparks[1].col > 5) {//&& sparks[1].pos > 0) { // as long as our known spark is lit, work with all the sparks + //fade_out(255); + for (int i = 1; i < nSparks; i++) { + sparks[i].pos += sparks[i].vel; + sparks[i].pos = constrain(sparks[i].pos, 0, SEGLEN-1); + sparks[i].vel += dying_gravity; + sparks[i].col *= .97; + sparks[i].col = constrain(sparks[i].col, 0, 255); // red cross dissolve + + if(sparks[i].pos > c1) { // fade white to yellow + setPixelColor(SEGMENT.start + sparks[i].pos,255, 255, (255 * (sparks[i].col - c1)) / (255 - c1)); + } else if (sparks[i].col < c2) { // fade from red to black + setPixelColor(SEGMENT.start + sparks[i].pos,(255 * sparks[i].col) / c2, 0, 0); + } else { // fade from yellow to red + setPixelColor(SEGMENT.start + sparks[i].pos,255, (255 * (sparks[i].col - c2)) / (c1 - c2), 0); + } + } + dying_gravity *= .995; // as sparks burn out they fall slower + } else { + SEGENV.aux0 = 0; //init again + SEGENV.aux1 = 0; //back to flare + } + } return FRAMETIME; } - -static float sparkPos[NUM_SPARKS]; -static float sparkVel[NUM_SPARKS]; -static float sparkCol[NUM_SPARKS]; -static float flarePos; -static float flareVel; -static float brightness; - -void WS2812FX::flare() { - float gravity = -0.02 - (SEGMENT.speed/10000.0); // m/s/s - - if (SEGENV.aux0 == 0) { //use aux0 for initialization flag - flarePos = 0; - flareVel = float(random16(150, 190)) / (75+(255-SEGMENT.intensity)/4); // trial and error to get reasonable range - brightness = 1; - - // initialize launch sparks - for (int i = 0; i < 5; i++) { - sparkPos[i] = 0; - sparkVel[i] = (float(random8(100,255)) / 255.0) * (flareVel/ 3.0); // random around 20% of flare velocity - sparkCol[i] = sparkVel[i] * 1000.0; - sparkCol[i] = constrain(sparkCol[i], 0, 255); - } - SEGENV.aux0=1; - } - - // launch - if (flareVel >= -.3) { - // sparks - for (int i = 0; i < 5; i++) { - sparkPos[i] += sparkVel[i]; - sparkPos[i] = constrain(sparkPos[i], 0, SEGLEN-1); - sparkVel[i] += gravity; - sparkCol[i] += -.8; - sparkCol[i] = constrain(sparkCol[i], 0, 255); - - CRGB color = HeatColor(sparkCol[i]); - setPixelColor(SEGMENT.stop - int(sparkPos[i]),color.red,color.green,color.blue); - } - // flare - fade_out(255); - setPixelColor(SEGMENT.stop - int(flarePos),brightness*255,brightness*255,brightness*255); - - flarePos += flareVel; - flarePos = constrain(flarePos, 0, SEGLEN-1); - flareVel += gravity; - brightness *= .975; - } else { - SEGENV.aux0=0; // allow next state to init - SEGENV.aux1=1; // ready to explode - } -} - -/* - * Explode! - * - * Explosion happens where the flare ended. - * Size is proportional to the height. - */ -void WS2812FX::explode() { - int nSparks = flarePos / 2; // works out to look about right - nSparks = constrain(nSparks,0,NUM_SPARKS); - static float dying_gravity; - float gravity = -0.02 - ((255-SEGMENT.speed)/10000.0); - float c1=120; - float c2=50; - - // initialize sparks - if (SEGENV.aux0==0) { - for (int i = 0; i < nSparks; i++) { - sparkPos[i] = flarePos; - sparkVel[i] = (float(random16(0, 20000)) / 10000.0) - 1.0; // from -1 to 1 - sparkCol[i] = abs(sparkVel[i] * 500.0); // set colors before scaling velocity to keep them bright - sparkCol[i] = constrain(sparkCol[i], 0, 255); - sparkVel[i] *= flarePos / SEGLEN; // proportional to height - } - sparkCol[0] = 255; // this will be our known spark - dying_gravity = gravity; - SEGENV.aux0=1; - } - - if (sparkCol[0] > c2/10 ) {//&& sparkPos[0] > 0) { // as long as our known spark is lit, work with all the sparks - fade_out(255); - for (int i = 0; i < nSparks; i++) { - sparkPos[i] += sparkVel[i]; - sparkPos[i] = constrain(sparkPos[i], 0, SEGLEN-1); - sparkVel[i] += dying_gravity; - sparkCol[i] *= .97; - sparkCol[i] = constrain(sparkCol[i], 0, 255); // red cross dissolve - - if(sparkCol[i] > c1) { // fade white to yellow - setPixelColor(SEGMENT.stop - sparkPos[i],255, 255, (255 * (sparkCol[i] - c1)) / (255 - c1)); - } else if (sparkCol[i] < c2) { // fade from red to black - setPixelColor(SEGMENT.stop - sparkPos[i],(255 * sparkCol[i]) / c2, 0, 0); - } else { // fade from yellow to red - setPixelColor(SEGMENT.stop - sparkPos[i],255, (255 * (sparkCol[i] - c2)) / (c1 - c2), 0); - } - } - dying_gravity *= .995; // as sparks burn out they fall slower - } else { - SEGENV.aux0=0; - SEGENV.aux1=0; - } -} diff --git a/wled00/FX.h b/wled00/FX.h index 824e0bef..0b2d21af 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -386,8 +386,6 @@ class WS2812FX { resetSegments(), setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), - flare(void), - explode(void), show(void); bool From 5c7d993dbea2c532f08eebf50d88d23edea29bb8 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Fri, 3 Jan 2020 22:56:56 +0100 Subject: [PATCH 5/5] Numerous improvements to 1D FW --- wled00/FX.cpp | 117 ++++++++++++++++++++++------------------------ wled00/wled00.ino | 2 +- 2 files changed, 58 insertions(+), 61 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 6051a155..e1af8338 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2610,7 +2610,8 @@ uint16_t WS2812FX::mode_starburst(void) { typedef struct Spark { float pos; float vel; - float col; + uint16_t col; + uint8_t colIndex; } spark; uint16_t WS2812FX::mode_exploding_fireworks(void) @@ -2623,104 +2624,100 @@ uint16_t WS2812FX::mode_exploding_fireworks(void) fill(BLACK); + bool actuallyReverse = SEGMENT.getOption(1); + //have fireworks start in either direction based on intensity + SEGMENT.setOption(1, SEGENV.step); + Spark* sparks = reinterpret_cast(SEGENV.data); Spark* flare = sparks; //first spark is flare data - float gravity = -0.02 - (SEGMENT.speed/10000.0); // m/s/s + float gravity = -0.0004 - (SEGMENT.speed/800000.0); // m/s/s + gravity *= SEGLEN; - if (SEGENV.aux1 == 0) { //FLARE + if (SEGENV.aux0 < 2) { //FLARE if (SEGENV.aux0 == 0) { //init flare flare->pos = 0; - flare->vel = float(random16(150, 190)) / (75+(255-SEGMENT.intensity)/4); // trial and error to get reasonable range - //flare->vel = 2; - flare->col = 1; //brightness - - // initialize launch sparks - for (int i = 1; i < min(6, numSparks); i++) { - sparks[i].pos = 0; - sparks[i].vel = (float(random8(100,255)) / 255.0) * (flare->vel/ 3.0); // random around 20% of flare velocity - sparks[i].col = sparks[i].vel * 1000.0; - sparks[i].col = constrain(sparks[i].col, 0, 255); - } + uint16_t peakHeight = 75 + random8(180); //0-255 + peakHeight = (peakHeight * (SEGLEN -1)) >> 8; + flare->vel = sqrt(-2.0 * gravity * peakHeight); + flare->col = 255; //brightness + SEGENV.aux0 = 1; } // launch - if (flare->vel > -.3) { - // sparks - for (int i = 1; i < min(6, numSparks); i++) { - sparks[i].pos += sparks[i].vel; - sparks[i].pos = constrain(sparks[i].pos, 0, SEGLEN-1); - sparks[i].vel += gravity; - sparks[i].col -= 0.8; - sparks[i].col = constrain(sparks[i].col, 0, 255); - - CRGB color = HeatColor(sparks[i].col); - setPixelColor(SEGMENT.start + int(sparks[i].pos),color.red,color.green,color.blue); - } + if (flare->vel > 12 * gravity) { // flare - //fade_out(255); - setPixelColor(SEGMENT.start + int(flare->pos),flare->col*255,flare->col*255,flare->col*255); + setPixelColor(SEGMENT.start + int(flare->pos),flare->col,flare->col,flare->col); flare->pos += flare->vel; flare->pos = constrain(flare->pos, 0, SEGLEN-1); flare->vel += gravity; - flare->col *= .975; + flare->col -= 2; } else { - SEGENV.aux0 = 0; // allow next state to init - SEGENV.aux1 = 1; // ready to explode + SEGENV.aux0 = 2; // ready to explode } - } else { + } else if (SEGENV.aux0 < 4) { /* * Explode! * * Explosion happens where the flare ended. * Size is proportional to the height. */ - int nSparks = flare->pos / 2; // works out to look about right + int nSparks = flare->pos; nSparks = constrain(nSparks, 0, numSparks); static float dying_gravity; - //gravity = -0.02 - ((255-SEGMENT.speed)/10000.0); // initialize sparks - if (SEGENV.aux0==0) { + if (SEGENV.aux0 == 2) { for (int i = 1; i < nSparks; i++) { sparks[i].pos = flare->pos; - sparks[i].vel = (float(random16(0, 20000)) / 10000.0) - 1.0; // from -1 to 1 - sparks[i].col = abs(sparks[i].vel * 500.0); // set colors before scaling velocity to keep them bright - sparks[i].col = constrain(sparks[i].col, 0, 255); - sparks[i].vel *= flare->pos / SEGLEN; // proportional to height + sparks[i].vel = (float(random16(0, 20000)) / 10000.0) - 0.9; // from -0.9 to 1.1 + sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright + //sparks[i].col = constrain(sparks[i].col, 0, 345); + sparks[i].colIndex = random8(); + sparks[i].vel *= flare->pos/SEGLEN; // proportional to height + sparks[i].vel *= -gravity *50; } - sparks[1].col = 255; // this will be our known spark - dying_gravity = gravity; - SEGENV.aux0 = 1; + //sparks[1].col = 345; // this will be our known spark + dying_gravity = gravity/2; + SEGENV.aux0 = 3; } - - float c1 = 120; - float c2 = 50; - if (sparks[1].col > 5) {//&& sparks[1].pos > 0) { // as long as our known spark is lit, work with all the sparks - //fade_out(255); + if (sparks[1].col > 4) {//&& sparks[1].pos > 0) { // as long as our known spark is lit, work with all the sparks for (int i = 1; i < nSparks; i++) { sparks[i].pos += sparks[i].vel; - sparks[i].pos = constrain(sparks[i].pos, 0, SEGLEN-1); sparks[i].vel += dying_gravity; - sparks[i].col *= .97; - sparks[i].col = constrain(sparks[i].col, 0, 255); // red cross dissolve - - if(sparks[i].pos > c1) { // fade white to yellow - setPixelColor(SEGMENT.start + sparks[i].pos,255, 255, (255 * (sparks[i].col - c1)) / (255 - c1)); - } else if (sparks[i].col < c2) { // fade from red to black - setPixelColor(SEGMENT.start + sparks[i].pos,(255 * sparks[i].col) / c2, 0, 0); - } else { // fade from yellow to red - setPixelColor(SEGMENT.start + sparks[i].pos,255, (255 * (sparks[i].col - c2)) / (c1 - c2), 0); + if (sparks[i].col > 3) sparks[i].col -= 4; + + if (sparks[i].pos > 0 && sparks[i].pos < SEGLEN) { + uint16_t prog = sparks[i].col; + uint32_t spColor = (SEGMENT.palette) ? color_wheel(sparks[i].colIndex) : SEGCOLOR(0); + CRGB c = CRGB::Black; //HeatColor(sparks[i].col); + if (prog > 300) { //fade from white to spark color + c = col_to_crgb(color_blend(spColor, WHITE, (prog - 300)*5)); + } else if (prog > 45) { //fade from spark color to black + c = col_to_crgb(color_blend(BLACK, spColor, prog - 45)); + uint8_t cooling = (300 - prog) >> 5; + c.g = qsub8(c.g, cooling); + c.b = qsub8(c.b, cooling * 2); + } + setPixelColor(SEGMENT.start + int(sparks[i].pos), c.red, c.green, c.blue); } } - dying_gravity *= .995; // as sparks burn out they fall slower + dying_gravity *= .99; // as sparks burn out they fall slower } else { - SEGENV.aux0 = 0; //init again - SEGENV.aux1 = 0; //back to flare + SEGENV.aux0 = 6 + random8(10); //wait for this many frames + } + } else { + SEGENV.aux0--; + if (SEGENV.aux0 < 4) { + SEGENV.aux0 = 0; //back to flare + SEGENV.step = (SEGMENT.intensity > random8()); //decide firing side } } + + SEGMENT.setOption(1, actuallyReverse); + return FRAMETIME; } diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 5fc1092f..52951f61 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 2001022 +#define VERSION 2001031 char versionString[] = "0.9.0-b2";