Merge pull request #143 from MoonModules/3DGEQ
3D GEQ, plus performance improvements when drawing lines.
This commit is contained in:
171
wled00/FX.cpp
171
wled00/FX.cpp
@@ -7879,7 +7879,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
|
||||
|
||||
uint16_t lastBandHeight = 0; // WLEDMM: for smoothing out bars
|
||||
|
||||
//WLEDMM: evenly ditribut bands
|
||||
//WLEDMM: evenly ditribute bands
|
||||
float bandwidth = (float)cols / NUM_BANDS;
|
||||
float remaining = bandwidth;
|
||||
uint8_t band = 0;
|
||||
@@ -7914,13 +7914,17 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
|
||||
if (barHeight > previousBarHeight[x]) previousBarHeight[x] = barHeight; //drive the peak up
|
||||
|
||||
uint32_t ledColor = BLACK;
|
||||
if ((! SEGMENT.check1) && (barHeight > 0)) { // use faster drawLine when single-color bars are needed
|
||||
ledColor = SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0);
|
||||
SEGMENT.drawLine(int(x), max(0,int(rows)-barHeight-1), int(x), int(rows-1), ledColor, false); // max(0, ...) to prevent negative Y
|
||||
} else {
|
||||
for (int y=0; y < barHeight; y++) {
|
||||
if (SEGMENT.check1) //color_vertical / color bars toggle
|
||||
colorIndex = map(y, 0, rows-1, 0, 255);
|
||||
|
||||
ledColor = SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0);
|
||||
SEGMENT.setPixelColorXY(x, rows-1 - y, ledColor);
|
||||
}
|
||||
} }
|
||||
if ((SEGMENT.intensity < 255) && (previousBarHeight[x] > 0) && (previousBarHeight[x] < rows)) // WLEDMM avoid "overshooting" into other segments
|
||||
SEGMENT.setPixelColorXY(x, rows - previousBarHeight[x], (SEGCOLOR(2) != BLACK) ? SEGCOLOR(2) : ledColor);
|
||||
|
||||
@@ -8384,6 +8388,166 @@ uint16_t mode_2Dwavingcell() {
|
||||
}
|
||||
static const char _data_FX_MODE_2DWAVINGCELL[] PROGMEM = "Waving Cell@!,,Amplitude 1,Amplitude 2,Amplitude 3;;!;2";
|
||||
|
||||
uint16_t mode_GEQLASER(void) {
|
||||
|
||||
// Author: @TroyHacks
|
||||
|
||||
const size_t dataSize = sizeof(uint16_t);
|
||||
if (!SEGENV.allocateData(dataSize * 2)) return mode_static(); //allocation failed
|
||||
|
||||
uint16_t *projector = reinterpret_cast<uint16_t*>(SEGENV.data);
|
||||
uint16_t *projector_dir = reinterpret_cast<uint16_t*>(SEGENV.data + dataSize);
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
*projector = 0;
|
||||
*projector_dir = 0;
|
||||
SEGMENT.setUpLeds(); // WLEDMM use lossless getPixelColor()
|
||||
SEGMENT.fill(BLACK);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
SEGMENT.fill(BLACK);
|
||||
|
||||
const int NUM_BANDS = map(SEGMENT.custom3, 0, 31, 1, 16); // custom3 is 0..31
|
||||
const int cols = SEGMENT.virtualWidth();
|
||||
const int rows = SEGMENT.virtualHeight();
|
||||
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)) {
|
||||
// add support for no audio
|
||||
um_data = simulateSound(SEGMENT.soundSim);
|
||||
}
|
||||
uint8_t *fftResult = (uint8_t*)um_data->u_data[2];
|
||||
|
||||
uint8_t heights[NUM_GEQ_CHANNELS] = { 0 };
|
||||
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
|
||||
}
|
||||
|
||||
uint16_t horizon = map(SEGMENT.custom1,0,255,rows-1,0);
|
||||
uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser")
|
||||
|
||||
for (int i=0; i<=split; i++) { // paint right vertical faces and top - LEFT to RIGHT
|
||||
|
||||
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);
|
||||
|
||||
int linex = i*(cols/NUM_BANDS);
|
||||
|
||||
if (heights[i] > 1) {
|
||||
|
||||
ledColorTemp = color_fade(ledColor,32,true);
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int linex = i*(cols/NUM_BANDS);
|
||||
int pPos = linex+(cols/NUM_BANDS)-1;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_BANDS; i++) {
|
||||
|
||||
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);
|
||||
|
||||
int linex = i*(cols/NUM_BANDS);
|
||||
int pPos = linex+(cols/NUM_BANDS)-1;
|
||||
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) {
|
||||
|
||||
ledColorTemp = color_fade(ledColor,128,true);
|
||||
|
||||
for (uint_fast8_t x=linex; x<=pPos;x++) {
|
||||
SEGMENT.drawLine(x,rows-heights[i]-2,*projector,horizon,ledColorTemp,false,depth); // top perspective
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (heights[i] > 1) {
|
||||
|
||||
ledColorTemp = color_fade(ledColor,SEGMENT.intensity,true);
|
||||
|
||||
for (uint_fast8_t x=linex; x<pPos1;x++) {
|
||||
SEGMENT.drawLine(x,rows-1,x,rows-heights[i]-1,ledColorTemp); // front fill
|
||||
}
|
||||
|
||||
if (!SEGMENT.check1 && heights[i] > 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
|
||||
|
||||
}
|
||||
|
||||
if (SEGMENT.check1) {
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
@@ -8630,6 +8794,9 @@ void WS2812FX::setupEffectData() {
|
||||
addEffect(FX_MODE_2DWAVINGCELL, &mode_2Dwavingcell, _data_FX_MODE_2DWAVINGCELL);
|
||||
|
||||
addEffect(FX_MODE_2DAKEMI, &mode_2DAkemi, _data_FX_MODE_2DAKEMI); // audio
|
||||
|
||||
addEffect(FX_MODE_GEQLASER, &mode_GEQLASER, _data_FX_MODE_GEQLASER); // audio
|
||||
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
}
|
||||
|
||||
11
wled00/FX.h
11
wled00/FX.h
@@ -348,8 +348,9 @@ bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn.
|
||||
#define FX_MODE_STARBURST_AR 192 // WLED-SR audioreactive fireworks starburst
|
||||
// #define FX_MODE_PALETTE_AR 193 // WLED-SR audioreactive palette
|
||||
#define FX_MODE_FIREWORKS_AR 194 // WLED-SR audioreactive fireworks
|
||||
#define FX_MODE_GEQLASER 195 // WLED-MM GEQ Laser
|
||||
|
||||
#define MODE_COUNT 195
|
||||
#define MODE_COUNT 196
|
||||
|
||||
typedef enum mapping1D2D {
|
||||
M12_Pixels = 0,
|
||||
@@ -431,6 +432,7 @@ typedef struct Segment {
|
||||
};
|
||||
size_t _dataLen; // WLEDMM uint16_t is too small
|
||||
static size_t _usedSegmentData; // WLEDMM uint16_t is too small
|
||||
void setPixelColorXY_fast(int x, int y,uint32_t c, uint32_t scaled_col, int cols, int rows); // set relative pixel within segment with color - faster, but no error checking!!!
|
||||
|
||||
// perhaps this should be per segment, not static
|
||||
static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette())
|
||||
@@ -665,6 +667,8 @@ typedef struct Segment {
|
||||
if (height == 0) return (x%width); // softhack007 avoid div/0
|
||||
return (x%width) + (y%height) * width;
|
||||
}
|
||||
|
||||
//void setPixelColorXY_fast(int x, int y,uint32_t c); // set relative pixel within segment with color - wrapper for _fast
|
||||
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
|
||||
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); }
|
||||
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
|
||||
@@ -693,8 +697,8 @@ typedef struct Segment {
|
||||
inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
||||
void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
|
||||
inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false);
|
||||
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft); } // automatic inline
|
||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false, uint8_t depth = UINT8_MAX);
|
||||
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline
|
||||
void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor = 0);
|
||||
inline 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);
|
||||
@@ -980,6 +984,7 @@ class WS2812FX { // 96 bytes
|
||||
|
||||
void
|
||||
setUpMatrix(),
|
||||
setPixelColorXY_fast(int x, int y, uint32_t c),
|
||||
setPixelColorXY(int x, int y, uint32_t c);
|
||||
|
||||
// outsmart the compiler :) by correctly overloading
|
||||
|
||||
@@ -176,6 +176,15 @@ void WS2812FX::setUpMatrix() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// absolute matrix version of setPixelColor(), without error checking
|
||||
void IRAM_ATTR WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||
{
|
||||
uint_fast16_t index = y * Segment::maxWidth + x;
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
if (index >= _length) return;
|
||||
busses.setPixelColor(index, col);
|
||||
}
|
||||
|
||||
// absolute matrix version of setPixelColor()
|
||||
void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||
{
|
||||
@@ -211,6 +220,67 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||
// WLEDMM Segment::XY()is declared inline, see FX.h
|
||||
|
||||
|
||||
// Simplified version of Segment::setPixelColorXY - without error checking. Does not support grouping or spacing
|
||||
// * expects scaled color (final brightness) as additional input parameter, plus segment virtualWidth() and virtualHeight()
|
||||
void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM
|
||||
{
|
||||
// if (Segment::maxHeight==1) return; // not a matrix set-up
|
||||
// const int_fast16_t cols = virtualWidth(); // WLEDMM optimization
|
||||
// const int_fast16_t rows = virtualHeight();
|
||||
// if (x<0 || y<0 || x >= cols || y >= rows) return; // if pixel would fall out of virtual segment just exit
|
||||
unsigned i = UINT_MAX;
|
||||
bool sameColor = false;
|
||||
if (ledsrgb) { // WLEDMM small optimization
|
||||
//i = XY(x,y);
|
||||
//i = (x%cols) + (y%rows) * cols; // avoid error checking done in XY()
|
||||
i = x + y*cols; // avoid error checking done by XY() - be optimistic about ranges of x and y
|
||||
CRGB fastled_col = CRGB(col);
|
||||
if (ledsrgb[i] == fastled_col) sameColor = true;
|
||||
else ledsrgb[i] = fastled_col;
|
||||
}
|
||||
#if 0
|
||||
// we are NOT doing brightness here - must be done by the calling function!
|
||||
//uint32_t scaled_col = col;
|
||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||
if (!_bri_t && !transitional) return;
|
||||
if (_bri_t < 255) scaled_col = color_fade(col, _bri_t);
|
||||
else scaled_col = col;
|
||||
#endif
|
||||
|
||||
#if 0 // this is still a dangerous optimization
|
||||
if ((i < UINT_MAX) && sameColor && (call > 0) && (!transitional) && (ledsrgb[i] == CRGB(col)) && (_globalLeds == nullptr)) return; // WLEDMM looks like nothing to do (but we don't trust globalleds)
|
||||
#endif
|
||||
|
||||
// handle reverse and transpose
|
||||
if (reverse ) x = cols - x - 1;
|
||||
if (reverse_y) y = rows - y - 1;
|
||||
if (transpose) std::swap(x,y); // swap X & Y if segment transposed
|
||||
|
||||
// set the requested pixel
|
||||
strip.setPixelColorXY_fast(start + x, startY + y, scaled_col);
|
||||
bool simpleSegment = !mirror && !mirror_y;
|
||||
if (simpleSegment) return; // WLEDMM shortcut when no mirroring needed
|
||||
|
||||
// handle mirroring
|
||||
const int_fast16_t wid_ = stop - start;
|
||||
const int_fast16_t hei_ = stopY - startY;
|
||||
//if (x >= wid_ || y >= hei_) return; // if pixel would fall out of segment just exit - should never happen, because width() >= virtualWidth()
|
||||
if (mirror) { //set the corresponding horizontally mirrored pixel
|
||||
if (transpose) strip.setPixelColorXY_fast(start + x, startY + hei_ - y - 1, scaled_col);
|
||||
else strip.setPixelColorXY_fast(start + wid_ - x - 1, startY + y, scaled_col);
|
||||
}
|
||||
if (mirror_y) { //set the corresponding vertically mirrored pixel
|
||||
if (transpose) strip.setPixelColorXY_fast(start + wid_ - x - 1, startY + y, scaled_col);
|
||||
else strip.setPixelColorXY_fast(start + x, startY + hei_ - y - 1, scaled_col);
|
||||
}
|
||||
if (mirror_y && mirror) { //set the corresponding vertically AND horizontally mirrored pixel
|
||||
strip.setPixelColorXY_fast(wid_ - x - 1, hei_ - y - 1, scaled_col);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// normal Segment::setPixelColorXY with error checking, and support for grouping / spacing
|
||||
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||
{
|
||||
if (Segment::maxHeight==1) return; // not a matrix set-up
|
||||
@@ -606,18 +676,44 @@ 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, bool soft) {
|
||||
void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft, uint8_t depth) {
|
||||
if (!isActive()) return; // not active
|
||||
// if (Segment::maxHeight==1) return; // not a matrix set-up
|
||||
const int cols = virtualWidth();
|
||||
const int rows = virtualHeight();
|
||||
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
||||
|
||||
// WLEDMM shortcut when no grouping/spacing used
|
||||
bool simpleSegment = !reverse && (grouping == 1) && (spacing == 0); // !reverse is just for back-to-back testing against "slow" functions
|
||||
uint32_t scaled_col = c;
|
||||
if (simpleSegment) {
|
||||
// segment brightness must be pre-calculated for the "fast" setPixelColorXY variant!
|
||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||
if (!_bri_t && !transitional) return;
|
||||
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
|
||||
}
|
||||
|
||||
// WLEDMM shorten line according to depth
|
||||
if (depth < UINT8_MAX) {
|
||||
if (depth == 0) return; // nothing to paint
|
||||
if (depth<2) {x1 = x0; y1=y0; } // single pixel
|
||||
else { // shorten line
|
||||
x0 *=2; y0 *=2; // we do everything "*2" for better rounding
|
||||
int dx1 = ((int(2*x1) - int(x0)) * int(depth)) / 255; // X distance, scaled down by depth
|
||||
int dy1 = ((int(2*y1) - int(y0)) * int(depth)) / 255; // Y distance, scaled down by depth
|
||||
x1 = (x0 + dx1 +1) / 2;
|
||||
y1 = (y0 + dy1 +1) / 2;
|
||||
x0 /=2; y0 /=2;
|
||||
}
|
||||
}
|
||||
|
||||
const int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; // x distance & step
|
||||
const int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; // y distance & step
|
||||
|
||||
// single pixel (line length == 0)
|
||||
if (dx+dy == 0) {
|
||||
setPixelColorXY(x0, y0, c);
|
||||
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
||||
else setPixelColorXY(x0, y0, c);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -651,7 +747,9 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
||||
// Bresenham's algorithm
|
||||
int err = (dx>dy ? dx : -dy)/2; // error direction
|
||||
for (;;) {
|
||||
setPixelColorXY(x0, y0, c);
|
||||
// if (x0 >= cols || y0 >= rows) break; // WLEDMM we hit the edge - should never happen
|
||||
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
||||
else setPixelColorXY(x0, y0, c);
|
||||
if (x0==x1 && y0==y1) break;
|
||||
int e2 = err;
|
||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||
|
||||
@@ -920,7 +920,8 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
|
||||
case M12_pBar:
|
||||
// expand 1D effect vertically or have it play on virtual strips
|
||||
if (vStrip>0) setPixelColorXY(vStrip - 1, vH - i - 1, col);
|
||||
else for (int x = 0; x < vW; x++) setPixelColorXY(x, vH - i - 1, col);
|
||||
//else for (int x = 0; x < vW; x++) setPixelColorXY(x, vH - i - 1, col);
|
||||
else drawLine(0, vH - i - 1, vW-1, vH - i - 1, col, false); // WLEDMM draw line instead of plotting each pixel
|
||||
break;
|
||||
case M12_pArc:
|
||||
// expand in circular fashion from center
|
||||
@@ -1003,6 +1004,16 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
|
||||
}
|
||||
break;
|
||||
case M12_sPinwheel: {
|
||||
// WLEDMM shortcut when no grouping/spacing used
|
||||
bool simpleSegment = !reverse && (grouping == 1) && (spacing == 0); // !reverse is just for back-to-back testing against "slow" functions
|
||||
uint32_t scaled_col = col;
|
||||
if (simpleSegment) {
|
||||
// segment brightness must be pre-calculated for the "fast" setPixelColorXY variant!
|
||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||
if (!_bri_t && !transitional) return;
|
||||
if (_bri_t < 255) scaled_col = color_fade(col, _bri_t);
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -1039,7 +1050,10 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
|
||||
int x = posx / Fixed_Scale;
|
||||
int y = posy / Fixed_Scale;
|
||||
// set pixel
|
||||
if (x != lastX || y != lastY) setPixelColorXY(x, y, col); // only paint if pixel position is different
|
||||
if (x != lastX || y != lastY) { // only paint if pixel position is different
|
||||
if (simpleSegment) setPixelColorXY_fast(x, y, col, scaled_col, vW, vH);
|
||||
else setPixelColorXY(x, y, col);
|
||||
}
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
// advance to next position
|
||||
@@ -1315,15 +1329,29 @@ void Segment::refreshLightCapabilities() {
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills segment with color
|
||||
* Fills segment with color - WLEDMM using faster sPC if possible
|
||||
*/
|
||||
void Segment::fill(uint32_t c) {
|
||||
if (!isActive()) return; // not active
|
||||
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
||||
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
||||
for(uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) {
|
||||
if (is2D()) setPixelColorXY((uint16_t)x, (uint16_t)y, c);
|
||||
else setPixelColor((uint16_t)x, c);
|
||||
|
||||
if (is2D()) {
|
||||
// pre-calculate scaled color
|
||||
uint32_t scaled_col = c;
|
||||
bool simpleSegment = !reverse && (grouping == 1) && (spacing == 0); // !reverse is just for back-to-back testing against "slow" functions
|
||||
if (simpleSegment) {
|
||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||
if (!_bri_t && !transitional) return;
|
||||
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
|
||||
}
|
||||
// fill 2D segment
|
||||
for(int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||
if (simpleSegment) setPixelColorXY_fast(x, y, c, scaled_col, cols, rows);
|
||||
else setPixelColorXY(x, y, c);
|
||||
}
|
||||
} else { // fill 1D strip
|
||||
for (int x = 0; x < cols; x++) setPixelColor(x, c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user