Skip to content

Commit

Permalink
Add Multiply and Rotate projection, fix gen serpentine, ring241 bugfix
Browse files Browse the repository at this point in the history
AppFixture:
- projectAndMap: a bit of refactoring but WIP!!!
- add Multiply and rotate projection

AppLeds: add spinXY raw code WIP and add to XYZ function (if rotate projection)

AppModFixtureGen:
- matrix: implement serpentine
- matrix 4x32x8, corrections
- pin: set remaining rows to same pin
- rings241: bug fix in2out

AppModLeds:
- fx and pro: deal with value changes where no rowNr provided (e.g. from curl and other instances)
- add multiply and rotate effects

SysModFiles: fileTbl: addRow: set rowNr

SysModModel:
- don't save stage property
- Coord3D add / and /= operator
- varPostDetails: use childVar iterator so null values can be properly removed

SysModWeb: add upd info

UserModInstances
- update udp Info
- sendSysInfoUDP: if valArray, send [0]
  • Loading branch information
ewowi committed Mar 1, 2024
1 parent 4f179dc commit 45ba553
Show file tree
Hide file tree
Showing 15 changed files with 1,279 additions and 1,110 deletions.
2 changes: 1 addition & 1 deletion data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -747,9 +747,9 @@ function changeHTML(variable, commandJson, rowNr = UINT8_MAX) {
//hasOwnProperty needed to catch also boolean commandJson.value when it is false !!!!

// if (node.id=="insName#0" || node.id=="fx")// || node.id=="mdlEnabled" || node.id=="clIsFull" || node.id=="pin2")
// console.log("changeHTML value", variable, node, commandJson, rowNr);
if (nodeType == "table") {
if (Array.isArray(commandJson.value)) {
console.log("changeHTML value table", variable, node, commandJson, rowNr);
//remove table rows
let tbodyNode = cE('tbody'); //the tbody of node will be replaced
//replace the table body
Expand Down
2 changes: 1 addition & 1 deletion src/App/AppEffects.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Effect {
default: return false;
}});
//tbd: check if memory is freed!
currentVar["stage"] = true;
// currentVar["stage"] = true;
}

CRGBPalette16 getPalette() {
Expand Down
171 changes: 94 additions & 77 deletions src/App/AppFixture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ void Fixture::projectAndMap() {
StarModJson starModJson(fileName); //open fileName for deserialize

// for (std::vector<Leds *>::iterator leds=ledsList.begin(); leds!=ledsList.end() && leds->doMap; ++leds) {
uint8_t rowNr = 0;
for (Leds *leds: ledsList) {
if (leds->doMap) {
USER_PRINTF("Leds %d %d\n", leds->fx, ledsList.size());
USER_PRINTF("Leds pre [%d] f:%d p:%d s:%d\n", rowNr, leds->fx, leds->projectionNr, ledsList.size());
//vectors really gone now?
for (std::vector<std::vector<uint16_t>> ::iterator physMap=leds->mappingTable.begin(); physMap!=leds->mappingTable.end(); ++physMap)
physMap->clear();
leds->mappingTable.clear();
}
rowNr++;
}

//deallocate all led pins
Expand Down Expand Up @@ -75,7 +77,7 @@ void Fixture::projectAndMap() {
// USER_PRINTF(" %d", num);
// USER_PRINTF("\n");

if (uint16CollectList.size()>=1) {
if (uint16CollectList.size()>=1) { // a pixel

Coord3D pixel; //in mm !
pixel.x = uint16CollectList[0];
Expand All @@ -84,89 +86,99 @@ void Fixture::projectAndMap() {

// USER_PRINTF("led %d,%d,%d start %d,%d,%d end %d,%d,%d\n",x,y,z, startPos.x, startPos.y, startPos.z, endPos.x, endPos.y, endPos.z);

// for (Leds leds:ledsList) {
//vector iterator needed to get the pointer to leds as we need to update leds, also vector iteration on classes is faster!!!
//search: ^(?=.*\bfor\b)(?=.*\b:\b).*$
// for (std::vector<Leds *>::iterator leds=ledsList.begin(); leds!=ledsList.end() && leds->doMap; ++leds) {
uint8_t rowNr = 0;
for (Leds *leds: ledsList) {
if (leds->doMap) {

//set start and endPos between bounderies of fixture
Coord3D startPosAdjusted = (leds->startPos).minimum(size - Coord3D{1,1,1}) * 10;
Coord3D endPosAdjusted = (leds->endPos).minimum(size - Coord3D{1,1,1}) * 10;
Coord3D projSize = (endPosAdjusted - startPosAdjusted).absx()/10 + Coord3D{1,1,1};

mdl->setValue("fxStart", startPosAdjusted/10, rowNr); //rowNr
mdl->setValue("fxEnd", endPosAdjusted/10, rowNr); //rowNr

if (pixel >= startPosAdjusted && pixel <= endPosAdjusted ) { //if pixel between start and end pos
// 0 to 3D depending on start and endpos (e.g. to display ScrollingText on one side of a cube)
uint8_t projectionDimension = 0;
if (projSize.x > 1) projectionDimension++;
if (projSize.y > 1) projectionDimension++;
if (projSize.z > 1) projectionDimension++;

Coord3D projSize = (endPosAdjusted - startPosAdjusted).absx()/10 + Coord3D{1,1,1};
// mdl->setValue("fxStart", startPosAdjusted/10, rowNr); //rowNr
// mdl->setValue("fxEnd", endPosAdjusted/10, rowNr); //rowNr

// 0 to 3D depending on start and endpos (e.g. to display ScrollingText on one side of a cube)
uint8_t projectionDimension = 0;
if (projSize.x > 1) projectionDimension++;
if (projSize.y > 1) projectionDimension++;
if (projSize.z > 1) projectionDimension++;
//only needed one time
//does not work for some reason...

//only needed one time
Coord3D split = mdl->getValue("proSplit", rowNr);

// if (indexP == 0) { //first
{
uint16_t maxDistance = distance(endPosAdjusted, startPosAdjusted) / 10;
// USER_PRINTF("maxDistance %d %d,%d,%d %d,%d,%d %d,%d,%d\n", maxDistance, pixel.x, pixel.y, pixel.z, startPosAdjusted.x, startPosAdjusted.y, startPosAdjusted.z, endPosAdjusted.x, endPosAdjusted.y, endPosAdjusted.z);
// if (indexP == 0) //first
{
uint16_t maxDistance = distance(endPosAdjusted, startPosAdjusted) / 10;
// USER_PRINTF("maxDistance %d %d,%d,%d %d,%d,%d %d,%d,%d\n", maxDistance, pixel.x, pixel.y, pixel.z, startPosAdjusted.x, startPosAdjusted.y, startPosAdjusted.z, endPosAdjusted.x, endPosAdjusted.y, endPosAdjusted.z);

float scale = 1;
switch (leds->effectDimension) {
case _1D:
leds->size.x = maxDistance;
leds->size.y = 1;
leds->size.z = 1;
break;
case _2D:
switch(projectionDimension) {
case _1D:
leds->size = map1Dto2D(projSize);
// leds->size.x = sqrt(projSize.x * projSize.y * projSize.z); //only one is > 1, square root
// leds->size.y = leds->size.x;
break;
case _2D:
float scale = 1;
switch (leds->effectDimension) {
case _1D:
leds->size.x = maxDistance;
leds->size.y = 1;
leds->size.z = 1;
break;
case _2D:
switch(projectionDimension) {
case _1D:
leds->size = map1Dto2D(projSize);
// leds->size.x = sqrt(projSize.x * projSize.y * projSize.z); //only one is > 1, square root
// leds->size.y = leds->size.x;
break;
case _2D:
if (leds->projectionNr == p_Multiply) {
leds->size = map2Dto2D(projSize) / split;
// USER_PRINTF("Multiply %d,%d,%d\n", leds->size.x, leds->size.y, leds->size.z);
}
else
leds->size = map2Dto2D(projSize);
break;
case _3D:
leds->size.x = projSize.x + projSize.y;
leds->size.y = projSize.z;
leds->size.z = 1;
break;
}
case _3D:
switch(projectionDimension) {
case _1D:
leds->size.x = std::pow(projSize.x * projSize.y * projSize.z, 1/3.); //only one is > 1, cube root
leds->size.y = leds->size.x;
leds->size.z = leds->size.x;
break;
case _2D:
leds->size.x = projSize.x; //2 of the 3 sizes are > 1, so one dimension of the effect is 1
leds->size.y = projSize.y;
leds->size.z = projSize.z;
break;
case _3D:
leds->size.x = projSize.x;
leds->size.y = projSize.y;
leds->size.z = projSize.z;
break;
}

//scaling (check rounding errors)
//1024 crash in makebuffer...
// if (leds->size.x * leds->size.y > 256)
// scale = (sqrt((float)256.0 / (leds->size.x * leds->size.y))); //avoid high virtual resolutions
// leds->size.x *= scale;
// leds->size.y *= scale;
}
leds->nrOfLeds = leds->size.x * leds->size.y * leds->size.z;
// USER_PRINTF("first [%d] s:%d,%d,%d e:%d,%d,%d s:%d,%d,%d\n", rowNr, startPosAdjusted.x, startPosAdjusted.y, startPosAdjusted.z, endPosAdjusted.x, endPosAdjusted.y, endPosAdjusted.z, leds->size.x, leds->size.y, leds->size.z);
} //only one time
break;
case _3D:
leds->size.x = projSize.x + projSize.y;
leds->size.y = projSize.z;
leds->size.z = 1;
break;
}
break;
case _3D:
switch(projectionDimension) {
case _1D:
leds->size.x = std::pow(projSize.x * projSize.y * projSize.z, 1/3.); //only one is > 1, cube root
leds->size.y = leds->size.x;
leds->size.z = leds->size.x;
break;
case _2D:
leds->size.x = projSize.x; //2 of the 3 sizes are > 1, so one dimension of the effect is 1
leds->size.y = projSize.y;
leds->size.z = projSize.z;
break;
case _3D:
leds->size.x = projSize.x;
leds->size.y = projSize.y;
leds->size.z = projSize.z;
break;
}

break;
//scaling (check rounding errors)
//1024 crash in makebuffer...
// if (leds->size.x * leds->size.y > 256)
// scale = (sqrt((float)256.0 / (leds->size.x * leds->size.y))); //avoid high virtual resolutions
// leds->size.x *= scale;
// leds->size.y *= scale;
}
leds->nrOfLeds = leds->size.x * leds->size.y * leds->size.z;
} //only one time

if (indexP == 0)
USER_PRINTF("first [%d] s:%d,%d,%d e:%d,%d,%d s:%d,%d,%d mt:%d\n", rowNr, startPosAdjusted.x, startPosAdjusted.y, startPosAdjusted.z, endPosAdjusted.x, endPosAdjusted.y, endPosAdjusted.z, leds->size.x, leds->size.y, leds->size.z, leds->mappingTable.size());

if (pixel >= startPosAdjusted && pixel <= endPosAdjusted ) { //if pixel between start and end pos

// if (leds->fx == 11) { //lines2D
// // USER_PRINTF(" XXX %d %d %d %d, %d, %d", leds->projectionNr, leds->effectDimension, projectionDimension, pixel.x, pixel.y, pixel.z);
Expand All @@ -185,6 +197,8 @@ void Fixture::projectAndMap() {
case p_Random:
break;
case p_Default:
case p_Multiply:
case p_Rotate:
case p_DistanceFromPoint:
if (leds->effectDimension == _1D) {
indexV = distance(pixel, startPosAdjusted) / 10;
Expand All @@ -205,6 +219,11 @@ void Fixture::projectAndMap() {
indexV = leds->XYZ(map1Dto2D((pixel - startPosAdjusted)/10));
else if (projectionDimension == _2D) {
Coord3D mapped = map2Dto2D(pixel - startPosAdjusted);
if (leds->projectionNr == p_Multiply) {
mapped.x = mapped.x % (leds->size.x*10);
mapped.y = mapped.y % (leds->size.y*10);
mapped.z = mapped.y % (leds->size.z*10);
}
indexV = leds->XYZ(mapped/10);
// USER_PRINTF("map2Dto2D %d-%d p:%d,%d,%d m:%d,%d,%d\n", indexV, indexP, pixel.x, pixel.y, pixel.z, mapped.x, mapped.y, mapped.z);

Expand Down Expand Up @@ -232,8 +251,6 @@ void Fixture::projectAndMap() {
break;
case p_Mirror:
break;
case p_Multiply:
break;
case p_Fun: //first attempt for distance from Circle 2D
if (leds->effectDimension == _2D) {
if (projectionDimension == _2D) {
Expand All @@ -256,7 +273,7 @@ void Fixture::projectAndMap() {

if (indexV != UINT16_MAX) {
if (indexV >= leds->nrOfLeds || indexV >= NUM_LEDS_Max) {
USER_PRINTF("dev pre [%d] indexV too high %d>=%d or %d (m:%d p:%d) p:%d,%d,%d\n", rowNr, indexV, leds->nrOfLeds, NUM_LEDS_Max, leds->mappingTable.size(), indexP, pixel.x, pixel.y, pixel.z);
USER_PRINTF("dev pre [%d] indexV too high %d>=%d or %d (m:%d p:%d) p:%d,%d,%d s:%d,%d,%d\n", rowNr, indexV, leds->nrOfLeds, NUM_LEDS_Max, leds->mappingTable.size(), indexP, pixel.x, pixel.y, pixel.z, leds->size.x, leds->size.y, leds->size.z);
}
else {
//post processing: inverse mapping
Expand Down Expand Up @@ -368,18 +385,18 @@ void Fixture::projectAndMap() {
// for (std::vector<Leds *>::iterator leds=ledsList.begin(); leds!=ledsList.end() && leds->doMap; ++leds) {
for (Leds *leds: ledsList) {
if (leds->doMap) {
USER_PRINTF("leds loop %d %d\n", rowNr, leds->fx);
USER_PRINTF("Leds pre [%d] f:%d p:%d s:%d\n", rowNr, leds->fx, leds->projectionNr, ledsList.size());

uint16_t nrOfMappings = 0;
uint16_t nrOfPixels = 0;

if (leds->projectionNr <= p_Random) {
if (leds->projectionNr == p_Random || leds->projectionNr == p_None) {

//defaults
leds->size = size;
leds->nrOfLeds = nrOfLeds;

} else if (leds->projectionNr > p_Random) {
} else {

// if (leds->mappingTable.size() < leds->size.x * leds->size.y * leds->size.z)
// USER_PRINTF("mapping add extra physMap %d of %d %d,%d,%d\n", leds->mappingTable.size(), leds->size.x * leds->size.y * leds->size.z, leds->size.x, leds->size.y, leds->size.z);
Expand All @@ -402,8 +419,8 @@ void Fixture::projectAndMap() {
}

// USER_PRINTF("\n");
nrOfMappings++;
}
nrOfMappings++;
// else
// USER_PRINTF("ledV %d no mapping\n", x);
indexV++;
Expand Down
14 changes: 0 additions & 14 deletions src/App/AppFixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,6 @@
#define _2D 2
#define _3D 3

enum Projections
{
p_None,
p_Random,
p_Default,
p_DistanceFromPoint,
p_Reverse,
p_Mirror,
p_Multiply,
p_Kaleidoscope,
p_Fun,
p_count
};


class Leds; //forward

Expand Down
63 changes: 62 additions & 1 deletion src/App/AppLeds.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,25 @@
#include "../data/font/console_font_6x8.h"
#include "../data/font/console_font_7x9.h"

enum Projections
{
p_Default,
p_Multiply,
p_Rotate,
p_DistanceFromPoint,
p_None,
p_Random,
p_Fun,
p_Reverse,
p_Mirror,
p_Kaleidoscope,
p_count
};

class Fixture; //forward



//StarMod implementation of segment.data
class SharedData {

Expand Down Expand Up @@ -79,6 +94,46 @@ class SharedData {

};

static float sinrot = 0.0f;
static float cosrot = 1.0f;
static unsigned long last_millis = UINT_MAX;

constexpr float projScaleMax = 1.0f; // full size
constexpr float projScaleMin = 0.701f; // 1/sqrt(2)
static float projScale = projScaleMax;

static Coord3D spinXY(uint_fast16_t x, uint_fast16_t y, uint_fast16_t width, uint_fast16_t height) {
if ((millis()/12) != last_millis) {
// update sin / cos for rotation - once each 12ms
float now = float(millis()/12) / 160.0f; // this sets the rotation speed
//float now = float(strip.now) / 2000.0f; // error: 'strip' was not declared in this scope
sinrot = sinf(now);
cosrot = cosf(now);
last_millis = millis()/12;
// scale to fit - comment out the next lines to disable
float maxProj = max(abs(width/2 * sinrot), abs(height/2 * cosrot));
int maxdim = max(width/2, height/2);
float newScaling = maxProj / float(maxdim);
projScale = max(min(newScaling, projScaleMax), projScaleMin);
}
// center
int x1 = int(x) - width/2;
int y1 = int(y) - height/2;
// matrix mult for rotation
float x2 = float(x1) * cosrot - float(y1) * sinrot;
float y2 = float(x1) * sinrot + float(y1) * cosrot;
// un-center
int x3 = lround(x2 * projScale) + width/2; // projScale adds some down-scaling,
int y3 = lround(y2 * projScale) + height/2; // so everything fits fully into the original matrix. Note to self: this is still sub-optimal.
// check bounds

if ((x3 <0) || (x3 >= width) || (y3 <0) || (y3 >= height)) return Coord3D{0, 0, 0}; // outside of matrix
// deliver fish
else return Coord3D{x3, y3, 0};
}





class Leds {
Expand Down Expand Up @@ -107,7 +162,13 @@ class Leds {
return XYZ(coord.x, coord.y, coord.z);
}
uint16_t XYZ(uint16_t x, uint16_t y, uint16_t z) {
return x + y * size.x + z * size.x * size.y;

if (projectionNr == p_Rotate) {
Coord3D result = spinXY(x,y, size.x, size.y);
return result.x + result.y * size.x + result.z * size.x * size.y;
}
else
return x + y * size.x + z * size.x * size.y;
}

uint16_t indexVLocal = 0; //set in operator[], used by operator=
Expand Down
Loading

0 comments on commit 45ba553

Please sign in to comment.