New Project: Syncronized LED Gloves

This is for the 3-axis accelerometer on my sword, which was destroyed the first time someone swung it with any force. :roll_eyes:

code
export var accelerometer

export var x = 0
export var y = 0
export var z = 0

export var total

// configuration
var max_total = 20 // maximum total value to prevent overload
var streak_count = 20 // streak count

// tuning
var scale_acceleration = 50.0 // acceleration scale to ~ [-1,1]
var scale_speed = 50.0 // speed scale to ~10x
var scale_brightness = 8.0 // scale rgb by 1/scale_brightness before summing

// streak state storage
var s_age = array(streak_count)
var s_hue = array(streak_count)
var s_spd = array(streak_count)
var s_len = array(streak_count)

var hPc = pixelCount/2 // half pixelCount

// output framebuffer
var fb_Red = array(hPc)
var fb_Green = array(hPc)
var fb_Blue = array(hPc)

// export var angle = 0
// export var max_spd = 0

var r, g, b // filled by HSVtoRGB

function HSVtoRGB(h, s, v) {
    var i, f, p, q, t;
    i = floor(h * 6);
    f = h * 6 - i;
    p = v * (1 - s);
    q = v * (1 - f * s);
    t = v * (1 - (1 - f) * s);
    im6 = i % 6
    if (im6 == 0) {
      r = v; g = t; b = p;
    } else { if (im6 == 1) {
      r = q; g = v; b = p;
    } else { if (im6 == 2) {
      r = p; g = v; b = t;
    } else { if (im6 == 3) {
      r = p; g = q; b = v;
    } else { if (im6 == 4) {
      r = t; g = p; b = v;
    } else {if (im6 == 5) {
      r = v; g = p; b = q;
    }}}}}}
}

export function beforeRender(delta) {
  // current acceleration, with a 1-sample smoothing window
  var nx = clamp((x + (accelerometer[2]*scale_acceleration))/2.0,-1,1)
  var ny = clamp((y + (accelerometer[0]*scale_acceleration))/2.0,-1,1)
  var nz = clamp((z + (accelerometer[1]*scale_acceleration))/2.0,-1,1)

  // angle = acos(((x*nx)+(y*ny)+(z*nz))/(sqrt(x*x+y*y+z*z)*sqrt(nx*nx+ny*ny+nz*nz)))

  // clear framebuffer
  for (n = 0; n < hPc; n++) {
    fb_Red[n] = 0
    fb_Green[n] = 0
    fb_Blue[n] = 0
  }

  // create a new streak if change in acceleration is low
  if (abs(sqrt(x*x+y*y+z*z) - sqrt(nx*nx+ny*ny+nz*nz)) < 0.125) {
    s_new = 1
  }

  // render streaks
  for (n = 0; n < streak_count; n++) {
    // if we are creating a new streak, and this slot is empty, fill it
    if (s_new && s_age[n] == 0) {
      s_age[n] = 1/32767
      s_hue[n] = random(1) // or angle/PI // or (abs(nx-ny))
      s_spd[n] = scale_speed * sqrt(abs(nz * nx * ny) * (2 + random(4)))
      s_len[n] = max(15 - s_spd[n] + random(3), 3)
      // max_spd = max(max_spd, s_spd[n])
      s_new = 0
    }

    if (s_age[n] > 0) {
      len = s_len[n]
      pix = s_spd[n] / scale_speed * s_age[n] / 6
      if ((pix-len) >= hPc) {
        s_age[n] = 0
        if (s_new) { n-- } // render this streak
      } else {
        s_age[n] += delta
        hue = s_hue[n]
        remaining = len
        for (pn = ceil(pix); remaining > 0 && pn >= 0; remaining--) {
          if (pn < hPc) {
            fade = remaining/len
            HSVtoRGB(hue, sqrt(clamp(1.5 - fade,0,1)), pow(clamp((1-pn/hPc) * fade * fade,0,1),1.5) )
            fb_Red[pn] += r/scale_brightness
            fb_Green[pn] += g/scale_brightness
            fb_Blue[pn] += b/scale_brightness
          }
          pn--
        }
      }
    }
  }

  // Calculate the sum of all pixels in the framebuffer ...
  total = 0
  for (n = 0; n < hPc; n++) {
    fb_Red[n] = min(1,fb_Red[n])
    fb_Green[n] = min(1,fb_Green[n])
    fb_Blue[n] = min(1,fb_Blue[n])
    total += fb_Red[n] + fb_Green[n] + fb_Blue[n]
  }
  // ... and scale them all down if necessary!
  if (total > max_total) {
    adjust = max_total / total
    for (n = 0; n < hPc; n++) {
      fb_Red[n] *= adjust
      fb_Green[n] *= adjust
      fb_Blue[n] *= adjust
    }
  }

  // Store current values for smoothing on next frame
  x = nx
  y = ny
  z = nz
}

export function render(index) {
  // The PB is at one end of the strip, and the strip is folded in half
  // Use \"^hPc - [...]\"\" instead of \"[...] - 1$\" if PB is at the other end
  pindex = ( (index < hPc) ? (hPc - index) : (index - hPc + 1) ) - 1

  rgb(fb_Red[pindex], fb_Green[pindex], fb_Blue[pindex])
}
1 Like