From ce8f01bf902b42c112157c4e5d57d885812f32e2 Mon Sep 17 00:00:00 2001 From: Troy <5659019+troyhacks@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:48:09 -0400 Subject: [PATCH] Bugfixed GEQ 3D Bug fixes after lots of testing, better settings, etc. Big thanks to @netmindz for restructuring the code. Add rough distance stop to Segment::drawLine() --- wled00/FX.cpp | 108 +++++++++++++++++++++++++------------------- wled00/FX.h | 4 +- wled00/FX_2Dfcn.cpp | 4 +- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 68b848cd..f1339bd1 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -8371,21 +8371,18 @@ uint16_t mode_GEQLASER(void) { SEGMENT.setUpLeds(); // WLEDMM use lossless getPixelColor() SEGMENT.fill(BLACK); } else { - *projector += *projector_dir; + if (SEGENV.call % map(SEGMENT.speed,0,255,10,1) == 0) *projector += *projector_dir; if (*projector == SEGMENT.virtualWidth()) *projector_dir = -1; if (*projector == 0) *projector_dir = 1; } - if (SEGMENT.speed > 250) { - SEGMENT.fill(BLACK); - } else { - SEGMENT.fadeToBlackBy(SEGMENT.speed); - } + SEGMENT.fill(BLACK); - const int NUM_BANDS = map(SEGMENT.custom1, 0, 255, 1, 16); + const int NUM_BANDS = map(SEGMENT.custom3, 0, 31, 1, 16); // custom3 is 0..31 const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); - const uint_fast8_t split = map(*projector,0,SEGMENT.virtualWidth(),0,(NUM_BANDS - 1)); + uint32_t ledColorTemp; + uint_fast8_t split = map(*projector,0,SEGMENT.virtualWidth(),0,(NUM_BANDS - 1)); um_data_t *um_data; if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { @@ -8397,10 +8394,14 @@ uint16_t mode_GEQLASER(void) { uint8_t heights[NUM_BANDS] = { 0 }; for (int i=0; i 1) { + ledColorTemp = color_fade(ledColor,32,true); + for (int y = 0; y <= heights[i]; y++) { - SEGMENT.drawLine(linex+(cols/NUM_BANDS)-1,rows-y-1,*projector,0,color_fade(ledColor,32,true)); + SEGMENT.drawLine(linex+(cols/NUM_BANDS)-1,rows-y-1,*projector,horizon,ledColorTemp,distance); // right side perspective } - for (int x=linex; x<=linex+(cols/NUM_BANDS)-1;x++) { - SEGMENT.drawLine(x, rows-heights[i]-2,*projector,0,color_fade(ledColor,128,true)); // top perspective + ledColorTemp = color_fade(ledColor,128,true); + + if (heights[i] < rows-horizon && (*projector <=linex || *projector >= linex+(cols/NUM_BANDS)-1)) { // draw if above horizon AND not directly under projector (special case later) + + for (uint_fast8_t x=linex; x<=linex+(cols/NUM_BANDS)-1;x++) { + SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,distance); // top perspective + } + } } } - for (int i=(NUM_BANDS - 1); i>split; i--) { // paint left vertical faces and top + for (int i=(NUM_BANDS - 1); i>split; i--) { // paint left vertical faces and top - RIGHT to LEFT uint16_t colorIndex = map(cols/NUM_BANDS*i, 0, cols-1, 0, 255); uint32_t ledColor = SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0); @@ -8430,19 +8439,26 @@ uint16_t mode_GEQLASER(void) { if (heights[i] > 1) { - for (int y = 0; y <= heights[i]; y++) { - SEGMENT.drawLine(linex ,rows-y-1,*projector,0,color_fade(ledColor,32,true)); - } + ledColorTemp = color_fade(ledColor,32,true); - for (int x=linex; x<=linex+(cols/NUM_BANDS)-1;x++) { - SEGMENT.drawLine(x, rows-heights[i]-2,*projector,0,color_fade(ledColor,128,true)); // top perspective + for (uint_fast8_t y = 0; y <= heights[i]; y++) { + SEGMENT.drawLine(linex,rows-y-1,*projector,horizon,ledColorTemp,distance); // left side perspective } + ledColorTemp = color_fade(ledColor,128,true); + + if (heights[i] < rows-horizon && (*projector <=linex || *projector >= linex+(cols/NUM_BANDS)-1)) { // draw if above horizon AND not directly under projector (special case later) + + for (uint_fast8_t x=linex; x<=linex+(cols/NUM_BANDS)-1;x++) { + SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,distance); // top perspective + } + + } + } } - uint8_t frontBrightness = SEGMENT.custom2; for (int i=0; i 1) { + if (*projector >=linex && *projector <= linex+(cols/NUM_BANDS)-1) { // special case when top perspective is directly under the projector - if(frontBrightness > 250) { - // Full bright fronts, fills all front face. - for (int x=linex; x= 50) { - // Faded fronts, assumes border added later. - for (int x=linex+1; x 1 && heights[i] < rows-horizon) { + + ledColorTemp = color_fade(ledColor,128,true); + + for (uint_fast8_t x=linex; x<=linex+(cols/NUM_BANDS)-1;x++) { + SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,distance); // top perspective } + } - if(frontBrightness >= 50) { // TODO: other values too? not sure exactly when we want the border - // Border - SEGMENT.drawLine(linex, rows-1,linex,rows-heights[i]-1,ledColor); // left side line - SEGMENT.drawLine(linex+(cols/NUM_BANDS)-1,rows-1,linex+(cols/NUM_BANDS)-1,rows-heights[i]-1,ledColor); // right side line - SEGMENT.drawLine(linex, rows-heights[i]-2,linex+(cols/NUM_BANDS)-1,rows-heights[i]-2,ledColor); // top line - SEGMENT.drawLine(linex, rows-1,linex+(cols/NUM_BANDS)-1,rows-1,ledColor); // bottom line } - } + if (heights[i] > 1) { + + ledColorTemp = color_fade(ledColor,SEGMENT.intensity,true); + + for (uint_fast8_t x=linex; x rows-horizon) { + + if (SEGMENT.intensity == 0) ledColorTemp = color_fade(ledColor,32,true); // match side fill if we're in blackout mode + + SEGMENT.drawLine(linex,rows-heights[i]-1,linex+(cols/NUM_BANDS)-1,rows-heights[i]-1,ledColorTemp); // top line to simulate hidden top fill + + } + + } } return FRAMETIME; } -static const char _data_FX_MODE_GEQLASER[] PROGMEM = "GEQ Laser ☾@Fade Speed,,Bands,Fill Front,;;!;2f"; - +static const char _data_FX_MODE_GEQLASER[] PROGMEM = "GEQ 3D ☾@Speed,Front Fill,Horizon,Distance,Num Bands,,,;!,,Peaks;!;2f;sx=255,ix=255,c1=255,c2=255,c3=255,pal=11"; #endif // WLED_DISABLE_2D diff --git a/wled00/FX.h b/wled00/FX.h index 2143d984..f6a5fd31 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -687,8 +687,8 @@ typedef struct Segment { void move(uint8_t dir, uint8_t delta, bool wrap = false); void draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); - void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c); - void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline + void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, uint16_t d = UINT16_MAX); + void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, uint16_t d = UINT16_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), d); } // automatic inline void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor = 0); void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.b,0)); } // automatic inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 1d217ff0..83599c97 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -582,7 +582,7 @@ void Segment::nscale8(uint8_t scale) { //WLEDMM: use fast types } //line function -void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) { +void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, uint16_t distance) { if (!isActive()) return; // not active const uint16_t cols = virtualWidth(); const uint16_t rows = virtualHeight(); @@ -590,7 +590,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3 const int16_t dx = abs(x1-x0), sx = x0dy ? dx : -dy)/2, e2; - for (;;) { + for (uint_fast16_t d=0; d