To put it another way…
Pixelblaze has a “Mapping” tab where, when configuring your LEDs, you can enter (or calculate) the X, Y and potentially Z positions of the pixels in 2D or 3D space. Those spatial coordinates, along with the index of the pixel along the data line, are then passed at runtime to the render2D(index, x, y)
or render3D(index, x, y, z)
function in your pattern, where you can use them to make rendering decisions. But the map is fixed at setup time; it can’t be changed from within a pattern.
At runtime, Pixelblaze decides which renderer to execute for each pattern depending on the presence or absence of the mapping data. If a map exists and the pattern has a render?D
function that matches the dimensionality of the map, Pixelblaze will use it; otherwise it calls the linear render()
function.
You can have a mixture of 1D and 2D/3D patterns on a Pixelblaze, but if you want to completely reorder pixels or change mapping on the fly, then you might need to ignore the mapping tab and do the mapping of pixels within the code of your own patterns.
Here’s a simple 1D remapping that changes the indexes of a 2D matrix so that the pixels spiral inwards instead of wrapping around at the edges:
//
// This pattern is intended to run on a CJMCU 8x8 matrix where the LED order is left-to-right, top-to-bottom.
// The remapped pixel order is concentric square rings, running clockwise:
//
mapIndex = [ 0, 1, 2, 3, 4, 5, 6, 7, 15, 23, 31, 39, 47, 55, 63, 62, 61, 60, 59, 58, 57, 56, 48, 40, 32, 24,16, 8, // outer ring
9, 10, 11, 12, 13, 14, 22, 30, 38, 46, 54, 53, 52, 51, 50, 49, 41, 33, 25, 17, // 2nd ring inwards
18, 19, 20, 21, 29, 37, 45, 44, 43, 42, 34, 26, // 3rd ring inwards
27, 28, 35, 36 // inner ring
];
export var pixelCount = mapIndex.length;
function remapIndex(index) { for (var i = 0; i < mapIndex.length; i++) if (mapIndex[i] == index) return i; }
//
// The pattern code (@jeff's KITT from https://forum.electromage.com/t/kitt-without-arrays/1219):
//
var t1;
export function beforeRender(delta) { t1 = time(.05) }
function pulse(x) {
var tailPct = .4;
return max(0, ((triangle(x - t1) * square(x - t1, .5)) - (1 - tailPct)) / tailPct)
}
export function render(index) {
index = remapIndex(index);
pct = index / pixelCount / 2; v = pulse(pct) + pulse(-pct); hsv(0, 1, v * v * v)
}
For more drastic 2D/3D remappings, you’d also need to store the X, Y and Z coordinates for each pixel into arrays and remap them at the top of the render2D
or render3D
function. For an extreme example of remapping, see here.