HSVtoRGB & Framebuffer with attenuation

@Scruffynerf ,
At some point I want to add a bitmap/raster API that would give you a 2D surface to draw into, and then map/pull from going to LEDs (a simple 1:1 if they happen to match, but not necessary).

In the meantime, I’ve been playing around with a fractal that lends itself to drawing pixels rather than math in render, and came up with this framework which isn’t totally dissimilar to what everyone else has been doing for 2D, but packs pixels into a single dimensional array:

/* Rendering into a "canvas" example
 *
 * In this example, an array is created to represend a 2D canvas with
 * x and y values in world coordinates, which are values from 0 to 1 exclusive.
 * The canvas is then scaled and drawn to the LEDs. The LEDs could match 1:1
 * or could be some other size, or even a non uniform layout.
 * The canvas is set up with 2 arrays, one for values, one for hues, which
 * are then fed to hsv() during render2D.
 * 
 * This example draws a dot traveling around the circumference of a cirlce,
 * leaving a fading trail of color.
 */

var width = 8
var height = 8
var numPixels = width * height
var canvasValues = array(numPixels) //make a "canvas" of brightness values
var canvasHues = array(numPixels) //likewise for hues
var fade = .95


//find the pixel index within a canvas array
//pixels are packed in rows, then columns of rows
function getIndex(x, y) {
  return floor(x*width) + floor(y*height)*width
}

function isIndexValid(index) {
  return index >= 0 && index < numPixels
}

export function beforeRender(delta) { 
  //fade out any existing pixels
  canvasValues.mutate(p => p*fade) //TODO fade based on delta for consistent fade

  //draw into the canvas here
  //this draws a pixel moving in a circle
  //radius 1/3rd, centered at 0.5, 0.5
  var a = time(.01) * PI2
  var r = 1/3
  var x = sin(a) * r + 0.5 
  var y = cos(a) * r + 0.5
  
  //optionally, you can make the pixels "wrap" around to the other side if out of bounds
  // x = mod(x,.99999)
  // y = mod(y,.99999)
  
  //calc this pixel's index in the canvas based on position of our coordinate
  var index = getIndex(x, y)
  
  //check that the coordinate is within bounds of the canvas before using it
  if (isIndexValid(index)) {
    canvasValues[index] = 1
    canvasHues[index] = time(.015)
  }
}

export function render2D(index, x, y) {
  index = getIndex(x, y) //calc this pixel's index in the canvas based on position
  h = canvasHues[index]
  v = canvasValues[index]
  hsv(h, 1, v*v)
}

2D canvas example.epe (7.9 KB)

@sorceror, On the other topic, I do want to add some way to get data between multiple PB. Sharing sensor board data is definitely top of the list, but I’m thinking about the best way to support other data, and perhaps events as well. I think a pub/sub kind of setup with UI to configure the connections might be best, allowing the code to remain more agnostic of where the data is coming from. Controls are a good example of something that could receive events/data from not only UI sliders and things, but could be “wired” up to an analog or digital input, or a data source on another PB on the network. Perhaps with an OSC compatibility layer (or using OSC if it fits well enough).

1 Like