From da79b93387cb80873d5dc65cd864be866a4b70bf Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Tue, 7 May 2024 18:04:29 -0400 Subject: [PATCH 01/15] Added Pinwheel Expand 1D Effect --- wled00/FX.h | 3 ++- wled00/FX_fcn.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++- wled00/data/index.js | 1 + 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 106a6712c..b1e6823ff 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -320,7 +320,8 @@ typedef enum mapping1D2D { M12_Pixels = 0, M12_pBar = 1, M12_pArc = 2, - M12_pCorner = 3 + M12_pCorner = 3, + M12_sPinwheel = 4 } mapping1D2D_t; // segment, 80 bytes diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index ce510f16e..7f8c1319a 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -637,6 +637,14 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { return vLen; } +// Constants for mapping mode "Pinwheel" +constexpr int Pinwheel_Steps_Medium = 208; // no holes up to 32x32; 60fps +constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" +constexpr int Pinwheel_Steps_Big = 360; // no holes expected up to 58x58; 40fps +constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians +constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...360 to Radians + + // 1D strip uint16_t IRAM_ATTR Segment::virtualLength() const { #ifndef WLED_DISABLE_2D @@ -652,6 +660,12 @@ uint16_t IRAM_ATTR Segment::virtualLength() const { case M12_pArc: vLen = max(vW,vH); // get the longest dimension break; + case M12_sPinwheel: + if (max(vW,vH) <= Pinwheel_Size_Medium) + vLen = Pinwheel_Steps_Medium; + else + vLen = Pinwheel_Steps_Big; + break; } return vLen; } @@ -718,6 +732,38 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) for (int x = 0; x <= i; x++) setPixelColorXY(x, i, col); for (int y = 0; y < i; y++) setPixelColorXY(i, y, col); break; + case M12_sPinwheel: { + // i = angle --> 0 through 359 (Big), OR 0 through 208 (Medium) + float centerX = roundf((vW-1) / 2.0f); + float centerY = roundf((vH-1) / 2.0f); + // int maxDistance = sqrt(centerX * centerX + centerY * centerY) + 1; + float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians + float cosVal = cosf(angleRad); + float sinVal = sinf(angleRad); + + // draw line at angle, starting at center and ending at the segment edge + // we use fixed point math for better speed. Starting distance is 0.5 for better rounding + constexpr int_fast32_t Fixed_Scale = 512; // fixpoint scaling factor + int_fast32_t posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point + int_fast32_t posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point + int_fast16_t inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) + int_fast16_t inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) + + int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint + int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint + // draw until we hit any edge + while ((posx > 0) && (posy > 0) && (posx < maxX) && (posy < maxY)) { + // scale down to integer (compiler will replace division with appropriate bitshift) + int x = posx / Fixed_Scale; + int y = posy / Fixed_Scale; + // set pixel + setPixelColorXY(x, y, col); + // advance to next position + posx += inc_x; + posy += inc_y; + } + break; + } } return; } else if (Segment::maxHeight!=1 && (width()==1 || height()==1)) { @@ -833,7 +879,17 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) // use longest dimension return vW>vH ? getPixelColorXY(i, 0) : getPixelColorXY(0, i); break; - } + case M12_sPinwheel: + // not 100% accurate, returns outer edge of circle + float distance = max(1.0f, min(vH-1, vW-1) / 2.0f); + float centerX = (vW - 1) / 2.0f; + float centerY = (vH - 1) / 2.0f; + float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians + int x = roundf(centerX + distance * cosf(angleRad)); + int y = roundf(centerY + distance * sinf(angleRad)); + return getPixelColorXY(x, y); + break; + } return 0; } #endif diff --git a/wled00/data/index.js b/wled00/data/index.js index d33fb63f7..26d78b284 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -801,6 +801,7 @@ function populateSegments(s) ``+ ``+ ``+ + ``+ ``+ ``; let sndSim = `
Sound sim
`+ From 6a18ce078e3b2f31404d3309b39985638d53fcf4 Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Thu, 9 May 2024 20:38:41 -0400 Subject: [PATCH 02/15] Pinwheel Expand1D changes cosf/sinf changed to cos_t/sin_t. int_fast32_t and int_fast_16_t changed to int. --- wled00/FX_fcn.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 7f8c1319a..88ec78f3e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -738,16 +738,17 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) float centerY = roundf((vH-1) / 2.0f); // int maxDistance = sqrt(centerX * centerX + centerY * centerY) + 1; float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians - float cosVal = cosf(angleRad); - float sinVal = sinf(angleRad); + float cosVal = cos_t(angleRad); + float sinVal = sin_t(angleRad); // draw line at angle, starting at center and ending at the segment edge // we use fixed point math for better speed. Starting distance is 0.5 for better rounding - constexpr int_fast32_t Fixed_Scale = 512; // fixpoint scaling factor - int_fast32_t posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point - int_fast32_t posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point - int_fast16_t inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) - int_fast16_t inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) + // int_fast16_t and int_fast32_t types changed to int, minimum bits commented + constexpr int Fixed_Scale = 512; // fixpoint scaling factor 18 bit + int posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point 18 bit + int posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point 18 bit + int inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) 10 bit + int inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) 10 bit int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint @@ -885,8 +886,8 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) float centerX = (vW - 1) / 2.0f; float centerY = (vH - 1) / 2.0f; float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians - int x = roundf(centerX + distance * cosf(angleRad)); - int y = roundf(centerY + distance * sinf(angleRad)); + int x = roundf(centerX + distance * cos_t(angleRad)); + int y = roundf(centerY + distance * sin_t(angleRad)); return getPixelColorXY(x, y); break; } From d3492b5b6c38e6a8cb2136bc8d7654a4594b59df Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Fri, 10 May 2024 16:06:37 -0400 Subject: [PATCH 03/15] Pinwheel Expand 1D Bug Fix Removed holes on 31x31 and 32x32 grids. --- wled00/FX_fcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 88ec78f3e..17a504ea0 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -639,7 +639,7 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { // Constants for mapping mode "Pinwheel" constexpr int Pinwheel_Steps_Medium = 208; // no holes up to 32x32; 60fps -constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" +constexpr int Pinwheel_Size_Medium = 30; // larger than this -> use "Big" constexpr int Pinwheel_Steps_Big = 360; // no holes expected up to 58x58; 40fps constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...360 to Radians From 9e468bd059510c66bbb99e41ed4855193a9cc05c Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Sat, 11 May 2024 13:57:21 -0400 Subject: [PATCH 04/15] Pinwheel Expand 1D Optimizations Added small pinwheel size. Adjusts medium and large values. --- wled00/FX_fcn.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 17a504ea0..ec0e087bc 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -638,9 +638,12 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { } // Constants for mapping mode "Pinwheel" -constexpr int Pinwheel_Steps_Medium = 208; // no holes up to 32x32; 60fps -constexpr int Pinwheel_Size_Medium = 30; // larger than this -> use "Big" -constexpr int Pinwheel_Steps_Big = 360; // no holes expected up to 58x58; 40fps +constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16; +constexpr int Pinwheel_Size_Small = 16; +constexpr int Pinwheel_Steps_Medium = 200; // no holes up to 32x32; 60fps +constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" +constexpr int Pinwheel_Steps_Big = 296; // no holes expected up to 58x58; 40fps +constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...208 to Radians constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...360 to Radians @@ -661,7 +664,9 @@ uint16_t IRAM_ATTR Segment::virtualLength() const { vLen = max(vW,vH); // get the longest dimension break; case M12_sPinwheel: - if (max(vW,vH) <= Pinwheel_Size_Medium) + if (max(vW,vH) <= Pinwheel_Size_Small) + vLen = Pinwheel_Steps_Small; + else if (max(vW,vH) <= Pinwheel_Size_Medium) vLen = Pinwheel_Steps_Medium; else vLen = Pinwheel_Steps_Big; @@ -736,8 +741,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) // i = angle --> 0 through 359 (Big), OR 0 through 208 (Medium) float centerX = roundf((vW-1) / 2.0f); float centerY = roundf((vH-1) / 2.0f); - // int maxDistance = sqrt(centerX * centerX + centerY * centerY) + 1; - float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians + float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians float cosVal = cos_t(angleRad); float sinVal = sin_t(angleRad); @@ -885,7 +889,7 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) float distance = max(1.0f, min(vH-1, vW-1) / 2.0f); float centerX = (vW - 1) / 2.0f; float centerY = (vH - 1) / 2.0f; - float angleRad = (max(vW,vH) > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med; // angle in radians + float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians int x = roundf(centerX + distance * cos_t(angleRad)); int y = roundf(centerY + distance * sin_t(angleRad)); return getPixelColorXY(x, y); From 3078bea7cce95038bc354acd73caecf9ca7327d7 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 12 May 2024 13:29:04 +0200 Subject: [PATCH 05/15] Pinwheel optimization: do nor repaint "same" pixels in a line avoids back to back duplicates within the same line --- wled00/FX_fcn.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index ec0e087bc..b06b0dceb 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -745,10 +745,13 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) float cosVal = cos_t(angleRad); float sinVal = sin_t(angleRad); + // avoid re-painting the same pixel + int lastX = INT_MIN; // impossible position + int lastY = INT_MIN; // impossible position // draw line at angle, starting at center and ending at the segment edge // we use fixed point math for better speed. Starting distance is 0.5 for better rounding // int_fast16_t and int_fast32_t types changed to int, minimum bits commented - constexpr int Fixed_Scale = 512; // fixpoint scaling factor 18 bit + constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction) int posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point 18 bit int posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point 18 bit int inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) 10 bit @@ -756,13 +759,20 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint - // draw until we hit any edge + // draw ray until we hit any edge while ((posx > 0) && (posy > 0) && (posx < maxX) && (posy < maxY)) { // scale down to integer (compiler will replace division with appropriate bitshift) int x = posx / Fixed_Scale; int y = posy / Fixed_Scale; +#if 1 // set pixel - setPixelColorXY(x, y, col); + if (x != lastX || y != lastY) setPixelColorXY(x, y, col); // only paint if pixel position is different +#else + // experimental: only set pixel if color is different (trade getPC performance against setPC) + if ((x != lastX || y != lastY) && (getPixelColorXY(x, y) != col)) setPixelColorXY(x, y, col); // only paint if pixel color is different +#endif + lastX = x; + lastY = y; // advance to next position posx += inc_x; posy += inc_y; From c84d4c637d46fadfa09855fe68465f8db780f68a Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Sun, 12 May 2024 11:52:31 -0400 Subject: [PATCH 06/15] Pinwheel Expand 1D Optimization Changed method for drawing odd numbered rays. --- wled00/FX_fcn.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index b06b0dceb..26ae9ca11 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -640,13 +640,13 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { // Constants for mapping mode "Pinwheel" constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16; constexpr int Pinwheel_Size_Small = 16; -constexpr int Pinwheel_Steps_Medium = 200; // no holes up to 32x32; 60fps +constexpr int Pinwheel_Steps_Medium = 192; // no holes up to 32x32; 60fps constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" constexpr int Pinwheel_Steps_Big = 296; // no holes expected up to 58x58; 40fps constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...208 to Radians constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...360 to Radians - +int prevRay = INT_MIN; // 1D strip uint16_t IRAM_ATTR Segment::virtualLength() const { @@ -738,7 +738,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) for (int y = 0; y < i; y++) setPixelColorXY(i, y, col); break; case M12_sPinwheel: { - // i = angle --> 0 through 359 (Big), OR 0 through 208 (Medium) + // i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small) float centerX = roundf((vW-1) / 2.0f); float centerY = roundf((vH-1) / 2.0f); float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians @@ -759,6 +759,14 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint + + // Odd rays start further from center if prevRay started at center. + if (i % 2 == 1 && (i - 1 == prevRay || i + 1 == prevRay)) { + posx = (posx + inc_x * (vW/4)); + posy = (posy + inc_y * (vH/4)); + } + prevRay = i; + // draw ray until we hit any edge while ((posx > 0) && (posy > 0) && (posx < maxX) && (posy < maxY)) { // scale down to integer (compiler will replace division with appropriate bitshift) From f26bb26ffad857e49b812843f006bfa5f74947be Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 12 May 2024 22:35:33 +0200 Subject: [PATCH 07/15] Update FX_fcn.cpp * minor cleanup, moved prevRay into setPixelColor * removed experimental code (too slow) * comments cleanup --- wled00/FX_fcn.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 26ae9ca11..ca1527a7c 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -638,15 +638,14 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { } // Constants for mapping mode "Pinwheel" -constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16; +constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16 constexpr int Pinwheel_Size_Small = 16; -constexpr int Pinwheel_Steps_Medium = 192; // no holes up to 32x32; 60fps +constexpr int Pinwheel_Steps_Medium = 192; // no holes up to 32x32 constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" -constexpr int Pinwheel_Steps_Big = 296; // no holes expected up to 58x58; 40fps -constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...208 to Radians -constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians -constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...360 to Radians -int prevRay = INT_MIN; +constexpr int Pinwheel_Steps_Big = 296; // no holes expected up to 56x56 +constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians +constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians +constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...296 to Radians // 1D strip uint16_t IRAM_ATTR Segment::virtualLength() const { @@ -738,6 +737,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) for (int y = 0; y < i; y++) setPixelColorXY(i, y, col); break; case M12_sPinwheel: { + static int prevRay = INT_MIN; // previous ray number // i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small) float centerX = roundf((vW-1) / 2.0f); float centerY = roundf((vH-1) / 2.0f); @@ -761,9 +761,9 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint // Odd rays start further from center if prevRay started at center. - if (i % 2 == 1 && (i - 1 == prevRay || i + 1 == prevRay)) { - posx = (posx + inc_x * (vW/4)); - posy = (posy + inc_y * (vH/4)); + if ((i % 2 == 1) && (i - 1 == prevRay || i + 1 == prevRay)) { + posx += inc_x * (vW/4); + posy += inc_y * (vH/4); } prevRay = i; @@ -772,13 +772,8 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) // scale down to integer (compiler will replace division with appropriate bitshift) int x = posx / Fixed_Scale; int y = posy / Fixed_Scale; -#if 1 // set pixel if (x != lastX || y != lastY) setPixelColorXY(x, y, col); // only paint if pixel position is different -#else - // experimental: only set pixel if color is different (trade getPC performance against setPC) - if ((x != lastX || y != lastY) && (getPixelColorXY(x, y) != col)) setPixelColorXY(x, y, col); // only paint if pixel color is different -#endif lastX = x; lastY = y; // advance to next position From ea83ec496b923b1d8e44bb3d5e46364abea5a65a Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 12 May 2024 23:05:58 +0200 Subject: [PATCH 08/15] pinwheel - parameter tuning to fix some holes fixing holes that appeared during testing * at 52x52 (big 296 -> 304) * at 24x32 (medium 192 -> 208) * at 12x16 (small 72 -> 82) ... there is still one hole at 14x16 ... well wtf --- wled00/FX_fcn.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index ca1527a7c..e29cbafa1 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -638,14 +638,14 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { } // Constants for mapping mode "Pinwheel" -constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16 +constexpr int Pinwheel_Steps_Small = 82; // no holes up to 16x16 constexpr int Pinwheel_Size_Small = 16; -constexpr int Pinwheel_Steps_Medium = 192; // no holes up to 32x32 +constexpr int Pinwheel_Steps_Medium = 208; // no holes up to 32x32 constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" -constexpr int Pinwheel_Steps_Big = 296; // no holes expected up to 56x56 -constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians -constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians -constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...296 to Radians +constexpr int Pinwheel_Steps_Big = 304; // no holes expected up to 56x56 +constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...82 to Radians +constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians +constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians // 1D strip uint16_t IRAM_ATTR Segment::virtualLength() const { From 9e0b91ac17f4ad84978be399d7c8f066a4508b85 Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Sun, 12 May 2024 17:46:42 -0400 Subject: [PATCH 09/15] Pinwheel changes. Jump distance for odd rays fixed. Removed holes on rectangular matrices. --- wled00/FX_fcn.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index ca1527a7c..1dd8da69e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -762,8 +762,9 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) // Odd rays start further from center if prevRay started at center. if ((i % 2 == 1) && (i - 1 == prevRay || i + 1 == prevRay)) { - posx += inc_x * (vW/4); - posy += inc_y * (vH/4); + int jump = min(vW/3, vH/3); + posx += inc_x * jump; + posy += inc_y * jump; } prevRay = i; From 1d7789f544540b5aa66099c2e54f4adaac09937a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 13 May 2024 19:27:41 +0200 Subject: [PATCH 10/15] pinwheel bugfixing * setPixelColor: ensure that 0/0 is used * getPixelColor: accuracy improvements unfortunately, "scrolling" audioreactive effects are still not working properly - they end after 1/4 of the circle. Could be due to limited resolution of getPixelColor. --- wled00/FX_fcn.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index c1ae6c2b9..c2f7cef46 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -737,7 +737,6 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) for (int y = 0; y < i; y++) setPixelColorXY(i, y, col); break; case M12_sPinwheel: { - static int prevRay = INT_MIN; // previous ray number // i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small) float centerX = roundf((vW-1) / 2.0f); float centerY = roundf((vH-1) / 2.0f); @@ -761,6 +760,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint // Odd rays start further from center if prevRay started at center. + static int prevRay = INT_MIN; // previous ray number if ((i % 2 == 1) && (i - 1 == prevRay || i + 1 == prevRay)) { int jump = min(vW/3, vH/3); posx += inc_x * jump; @@ -769,7 +769,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) prevRay = i; // draw ray until we hit any edge - while ((posx > 0) && (posy > 0) && (posx < maxX) && (posy < maxY)) { + while ((posx >= 0) && (posy >= 0) && (posx < maxX) && (posy < maxY)) { // scale down to integer (compiler will replace division with appropriate bitshift) int x = posx / Fixed_Scale; int y = posy / Fixed_Scale; @@ -900,12 +900,17 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) break; case M12_sPinwheel: // not 100% accurate, returns outer edge of circle - float distance = max(1.0f, min(vH-1, vW-1) / 2.0f); + int maxXY = max(vW, vH); // max dimension + int minXY = min(vW, vH); // circle diameter + float distance = max(1.0f, 0.5f * minXY) -0.5f; float centerX = (vW - 1) / 2.0f; float centerY = (vH - 1) / 2.0f; - float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians + float angleRad = (maxXY > Pinwheel_Size_Small) ? ((maxXY > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small; // angle in radians int x = roundf(centerX + distance * cos_t(angleRad)); int y = roundf(centerY + distance * sin_t(angleRad)); + // move "slightly off" coordinates back into segment + x = max(0, min(x, int(vW) - 1)); + y = max(0, min(y, int(vH) - 1)); return getPixelColorXY(x, y); break; } From 1d20f18d3f1e09de65ae4cc75e7dca437a9e56bf Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Mon, 13 May 2024 17:43:31 -0400 Subject: [PATCH 11/15] Pinwheel bugfix Fixed getPixelColor. --- wled00/FX_fcn.cpp | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index c2f7cef46..3fd9245ea 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -638,13 +638,13 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { } // Constants for mapping mode "Pinwheel" -constexpr int Pinwheel_Steps_Small = 82; // no holes up to 16x16 +constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16 constexpr int Pinwheel_Size_Small = 16; -constexpr int Pinwheel_Steps_Medium = 208; // no holes up to 32x32 +constexpr int Pinwheel_Steps_Medium = 192; // no holes up to 32x32 constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" constexpr int Pinwheel_Steps_Big = 304; // no holes expected up to 56x56 -constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...82 to Radians -constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...208 to Radians +constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians +constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians // 1D strip @@ -762,7 +762,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) // Odd rays start further from center if prevRay started at center. static int prevRay = INT_MIN; // previous ray number if ((i % 2 == 1) && (i - 1 == prevRay || i + 1 == prevRay)) { - int jump = min(vW/3, vH/3); + int jump = min(vW/3, vH/3); // can add 2 if using medium pinwheel posx += inc_x * jump; posy += inc_y * jump; } @@ -900,17 +900,32 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) break; case M12_sPinwheel: // not 100% accurate, returns outer edge of circle - int maxXY = max(vW, vH); // max dimension - int minXY = min(vW, vH); // circle diameter - float distance = max(1.0f, 0.5f * minXY) -0.5f; - float centerX = (vW - 1) / 2.0f; - float centerY = (vH - 1) / 2.0f; - float angleRad = (maxXY > Pinwheel_Size_Small) ? ((maxXY > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small; // angle in radians - int x = roundf(centerX + distance * cos_t(angleRad)); - int y = roundf(centerY + distance * sin_t(angleRad)); - // move "slightly off" coordinates back into segment - x = max(0, min(x, int(vW) - 1)); - y = max(0, min(y, int(vH) - 1)); + // i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small) + float centerX = roundf((vW-1) / 2.0f); + float centerY = roundf((vH-1) / 2.0f); + float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians + float cosVal = cos_t(angleRad); + float sinVal = sin_t(angleRad); + + constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction) + int posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point 18 bit + int posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point 18 bit + int inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) 10 bit + int inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) 10 bit + + int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint + int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint + + int x = INT_MIN; + int y = INT_MIN; + while ((posx >= 0) && (posy >= 0) && (posx < maxX) && (posy < maxY)) { + // scale down to integer (compiler will replace division with appropriate bitshift) + x = posx / Fixed_Scale; + y = posy / Fixed_Scale; + // advance to next position + posx += inc_x; + posy += inc_y; + } return getPixelColorXY(x, y); break; } From ecb861de561673618f5493ebb29fb716cbcf4f21 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 14 May 2024 10:36:50 +0200 Subject: [PATCH 12/15] pinwheel code cleanup reducing code duplication between sPC and gPC --- wled00/FX_fcn.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 3fd9245ea..b5b456feb 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -646,6 +646,12 @@ constexpr int Pinwheel_Steps_Big = 304; // no holes expected up to 56x56 constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians +constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction) +// Pinwheel helper function: pixel index to radians +static float getPinwheelAngle(int i, int vW, int vH) { + int maxXY = max(vW, vH); + return (maxXY > Pinwheel_Size_Small) ? ((maxXY > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small; +} // 1D strip uint16_t IRAM_ATTR Segment::virtualLength() const { @@ -740,7 +746,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) // i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small) float centerX = roundf((vW-1) / 2.0f); float centerY = roundf((vH-1) / 2.0f); - float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians + float angleRad = getPinwheelAngle(i, vW, vH); // angle in radians float cosVal = cos_t(angleRad); float sinVal = sin_t(angleRad); @@ -750,7 +756,6 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col) // draw line at angle, starting at center and ending at the segment edge // we use fixed point math for better speed. Starting distance is 0.5 for better rounding // int_fast16_t and int_fast32_t types changed to int, minimum bits commented - constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction) int posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point 18 bit int posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point 18 bit int inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) 10 bit @@ -899,23 +904,22 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i) return vW>vH ? getPixelColorXY(i, 0) : getPixelColorXY(0, i); break; case M12_sPinwheel: - // not 100% accurate, returns outer edge of circle + // not 100% accurate, returns pixel at outer edge // i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small) float centerX = roundf((vW-1) / 2.0f); float centerY = roundf((vH-1) / 2.0f); - float angleRad = (max(vW, vH) > Pinwheel_Size_Small ? (max(vW, vH) > Pinwheel_Size_Medium ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small); // angle in radians + float angleRad = getPinwheelAngle(i, vW, vH); // angle in radians float cosVal = cos_t(angleRad); float sinVal = sin_t(angleRad); - constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction) int posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point 18 bit int posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point 18 bit int inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) 10 bit int inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) 10 bit - int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint + // trace ray from center until we hit any edge - to avoid rounding problems, we use the same method as in setPixelColor int x = INT_MIN; int y = INT_MIN; while ((posx >= 0) && (posy >= 0) && (posx < maxX) && (posy < maxY)) { From a5a6a8eaeea513ce3f4fea51bcc054e4d3d62626 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 14 May 2024 11:30:25 +0200 Subject: [PATCH 13/15] pinwheel : fix holes on large matrix, minor code cleanup there were still two holes in my 52x52 setup --> added "XL" size for bigger than 50x50 - achieves 18fps on 52x52 --- wled00/FX_fcn.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index b5b456feb..b31a5e1b8 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -638,20 +638,36 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { } // Constants for mapping mode "Pinwheel" +#ifndef WLED_DISABLE_2D constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16 -constexpr int Pinwheel_Size_Small = 16; +constexpr int Pinwheel_Size_Small = 16; constexpr int Pinwheel_Steps_Medium = 192; // no holes up to 32x32 -constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" -constexpr int Pinwheel_Steps_Big = 304; // no holes expected up to 56x56 +constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" +constexpr int Pinwheel_Steps_Big = 304; // no holes up to 50x50 +constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL" +constexpr int Pinwheel_Steps_XL = 368; constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians +constexpr float Int_to_Rad_XL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XL; // conversion: from 0...368 to Radians + constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction) + // Pinwheel helper function: pixel index to radians static float getPinwheelAngle(int i, int vW, int vH) { int maxXY = max(vW, vH); - return (maxXY > Pinwheel_Size_Small) ? ((maxXY > Pinwheel_Size_Medium) ? float(i) * Int_to_Rad_Big : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small; + return (maxXY > Pinwheel_Size_Small) ? ((maxXY > Pinwheel_Size_Medium) ? ((maxXY > Pinwheel_Size_Big) ? float(i) * Int_to_Rad_XL : float(i) * Int_to_Rad_Big) : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small; } +// Pinwheel helper function: matrix dimensions to number of rays +static int getPinwheelLength(int vW, int vH) { + int maxXY = max(vW, vH); + if (maxXY <= Pinwheel_Size_Small) return Pinwheel_Steps_Small; + if (maxXY <= Pinwheel_Size_Medium) return Pinwheel_Steps_Medium; + if (maxXY <= Pinwheel_Size_Big) return Pinwheel_Steps_Big; + // else + return Pinwheel_Steps_XL; +} +#endif // 1D strip uint16_t IRAM_ATTR Segment::virtualLength() const { @@ -669,12 +685,7 @@ uint16_t IRAM_ATTR Segment::virtualLength() const { vLen = max(vW,vH); // get the longest dimension break; case M12_sPinwheel: - if (max(vW,vH) <= Pinwheel_Size_Small) - vLen = Pinwheel_Steps_Small; - else if (max(vW,vH) <= Pinwheel_Size_Medium) - vLen = Pinwheel_Steps_Medium; - else - vLen = Pinwheel_Steps_Big; + vLen = getPinwheelLength(vW, vH); break; } return vLen; From c0cb677a4cf33a8244344d8269790ad46fdb5cb8 Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Tue, 14 May 2024 11:30:33 -0400 Subject: [PATCH 14/15] Pinwheel cleanup --- wled00/FX_fcn.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index b31a5e1b8..e3dcc2c0d 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -640,23 +640,27 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const { // Constants for mapping mode "Pinwheel" #ifndef WLED_DISABLE_2D constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16 -constexpr int Pinwheel_Size_Small = 16; +constexpr int Pinwheel_Size_Small = 16; // larger than this -> use "Medium" constexpr int Pinwheel_Steps_Medium = 192; // no holes up to 32x32 constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big" constexpr int Pinwheel_Steps_Big = 304; // no holes up to 50x50 constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL" constexpr int Pinwheel_Steps_XL = 368; constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians -constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians -constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians -constexpr float Int_to_Rad_XL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XL; // conversion: from 0...368 to Radians +constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians +constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians +constexpr float Int_to_Rad_XL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XL; // conversion: from 0...368 to Radians constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction) // Pinwheel helper function: pixel index to radians static float getPinwheelAngle(int i, int vW, int vH) { int maxXY = max(vW, vH); - return (maxXY > Pinwheel_Size_Small) ? ((maxXY > Pinwheel_Size_Medium) ? ((maxXY > Pinwheel_Size_Big) ? float(i) * Int_to_Rad_XL : float(i) * Int_to_Rad_Big) : float(i) * Int_to_Rad_Med) : float(i) * Int_to_Rad_Small; + if (maxXY <= Pinwheel_Size_Small) return float(i) * Int_to_Rad_Small; + if (maxXY <= Pinwheel_Size_Medium) return float(i) * Int_to_Rad_Med; + if (maxXY <= Pinwheel_Size_Big) return float(i) * Int_to_Rad_Big; + // else + return Pinwheel_Steps_XL; } // Pinwheel helper function: matrix dimensions to number of rays static int getPinwheelLength(int vW, int vH) { From 3cb6b173163ad3311b8d6063c01c7c1b74dedfd0 Mon Sep 17 00:00:00 2001 From: Brandon502 <105077712+Brandon502@users.noreply.github.com> Date: Tue, 14 May 2024 11:46:52 -0400 Subject: [PATCH 15/15] Pinwheel fix --- wled00/FX_fcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e3dcc2c0d..ef710b0b8 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -660,7 +660,7 @@ static float getPinwheelAngle(int i, int vW, int vH) { if (maxXY <= Pinwheel_Size_Medium) return float(i) * Int_to_Rad_Med; if (maxXY <= Pinwheel_Size_Big) return float(i) * Int_to_Rad_Big; // else - return Pinwheel_Steps_XL; + return float(i) * Int_to_Rad_XL; } // Pinwheel helper function: matrix dimensions to number of rays static int getPinwheelLength(int vW, int vH) {