Pixel X,Y available from map?

I have created a working 2D map, and I would like to access the pixel coordinates in beforeRender(). Is that already available or do I have to build up an array manually?

I have a moving animation, and in beforeRender() I would like to loop through all the pixels and find the one that is closest to my animated point. Perhaps there is a better way to do this?

Hi @daniel3550,
You might be able to do that in the render call itself, perhaps to calculate for the next frame.

I’m thinking of adding an API that would let you iterate a function over the map outside of rendering. Something like this:

map2DPixels((index, x, y) => {
  //this code is called for each coordinate on the pixel map if a 2D map is installed
})
map3DPixels((index, x, y, z) => {
  //this code is called likewise for 3D maps
})

Thats basically the same as render, and code that could use the above, could be implemented in render itself.

If you have knowledge of how the pixels are arranged and they are a regular matrix, some simple math can usually get you an index directly. Often something like i = y*width + x.

3 Likes

Thank you! I was wondering if I should do it in render(). Is it correct to say general guideline is to keep render() execution time short and do longer running things in beforeRender()? What would be the problem if we didn’t? Might not possibly update all LEDs within a certain time?

Yes, generally you want to keep render fast because it happens for every single pixel. On the other hand, if you need to do something for every single pixel, it is an optimal place to do that (currently).

If you slow render down, your FPS will be lower. The pixel rendering engine is calling your beforeRender + render function as fast as possible, and piping that to the LEDs.

Generally if you have something that needs to be done only once per animation frame, you want to put that in your beforeRender function.

Slowing down beforeRender will also reduce FPS, but if the total amount of work is the same, it doesn’t matter where you incur the cost as long as its not multiplied by the number of pixels (thus creating more work).

Doing per-pixel work inside render has the benefit that you don’t have additional loop iteration overhead, and have access to the pixel coordinates in render2D and render3D.

1 Like

Found via search and am also interested in this.

I’ve got a function that uses nearby pixels x,y positions to calculate an average color per cluster of pixels. As a result I need access to all of the x,y data, not just the x,y data of the individual pixel you get in render2D. I’m currently just dropping in two arrays of x_pos and y_pos and running the calculation through beforeRender though so thats a workaround.

A lib level function like position_x(index), position_y(index) could be clean.

With a bit of work, you can capture the map coordinates within pattern code.

In addition to your normal pattern code, you’d need to merge in the following:

//  MAP STORAGE functions.
var numDimensions = 0;
var mapXYZ;
function allocateXYZ(dimensions) {
  if (numDimensions == 0) {
    numDimensions = dimensions;
    mapXYZ = array(pixelCount * numDimensions);
  }
}
function storeXYZ(index, x, y, z) {
  if (numDimensions >= 1) mapXYZ[numDimensions*index+0] = x; 
  if (numDimensions >= 2) mapXYZ[numDimensions*index+1] = y; 
  if (numDimensions == 3) mapXYZ[numDimensions*index+2] = z;
}

//  BEFORERENDER functions.
var mapMode = -1;  //  Mode selector: 0 = capture coordinates; 1 = draw pattern
export function beforeRender(delta) { 
  //
  // ...Do whatever per-frame work your pattern requires here.
  //
  //  Move to the next map-capture mode.
  if (mapMode < 1) mapMode++; 
}

//  RENDER functions.
function renderPattern(index) {
  //  Get the appropriate region-specific coordinates for this pixel.
  var offset = index*numDimensions;
  var x = mapXYZ[offset+0];
  var y = 0; if (numDimensions > 1) y = mapXYZ[offset+1];
  var z = 0; if (numDimensions > 2) z = mapXYZ[offset+2];
  // ...
  // Render your pattern here.  The entire set of map coordinates
  // are available in the mapXYZ array if you want to use them.
  // ...
}
export function render(index) {
  //  On the first pass, store the map coordinates. On successive passes, call the client renderer.
  if (mapMode == 0) { allocateXYZ(1); storeXYZ(index, index/pixelCount, 0, 0); return; } else renderPattern(index);
}

export function render2D(index, x, y) {
  //  On the first pass, store the map coordinates. On successive passes, call the client renderer.
  if (mapMode == 0) { allocateXYZ(2); storeXYZ(index, x, y, 0); return; } else renderPattern(index);
}

export function render3D(index, x, y, z) {
  //  On the first pass, store the map coordinates. On successive passes, call the client renderer.
  if (mapMode == 0) { allocateXYZ(3); storeXYZ(index, x, y, 0); return; } else renderPattern(index);
}

This is essentially the same thing as just storing it all in an x_pos array and y_pos array that you can get from your map, no?

You already have the x,y positions from the map and can just write a loop to grab all the x coordinates into an array in any language and then put them in.

I’m just wondering if the overhead of storing multiple arrays of long length and accessing them directly is redundant with non-exposed functions of getting the x,y position of each pixel that render2D already has.

Just a quick note: PB’s Javascript allows pointers to functions, so if you want to eliminate the “is it the first pass” test on every pixel, you can switch render functions by doing something like this:

// stuff that needs to be done on only the first pass
export function firstPassRender(index,x,y) {
  hsv(0,1,1); // all pixels red on the first pass
  if (index == pixelCount - 1) render2D  = normalRender;
}

// render function post-first pass
export function normalRender(index,x,y) {
  hsv(0.6667,1,1); // all pixels blue
}

// use first pass renderer whenever pattern loads
export var render2D = firstPassRender;

export function beforeRender(delta) {
  ; // nothing to do
}

2 Likes

The API that I proposed results in similar data that you can get with @pixie 's approach. Effectively a way to invoke a run through each pixel, like render, outside of the render cycle e.g. in beforeRender or main body init code. It would give you the coordinates one at a time, calling a function you provide.

Getting distance or nearest pixel would be a nice API, and a bit more expensive.

The coordinate transformation API makes that a little trickier. The transformation matrix is composed as necessary on each render frame with up to 31 transformations. Each pixels coordinates are then transformed on the fly during render, and not otherwise stored. It would be similar with the map walking function, allowing transforms to be applied before walking.

Something like getMapX(index) could be done, with a little caching on the API side so that getting other dimensions of the same index afterward doesn’t result in twice the transformation work. I don’t think that would be any faster than getting a coordinate from an array, almost certainly slower, but would let you get coordinates using arbitrary transforms without dummy render cycles.