diff --git a/wled00/FX.cpp b/wled00/FX.cpp index dcd6b2b8..91e52099 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -8414,7 +8414,12 @@ uint16_t mode_GEQLASER(void) { // Author: @TroyHacks // @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - + + if (!strip.isMatrix) return mode_static(); // not a 2D set-up + const int cols = SEGMENT.virtualWidth(); + const int rows = SEGMENT.virtualHeight(); + if ((cols < 3) || (rows < 3)) return mode_static(); // too small + const size_t dataSize = sizeof(uint16_t); if (!SEGENV.allocateData(dataSize * 2)) return mode_static(); //allocation failed uint16_t *projector = reinterpret_cast(SEGENV.data); @@ -8434,11 +8439,9 @@ uint16_t mode_GEQLASER(void) { SEGMENT.fill(BLACK); uint32_t ledColorTemp; - const int cols = SEGMENT.virtualWidth(); - const int rows = SEGMENT.virtualHeight(); - const int NUM_BANDS = map(SEGMENT.custom3, 0, 31, 1, 16); // custom3 is 0..31 - uint_fast8_t split = map(*projector,0,SEGMENT.virtualWidth(),0,(NUM_BANDS - 1)); - uint16_t horizon = map(SEGMENT.custom1,0,255,rows-1,0); + const int NUM_BANDS = max(2, min(cols, int(map2(SEGMENT.custom3, 0, 31, 1, NUM_GEQ_CHANNELS)))); // custom3 is 0..31 - constrain NUM_BANDS between 2(for split) and cols (for small width segments) + uint_fast8_t split = map2(*projector,0,SEGMENT.virtualWidth(),0,(NUM_BANDS - 1)); + uint16_t horizon = map2(SEGMENT.custom1,0,255,rows-1,0); uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser") um_data_t *um_data; @@ -8450,7 +8453,7 @@ uint16_t mode_GEQLASER(void) { uint8_t heights[NUM_GEQ_CHANNELS] = { 0 }; for (int i=0; i 0) SEGMENT.drawLine(pPos,rows-y-1,*projector,horizon,ledColorTemp,false,depth); // right side perspective } ledColorTemp = color_fade(ledColor,128,true); if (heights[i] < rows-horizon && (*projector <=linex || *projector >= pPos)) { // draw if above horizon AND not directly under projector (special case later) - for (uint_fast8_t x=linex; x<=pPos;x++) { - bool doSoft = SEGMENT.check2 && ((x==linex) || (x==pPos)); // only first and last line need AA - SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,doSoft,depth); // top perspective + if (rows-heights[i] > 1) { // sanity check - avoid negative Y + for (uint_fast8_t x=linex; x<=pPos;x++) { + bool doSoft = SEGMENT.check2 && ((x==linex) || (x==pPos)); // only first and last line need AA + SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,doSoft,depth); // top perspective + } } } } @@ -8486,14 +8491,16 @@ uint16_t mode_GEQLASER(void) { if (heights[i] > 1) { ledColorTemp = color_fade(ledColor,32,true); for (uint_fast8_t y = (i>0) ? heights[i-1] : 0; y <= heights[i]; y++) { // don't bother drawing what we'll hide anyway - SEGMENT.drawLine(linex,rows-y-1,*projector,horizon,ledColorTemp,false,depth); // left side perspective + if (rows-y > 0) SEGMENT.drawLine(linex,rows-y-1,*projector,horizon,ledColorTemp,false,depth); // left side perspective } ledColorTemp = color_fade(ledColor,128,true); if (heights[i] < rows-horizon && (*projector <=linex || *projector >= pPos)) { // draw if above horizon AND not directly under projector (special case later) - for (uint_fast8_t x=linex; x<=pPos;x++) { - bool doSoft = SEGMENT.check2 && ((x==linex) || (x==pPos)); // only first and last line need AA - SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,doSoft,depth); // top perspective + if (rows-heights[i] > 1) { // sanity check - avoid negative Y + for (uint_fast8_t x=linex; x<=pPos;x++) { + bool doSoft = SEGMENT.check2 && ((x==linex) || (x==pPos)); // only first and last line need AA + SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,doSoft,depth); // top perspective + } } } } @@ -8508,7 +8515,7 @@ uint16_t mode_GEQLASER(void) { int pPos1 = linex+(cols/NUM_BANDS); if (*projector >=linex && *projector <= pPos) { // special case when top perspective is directly under the projector - if (heights[i] > 1 && heights[i] < rows-horizon) { + if ((heights[i] > 1) && (heights[i] < rows-horizon) && (rows-heights[i] > 1)) { ledColorTemp = color_fade(ledColor,128,true); for (uint_fast8_t x=linex; x<=pPos;x++) { bool doSoft = SEGMENT.check2 && ((x==linex) || (x==pPos)); // only first and last line need AA @@ -8517,7 +8524,7 @@ uint16_t mode_GEQLASER(void) { } } - if (heights[i] > 1) { + if ((heights[i] > 1) && (rows-heights[i] > 0)) { ledColorTemp = color_fade(ledColor,SEGMENT.intensity,true); for (uint_fast8_t x=linex; x