GEQ 3D robustness improvements
* require at least a 3x3 setup * make sure that NUM_BANDS is limited by available columns * avoid drawing with negative Y * slightly reduce default "front fill", so that "borders" has a visible effect when running with defaults
This commit is contained in:
@@ -8415,6 +8415,11 @@ uint16_t mode_GEQLASER(void) {
|
|||||||
// Author: @TroyHacks
|
// Author: @TroyHacks
|
||||||
// @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
|
// @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);
|
const size_t dataSize = sizeof(uint16_t);
|
||||||
if (!SEGENV.allocateData(dataSize * 2)) return mode_static(); //allocation failed
|
if (!SEGENV.allocateData(dataSize * 2)) return mode_static(); //allocation failed
|
||||||
uint16_t *projector = reinterpret_cast<uint16_t*>(SEGENV.data);
|
uint16_t *projector = reinterpret_cast<uint16_t*>(SEGENV.data);
|
||||||
@@ -8434,11 +8439,9 @@ uint16_t mode_GEQLASER(void) {
|
|||||||
SEGMENT.fill(BLACK);
|
SEGMENT.fill(BLACK);
|
||||||
|
|
||||||
uint32_t ledColorTemp;
|
uint32_t ledColorTemp;
|
||||||
const int cols = SEGMENT.virtualWidth();
|
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)
|
||||||
const int rows = SEGMENT.virtualHeight();
|
uint_fast8_t split = map2(*projector,0,SEGMENT.virtualWidth(),0,(NUM_BANDS - 1));
|
||||||
const int NUM_BANDS = map(SEGMENT.custom3, 0, 31, 1, 16); // custom3 is 0..31
|
uint16_t horizon = map2(SEGMENT.custom1,0,255,rows-1,0);
|
||||||
uint_fast8_t split = map(*projector,0,SEGMENT.virtualWidth(),0,(NUM_BANDS - 1));
|
|
||||||
uint16_t horizon = map(SEGMENT.custom1,0,255,rows-1,0);
|
|
||||||
uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser")
|
uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser")
|
||||||
|
|
||||||
um_data_t *um_data;
|
um_data_t *um_data;
|
||||||
@@ -8450,7 +8453,7 @@ uint16_t mode_GEQLASER(void) {
|
|||||||
|
|
||||||
uint8_t heights[NUM_GEQ_CHANNELS] = { 0 };
|
uint8_t heights[NUM_GEQ_CHANNELS] = { 0 };
|
||||||
for (int i=0; i<NUM_BANDS; i++) {
|
for (int i=0; i<NUM_BANDS; i++) {
|
||||||
heights[i] = map8(fftResult[i],0,rows*0.85); // cache fftResult[] as data might be updated in parallel by the audioreactive core
|
heights[i] = map8(fftResult[i],0,roundf(rows*0.85f)); // cache fftResult[] as data might be updated in parallel by the audioreactive core
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -8463,14 +8466,16 @@ uint16_t mode_GEQLASER(void) {
|
|||||||
ledColorTemp = color_fade(ledColor,32,true);
|
ledColorTemp = color_fade(ledColor,32,true);
|
||||||
int pPos = linex+(cols/NUM_BANDS)-1;
|
int pPos = linex+(cols/NUM_BANDS)-1;
|
||||||
for (int y = (i<NUM_BANDS-1) ? heights[i+1] : 0; y <= heights[i]; y++) { // don't bother drawing what we'll hide anyway
|
for (int y = (i<NUM_BANDS-1) ? heights[i+1] : 0; y <= heights[i]; y++) { // don't bother drawing what we'll hide anyway
|
||||||
SEGMENT.drawLine(pPos,rows-y-1,*projector,horizon,ledColorTemp,false,depth); // right side perspective
|
if (rows-y > 0) SEGMENT.drawLine(pPos,rows-y-1,*projector,horizon,ledColorTemp,false,depth); // right side perspective
|
||||||
}
|
}
|
||||||
|
|
||||||
ledColorTemp = color_fade(ledColor,128,true);
|
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)
|
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++) {
|
if (rows-heights[i] > 1) { // sanity check - avoid negative Y
|
||||||
bool doSoft = SEGMENT.check2 && ((x==linex) || (x==pPos)); // only first and last line need AA
|
for (uint_fast8_t x=linex; x<=pPos;x++) {
|
||||||
SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,doSoft,depth); // top perspective
|
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) {
|
if (heights[i] > 1) {
|
||||||
ledColorTemp = color_fade(ledColor,32,true);
|
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
|
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);
|
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)
|
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++) {
|
if (rows-heights[i] > 1) { // sanity check - avoid negative Y
|
||||||
bool doSoft = SEGMENT.check2 && ((x==linex) || (x==pPos)); // only first and last line need AA
|
for (uint_fast8_t x=linex; x<=pPos;x++) {
|
||||||
SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,doSoft,depth); // top perspective
|
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);
|
int pPos1 = linex+(cols/NUM_BANDS);
|
||||||
|
|
||||||
if (*projector >=linex && *projector <= pPos) { // special case when top perspective is directly under the projector
|
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);
|
ledColorTemp = color_fade(ledColor,128,true);
|
||||||
for (uint_fast8_t x=linex; x<=pPos;x++) {
|
for (uint_fast8_t x=linex; x<=pPos;x++) {
|
||||||
bool doSoft = SEGMENT.check2 && ((x==linex) || (x==pPos)); // only first and last line need AA
|
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);
|
ledColorTemp = color_fade(ledColor,SEGMENT.intensity,true);
|
||||||
for (uint_fast8_t x=linex; x<pPos1;x++) {
|
for (uint_fast8_t x=linex; x<pPos1;x++) {
|
||||||
SEGMENT.drawLine(x,rows-1,x,rows-heights[i]-1,ledColorTemp); // front fill
|
SEGMENT.drawLine(x,rows-1,x,rows-heights[i]-1,ledColorTemp); // front fill
|
||||||
@@ -8528,7 +8535,7 @@ uint16_t mode_GEQLASER(void) {
|
|||||||
SEGMENT.drawLine(linex,rows-heights[i]-1,linex+(cols/NUM_BANDS)-1,rows-heights[i]-1,ledColorTemp); // top line to simulate hidden top fill
|
SEGMENT.drawLine(linex,rows-heights[i]-1,linex+(cols/NUM_BANDS)-1,rows-heights[i]-1,ledColorTemp); // top line to simulate hidden top fill
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SEGMENT.check1) {
|
if ((SEGMENT.check1) && (rows-heights[i] > 1)) {
|
||||||
SEGMENT.drawLine(linex, rows-1,linex,rows-heights[i]-1,ledColor); // left side line
|
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+(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-heights[i]-2,linex+(cols/NUM_BANDS)-1,rows-heights[i]-2,ledColor); // top line
|
||||||
@@ -8538,7 +8545,7 @@ uint16_t mode_GEQLASER(void) {
|
|||||||
}
|
}
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
}
|
}
|
||||||
static const char _data_FX_MODE_GEQLASER[] PROGMEM = "GEQ 3D ☾@Speed,Front Fill,Horizon,Depth,Num Bands,Borders,Soft,;!,,Peaks;!;2f;sx=255,ix=255,c1=255,c2=255,c3=255,pal=11";
|
static const char _data_FX_MODE_GEQLASER[] PROGMEM = "GEQ 3D ☾@Speed,Front Fill,Horizon,Depth,Num Bands,Borders,Soft,;!,,Peaks;!;2f;sx=255,ix=228,c1=255,c2=255,c3=255,pal=11";
|
||||||
|
|
||||||
#endif // WLED_DISABLE_2D
|
#endif // WLED_DISABLE_2D
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user