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] 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 106a6712c0..b1e6823ff1 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 ce510f16e6..7f8c1319af 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 d33fb63f70..26d78b2848 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -801,6 +801,7 @@ function populateSegments(s) ``+ ``+ ``+ + ``+ ``+ ``; let sndSim = `
Sound sim
`+