Skip to content

Commit

Permalink
Overhaul Picasso effect. Change to three entry points via custom ADD_…
Browse files Browse the repository at this point in the history
…EFFECTs

effects.h: create three new entry points. Bump Hexagon Ring.
Picasso3in1.h: zero used FP tables. Don't use custom drawPixelXYF,
drawPixelXY, DrawLine, DrawLineF: use common versions in g().
* Add, use custom entry poins for each of the three major effects - the
passed argument is the number of circles/lines/swoops within each effect
as noted internally in Scale.
* Add JSON jibberizers.
* Let draw() reclibrarte tables when it sees scale change.
effects.cpp: use new entry points.

Fixes #6
  • Loading branch information
robertlipe committed Aug 17, 2023
1 parent fcc51fe commit 554e052
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 161 deletions.
6 changes: 5 additions & 1 deletion include/effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,13 @@
#define EFFECT_MATRIX_SMNOISE_SHIKON 198
#define EFFECT_MATRIX_SMNOISE_COLORCUBE 199

#define EFFECT_MATRIX_SMPICASSO_1 200
#define EFFECT_MATRIX_SMPICASSO_2 201
#define EFFECT_MATRIX_SMPICASSO_3 202

//TODO: Talk to Rutger about impact of changing this.
// Hexagon Effects
#define EFFECT_HEXAGON_OUTER_RING 201
#define EFFECT_HEXAGON_OUTER_RING 301

// Starry Night star variations
#define EFFECT_STAR 1
Expand Down
210 changes: 51 additions & 159 deletions include/effects/matrix/PatternSMFPicasso3in1.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,142 +18,26 @@ class PatternSMPicasso3in1 : public LEDStripEffect
static constexpr int trackingOBJECT_MAX_COUNT = 100U;
// максимальное количество отслеживаемых объектов (очень влияет на
// расход памяти)
float trackingObjectPosX[trackingOBJECT_MAX_COUNT];
float trackingObjectPosY[trackingOBJECT_MAX_COUNT];
float trackingObjectSpeedX[trackingOBJECT_MAX_COUNT];
float trackingObjectSpeedY[trackingOBJECT_MAX_COUNT];
float trackingObjectShift[trackingOBJECT_MAX_COUNT];
uint8_t trackingObjectHue[trackingOBJECT_MAX_COUNT];
uint8_t trackingObjectState[trackingOBJECT_MAX_COUNT];
bool trackingObjectIsShift[trackingOBJECT_MAX_COUNT];
float trackingObjectPosX[trackingOBJECT_MAX_COUNT] {0};
float trackingObjectPosY[trackingOBJECT_MAX_COUNT] {0};
float trackingObjectSpeedX[trackingOBJECT_MAX_COUNT] {0};
float trackingObjectSpeedY[trackingOBJECT_MAX_COUNT] {0};
float trackingObjectShift[trackingOBJECT_MAX_COUNT] {0};
uint8_t trackingObjectHue[trackingOBJECT_MAX_COUNT] {0};
uint8_t trackingObjectState[trackingOBJECT_MAX_COUNT] {0};
bool trackingObjectIsShift[trackingOBJECT_MAX_COUNT] {0};
static constexpr int enlargedOBJECT_MAX_COUNT = (MATRIX_WIDTH * 2);
// максимальное количество сложных отслеживаемых объектов
// (меньше, чем trackingOBJECT_MAX_COUNT)
uint8_t enlargedObjectNUM; // используемое в эффекте количество объектов
long enlargedObjectTime[enlargedOBJECT_MAX_COUNT];

// функция отрисовки точки по координатам X Y
void drawPixelXYF(float x, float y, CRGB color) const
{
y = MATRIX_HEIGHT - 1 - y;
if (!g()->isValidPixel(x,y))
return;
// uint32_t thisPixel = XY((uint8_t)x, (uint8_t)y);
// NightDriver's coordinate system is dfferent. Invert height and this all
// works!
uint32_t thisPixel = XY((uint8_t)x, (uint8_t)y);
g()->leds[thisPixel] = color;
}

// функция отрисовки точки по координатам X Y
void drawPixelXY(int x, int y, CRGB color) const
{
y = MATRIX_HEIGHT - 1 - y;
if (!g()->isValidPixel(x,y))
return;
uint32_t thisPixel = XY(x, y);
g()->leds[thisPixel] = color;
}

// ------------------------------ Дополнительные функции рисования
// ----------------------
void DrawLine(int x1, int y1, int x2, int y2, CRGB color) const
{
int deltaX = std::abs(x2 - x1);
int deltaY = std::abs(y2 - y1);
int signX = x1 < x2 ? 1 : -1;
int signY = y1 < y2 ? 1 : -1;
int error = deltaX - deltaY;

drawPixelXY(x2, y2, color);
while (x1 != x2 || y1 != y2)
{
drawPixelXY(x1, y1, color);
int error2 = error * 2;
if (error2 > -deltaY)
{
error -= deltaY;
x1 += signX;
}
if (error2 < deltaX)
{
error += deltaX;
y1 += signY;
}
}
}

void DrawLineF(float x1, float y1, float x2, float y2, CRGB color) const
{
float deltaX = fabs(x2 - x1);
float deltaY = fabs(y2 - y1);
float error = deltaX - deltaY;

float signX = x1 < x2 ? 0.5 : -0.5;
float signY = y1 < y2 ? 0.5 : -0.5;

while (x1 != x2 || y1 != y2)
{ // (true) - а я то думаю - "почему функция часто вызывает
// вылет по вачдогу?" А оно вон оно чё, Михалычь!
if ((signX > 0 && x1 > x2 + signX) || (signX < 0 && x1 < x2 + signX))
break;
if ((signY > 0 && y1 > y2 + signY) || (signY < 0 && y1 < y2 + signY))
break;
drawPixelXYF(x1, y1,
color); // интересно, почему тут было обычное drawPixelXY() ???
float error2 = error;
if (error2 > -deltaY)
{
error -= deltaY;
x1 += signX;
}
if (error2 < deltaX)
{
error += deltaX;
y1 += signY;
}
}
}

// We use our own drawCircle() and drawPixel() because we KNOW we're going to
// draw near edges and the system versions scribble on memory when we do. Ours
// clamp.
void drawCircle(uint x0, uint y0, int radius, const CRGB &color) const
{
int a = radius, b = 0;
int radiusError = 1 - a;

if (radius == 0)
{
drawPixelXY(x0, y0, color);
return;
}

while (a >= b)
{
drawPixelXY(a + x0, b + y0, color);
drawPixelXY(b + x0, a + y0, color);
drawPixelXY(-a + x0, b + y0, color);
drawPixelXY(-b + x0, a + y0, color);
drawPixelXY(-a + x0, -b + y0, color);
drawPixelXY(-b + x0, -a + y0, color);
drawPixelXY(a + x0, -b + y0, color);
drawPixelXY(b + x0, -a + y0, color);
b++;
if (radiusError < 0)
radiusError += 2 * b + 1;
else
{
a--;
radiusError += 2 * (b - a + 1);
}
}
}
long enlargedObjectTime[enlargedOBJECT_MAX_COUNT] {0};
int _scale{-1};
const String _name;

void PicassoGenerate(bool reset)
{
static int loadingFlag = true;
if (loadingFlag)
if (reset || loadingFlag)
{
loadingFlag = false;
if (enlargedObjectNUM > enlargedOBJECT_MAX_COUNT)
Expand Down Expand Up @@ -222,7 +106,7 @@ class PatternSMPicasso3in1 : public LEDStripEffect

for (uint8_t i = 0; i < enlargedObjectNUM - 2U; i += 2)
{
DrawLine(trackingObjectPosX[i], trackingObjectPosY[i], trackingObjectPosX[i + 1U],
g()->drawLine(trackingObjectPosX[i], trackingObjectPosY[i], trackingObjectPosX[i + 1U],
trackingObjectPosY[i + 1U], CHSV(trackingObjectHue[i], 255U, 255U));
// DrawLine(trackingObjectPosX[i], trackingObjectPosY[i],
// trackingObjectPosX[i+1U], trackingObjectPosY[i+1U],
Expand All @@ -240,7 +124,7 @@ class PatternSMPicasso3in1 : public LEDStripEffect
g()->DimAll(180);

for (uint8_t i = 0; i < enlargedObjectNUM - 1U; i++)
DrawLineF(trackingObjectPosX[i], trackingObjectPosY[i], trackingObjectPosX[i + 1U],
g()->drawLine(trackingObjectPosX[i], trackingObjectPosY[i], trackingObjectPosX[i + 1U],
trackingObjectPosY[i + 1U], CHSV(trackingObjectHue[i], 255U, 255U));

EVERY_N_MILLIS(20000)
Expand All @@ -257,7 +141,7 @@ class PatternSMPicasso3in1 : public LEDStripEffect
g()->DimAll(180);

for (uint8_t i = 0; i < enlargedObjectNUM - 2U; i += 2)
drawCircle(fabs(trackingObjectPosX[i] - trackingObjectPosX[i + 1U]),
g()->DrawSafeCircle(fabs(trackingObjectPosX[i] - trackingObjectPosX[i + 1U]),
fabs(trackingObjectPosY[i] - trackingObjectPosX[i + 1U]),
fabs(trackingObjectPosX[i] - trackingObjectPosY[i]), CHSV(trackingObjectHue[i], 255U, 255U));

Expand All @@ -269,18 +153,37 @@ class PatternSMPicasso3in1 : public LEDStripEffect
}

public:
PatternSMPicasso3in1() : LEDStripEffect(EFFECT_MATRIX_SMPICASSO3IN1, "Picasso")
PatternSMPicasso3in1() : LEDStripEffect(EFFECT_MATRIX_SMPICASSO3IN1, "Picasso"), _scale(-1)
{
}

PatternSMPicasso3in1(const JsonObjectConst &jsonObject) : LEDStripEffect(jsonObject)
PatternSMPicasso3in1(const String& name, int scale) : LEDStripEffect(EFFECT_MATRIX_SMPICASSO3IN1, name), _name(name), _scale(scale)
{
}

// This has atomicity issues. It looks at a global (boooo) that may change the
// contents of the underlying enlarge/trackingFOO arrays while they're being
// traversed. It's just a bad diea to modify Scale while these are running,
// but there's too much cool code in this effect to just let it go to waste.

PatternSMPicasso3in1(const JsonObjectConst &jsonObject) : LEDStripEffect(jsonObject), _scale(jsonObject["scale"])
{
}

virtual bool SerializeToJSON(JsonObject& jsonObject) override
{
StaticJsonDocument<128> jsonDoc;

JsonObject root = jsonDoc.to<JsonObject>();
LEDStripEffect::SerializeToJSON(root);

jsonDoc["scale"] = _scale;

return jsonObject.set(jsonDoc.as<JsonObjectConst>());
}


// This has atomicity issues. It looks at a global (boooo) that
// may change the contents of the underlying enlarge/trackingFOO
// arrays while they're being traversed. It's just a bad diea
// to modify Scale while these are running, so we try to do it
// only when Scale changes.

void RecalibrateDrawnObjects()
{
Expand All @@ -295,34 +198,23 @@ class PatternSMPicasso3in1 : public LEDStripEffect
void Start() override
{
g()->Clear();
Scale = _scale;
RecalibrateDrawnObjects();
}

void Draw() override
{
// Mesmerizer/NightDriver demo: just pick some preset and skip through them.
// Good way to demo off this module, but it's a bit much visually!
// robert
// An entry of 6 does so much work it trips the watchdog!
// An entry of 45 does so much work it trips the watchdog!
static int demo_values[] = {3, 35, 68};
static int demo_idx = 0;

// BUGBUG(robertl): Just eyeballing this, I think the clock is running about
// double time...
EVERY_N_MILLIS(10000)
{
if (demo_idx++ == sizeof(demo_values) / sizeof(demo_values[0]))
demo_idx = 0;
Scale = demo_values[demo_idx];
// RecalibrateDrawnObjects();
debugI("Index %d Scale %d", demo_idx, Scale);
// delay(10);
}
// end robert
static int last_scale = _scale;

// Force a recalibration on effect change.
if (last_scale != Scale) {
debugA("Recalibrating from %d to %d", last_scale, Scale);
PicassoGenerate(true);
last_scale = Scale;
}

Scale = _scale;

// Don't just let the renderer freewheel.
// Unfortunately, this is a terrible way to implement usage governors.
if (Scale < 34U) // если масштаб до 34
PicassoRoutine1();
else if (Scale > 67U) // если масштаб больше 67
Expand Down
6 changes: 5 additions & 1 deletion src/effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,11 @@ void LoadEffectFactories()

ADD_EFFECT(EFFECT_MATRIX_SMNOISE, PatternSMNoise);
ADD_EFFECT(EFFECT_MATRIX_SM2DDPR, PatternSM2DDPR);
ADD_EFFECT(EFFECT_MATRIX_SMPICASSO3IN1, PatternSMPicasso3in1);
// ADD_EFFECT(EFFECT_MATRIX_SMPICASSO3IN1, PatternSMPicasso3in1);
ADD_EFFECT(EFFECT_MATRIX_SMPICASSO_1, PatternSMPicasso3in1, "Picasso 1", 12);
ADD_EFFECT(EFFECT_MATRIX_SMPICASSO_2, PatternSMPicasso3in1, "Picasso 2", 38);
ADD_EFFECT(EFFECT_MATRIX_SMPICASSO_3, PatternSMPicasso3in1, "Picasso 3", 73);

ADD_EFFECT(EFFECT_MATRIX_SMAMBERRAIN, PatternSMAmberRain);
ADD_EFFECT(EFFECT_MATRIX_SMSTROBE_DIFFUSION,PatternSMStrobeDiffusion);
ADD_EFFECT(EFFECT_MATRIX_SMRAINBOW_TUNNEL, PatternSMRainbowTunnel);
Expand Down

0 comments on commit 554e052

Please sign in to comment.