Skip to content

Commit

Permalink
Add Rotate Projection and Mario test effect
Browse files Browse the repository at this point in the history
Rotation by shearing, prevents holes.
Added Mario test effect to test projections.
  • Loading branch information
Brandon502 committed Aug 17, 2024
1 parent 76350d8 commit 025f280
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 0 deletions.
46 changes: 46 additions & 0 deletions src/App/LedEffects.h
Original file line number Diff line number Diff line change
Expand Up @@ -2823,6 +2823,52 @@ class PixelMapEffect: public Effect {
}
}; // PixelMap

class MarioTestEffect: public Effect {
const char * name() {return "MarioTest";}
uint8_t dim() {return _2D;}
const char * tags() {return "💫";}

void loop(LedsLayer &leds) {
bool background = leds.effectData.read<bool>();
uint8_t offsetX = leds.effectData.read<uint8_t>();
uint8_t offsetY = leds.effectData.read<uint8_t>();

const uint8_t mario[16][16] = {
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 0, 2, 2, 2, 3, 3, 4, 3, 0, 0, 0, 0, 0},
{0, 0, 0, 2, 3, 2, 3, 3, 3, 4, 3, 3, 3, 0, 0, 0},
{0, 0, 0, 2, 3, 2, 2, 3, 3, 3, 4, 3, 3, 3, 0, 0},
{0, 0, 0, 0, 2, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0, 0},
{0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 5, 5, 1, 5, 5, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 5, 5, 5, 1, 5, 5, 1, 5, 5, 5, 0, 0, 0},
{0, 0, 5, 5, 5, 5, 1, 5, 5, 1, 5, 5, 5, 5, 0, 0},
{0, 0, 3, 3, 5, 5, 1, 1, 1, 1, 5, 5, 3, 3, 0, 0},
{0, 0, 3, 3, 3, 1, 6, 1, 1, 6, 1, 3, 3, 3, 0, 0},
{0, 0, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 0, 0},
{0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0},
{0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0}
};

CRGB colors[7] = {CRGB::DimGrey, CRGB::Red, CRGB::Brown, CRGB::Tan, CRGB::Black, CRGB::Blue, CRGB::Yellow};

if (background) leds.fill_solid(CRGB::DimGrey);
else leds.fill_solid(CRGB::Black);
//draw 16x16 mario
for (int x = 0; x < 16; x++) for (int y = 0; y < 16; y++) {
leds[Coord3D({x + offsetX, y + offsetY, 0})] = colors[mario[y][x]];
}
}

void controls(LedsLayer &leds, JsonObject parentVar) {
ui->initCheckBox(parentVar, "Background", leds.effectData.write<bool>(false));
ui->initSlider(parentVar, "OffsetX", leds.effectData.write<uint8_t>(leds.size.x/2 - 8), 0, leds.size.x - 16);
ui->initSlider(parentVar, "OffsetY", leds.effectData.write<uint8_t>(leds.size.y/2 - 8), 0, leds.size.y - 16);
}
}; // MarioTest

#ifdef STARBASE_USERMOD_LIVE

class LiveScriptEffect: public Effect {
Expand Down
1 change: 1 addition & 0 deletions src/App/LedLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ enum ProjectionsE
p_Scrolling,
p_Acceleration,
p_Checkerboard,
p_Rotate,
p_count // keep as last entry
};

Expand Down
2 changes: 2 additions & 0 deletions src/App/LedModEffects.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class LedModEffects:public SysModule {
effects.push_back(new RubiksCubeEffect);
effects.push_back(new SphereMoveEffect);
effects.push_back(new PixelMapEffect);
effects.push_back(new MarioTestEffect);

#ifdef STARBASE_USERMOD_LIVE
effects.push_back(new LiveScriptEffect);
Expand All @@ -140,6 +141,7 @@ class LedModEffects:public SysModule {
fixture.projections.push_back(new ScrollingProjection);
fixture.projections.push_back(new AccelerationProjection);
fixture.projections.push_back(new CheckerboardProjection);
fixture.projections.push_back(new RotateProjection);

#ifdef STARLIGHT_CLOCKLESS_LED_DRIVER
#if !(CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2)
Expand Down
128 changes: 128 additions & 0 deletions src/App/LedProjections.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,22 @@ class TiltPanRollProjection: public Projection {
public:

void setup(LedsLayer &leds, Coord3D &sizeAdjusted, Coord3D &pixelAdjusted, Coord3D &midPosAdjusted, Coord3D &mapped, uint16_t &indexV) {
// adjustSizeAndPixel(leds, sizeAdjusted, pixelAdjusted, midPosAdjusted); // Uncomment to expand grid to fill corners
DefaultProjection dp;
dp.setup(leds, sizeAdjusted, pixelAdjusted, midPosAdjusted, mapped, indexV);
}

void adjustSizeAndPixel(LedsLayer &leds, Coord3D &sizeAdjusted, Coord3D &pixelAdjusted, Coord3D &midPosAdjusted) {
uint8_t size = max(sizeAdjusted.x, max(sizeAdjusted.y, sizeAdjusted.z));
size = sqrt(size * size * 2) + 1;
Coord3D offset = {(size - sizeAdjusted.x) / 2, (size - sizeAdjusted.y) / 2, 0};
sizeAdjusted = Coord3D{size, size, 1};

pixelAdjusted.x += offset.x;
pixelAdjusted.y += offset.y;
pixelAdjusted.z += offset.z;
}

void adjustXYZ(LedsLayer &leds, Coord3D &pixel) {
#ifdef STARBASE_USERMOD_MPU6050
if (leds.proGyro) {
Expand Down Expand Up @@ -862,6 +874,122 @@ class CheckerboardProjection: public Projection {
}
}; //CheckerboardProjection

class RotateProjection: public Projection {
const char * name() {return "Rotate";}
const char * tags() {return "💫";}

public:

void setup(LedsLayer &leds, Coord3D &sizeAdjusted, Coord3D &pixelAdjusted, Coord3D &midPosAdjusted, Coord3D &mapped, uint16_t &indexV) {
adjustSizeAndPixel(leds, sizeAdjusted, pixelAdjusted, midPosAdjusted);
DefaultProjection dp;
dp.setup(leds, sizeAdjusted, pixelAdjusted, midPosAdjusted, mapped, indexV);
}

void adjustSizeAndPixel(LedsLayer &leds, Coord3D &sizeAdjusted, Coord3D &pixelAdjusted, Coord3D &midPosAdjusted) {
leds.projectionData.begin();
bool expand = leds.projectionData.read<bool>();
Coord3D *halfSize = leds.projectionData.readWrite<Coord3D>();
if (expand) {
uint8_t size = max(sizeAdjusted.x, max(sizeAdjusted.y, sizeAdjusted.z));
size = sqrt(size * size * 2) + 1;
Coord3D offset = {(size - sizeAdjusted.x) / 2, (size - sizeAdjusted.y) / 2, 0};
sizeAdjusted = Coord3D{size, size, 1};
pixelAdjusted.x += offset.x;
pixelAdjusted.y += offset.y;
pixelAdjusted.z += offset.z;
}
*halfSize = sizeAdjusted / 2;
}

void adjustXYZ(LedsLayer &leds, Coord3D &pixel) {
if (leds.proRollSpeed == 0) return;
leds.projectionData.begin();
bool expand = leds.projectionData.read<bool>(); // Not used
Coord3D halfSize = leds.projectionData.read<Coord3D>();
int *prevAngle = leds.projectionData.readWrite<int>();
float *shearX = leds.projectionData.readWrite<float>();
float *shearY = leds.projectionData.readWrite<float>();
bool *flip = leds.projectionData.readWrite<bool>();
bool freeze = leds.projectionData.read<bool>();

int angle = sys->now * 5 / (255 - leds.proRollSpeed);

if (angle != *prevAngle && !freeze) {
*prevAngle = angle;
angle %= 360;
angle -= 180;
if (angle >= -90 && angle <= 90) *flip = false;
else {*flip = true; angle = angle - 180;}
// calculate shearX and shearY
float angleRadians = radians(angle);
*shearX = -tan(angleRadians / 2);
*shearY = sin(angleRadians);
}

if (*flip) {
// Reverse x and y values
pixel.x = leds.size.x - pixel.x;
pixel.y = leds.size.y - pixel.y;
}

// Translate pixel to origin
int dx = pixel.x - halfSize.x;
int dy = pixel.y - halfSize.y;

// // Apply the first shear on x
int x1 = dx + round(*shearX * dy);

// Apply the shear on y
int y1 = dy + round(*shearY * x1);

// Apply the second shear on x
int x2 = x1 + round(*shearX * y1);

// Translate pixel back and assign
pixel.x = x2 + halfSize.x;
pixel.y = y1 + halfSize.y;
pixel.z = 0;

// Clamp the pixel to the bounds
if (pixel.x < 0) pixel.x = 0;
else if (pixel.x >= leds.size.x) pixel.x = leds.size.x - 1;
if (pixel.y < 0) pixel.y = 0;
else if (pixel.y >= leds.size.y) pixel.y = leds.size.y - 1;
}

void controls(LedsLayer &leds, JsonObject parentVar) {
leds.projectionData.begin();
bool *expand = leds.projectionData.write<bool>(false);
Coord3D *halfSize = leds.projectionData.write<Coord3D>(leds.size/2);
int *prevAngle = leds.projectionData.write<int>(0);
float *shearX = leds.projectionData.write<float>(0);
float *shearY = leds.projectionData.write<float>(0);
bool *flip = leds.projectionData.write<bool>(false);
bool *freeze = leds.projectionData.write<bool>(false);

ui->initButton(parentVar, "Freeze", false, [freeze](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case onChange:
*freeze = !*freeze;
return true;
default: return false;
}});
ui->initSlider(parentVar, "Rotate Speed", 128, 0, 254, false, [&leds](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case onChange:
if (rowNr < leds.fixture->layers.size())
leds.fixture->layers[rowNr]->proRollSpeed = mdl->getValue(var, rowNr);
return true;
default: return false;
}});
ui->initCheckBox(parentVar, "Expand", expand, false, [&leds](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun
case onChange:
leds.fixture->layers[rowNr]->triggerMapping();
return true;
default: return false;
}});
}
}; //RotateProjection

class TestProjection: public Projection {
const char * name() {return "Test";}
const char * tags() {return "💡";}
Expand Down

0 comments on commit 025f280

Please sign in to comment.