@J.D_Fontanella : Great thoughts and questions. You can totally have multiple icosaLEDs map to the same canvasLEDs, and do all sorts of interesting things that way, effects-wise.
The RGBshades-map approach uses as much RAM as if the whole thing was an X-by-Y array of LEDs. So 60x30 = 1,800 ‘virtual’ LEDs = 5,400 bytes of RAM just for the LED array – which is fine if you’re on an ARM (Arduino Due, Teensy 3, etc) or ESP platform. If you’re on an ATmega MCU, you’re out of RAM in a hurry.
There’s another approach which might be workable here: write a custom “XY” function that understands the topology of the struts. In fact, that might be the right way to go here. It would look something like this:
uint16_t XY( uint8_t x, uint8_t y)
{
uint16_t i = SAFETY_PIXEL_ID; /* minus 1 */
if( y < 10 ) { // top bars
uint8_t bar = x / 11;
if( (bar * 11) == x ) {-
i = bar + (y * 5);
}
} else if( y == 10 ) { // top horizontal strip
uint8_t bar = x / 11;
if( (bar * 11) != x ) {
i = TOP_STRIP_BASE_ID + (x - bar);;
}
} else if( y < 21 ) { // middle zigzags
…etc… {this will be a pain but maybe worth it}
} else if( y == 21 ) { // bottom horiz strip
…etc…
} else if( y < 32 ) { // bottom bars
…etc…
}
return i;
}
You define SAFETY_PIXEL_ID as minus 1, and define your leds array like this:
CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
CRGB const leds( leds_plus_safety_pixel + 1);
Now you can just do this:
leds [ XY( xcoord, ycoord) ] = color;
For any values for xcoord and yoord that do NOT map to a real pixel, the XY function will return negative 1. And leds[—1] is the same as leds_plus_safety_pixel[0], which is a perfectly legitimate place to write to - no crash, no problem.
Now, there are two problems with this:first, writing the XY function correctly will be a pain in the butt. I stopped my example code just before the really annoying part, but it’s still totally doable with a combination of patience, math, and a lot of if-then statements. You’ll also want to get all that “long division” and “modulo” out of there for speed reasons - a simple lookup table called “XdividedBy11” might help with that.
But the second problem with this approach is performance/waste.
Suppose you want to paint a rainbow wash over the whole thing. Since your programming model is just a 32x60(?) array, your code might do this:
for( y = 0 to 31) {
for( x = 0 to 59) {
leds[ XY( x, y) ] = rainbow color
}
}
And before you know it, you’re having to calculate and ‘paint’ nearly 2,000 virtual pixels every time – even though most of them don’t exist and are invisible and a waste of time. Wasteful and slow.
The more I think about this, the more I like the idea of having a canvas array of say 32x16 and mapping each icosaLED to one (or more, via supersampling) canvasLED. You can always increase or decrease the resolution of the canvas independently of the physical resolution of the icosahedron, to balance speed and memory and visual density etc.
Lots of ways to approach this, each with various (interesting / annoying!) trade-offs. Let us know what you try and how it goes!