From e587ac073aef77be6f152172ab5ea4d2297b5b78 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Sat, 16 May 2020 21:51:35 +0200 Subject: [PATCH] Some new 2D animation scripts; Changed config to 60 FPS --- config.h | 7 +- fire.lua | 144 +++++++++++++++++++++++ pixelation.lua | 134 ++++++++++++++++++++++ sparkler.lua | 159 ++++++++++++++++++++++++++ sparkler_energycontrolled.lua | 207 ++++++++++++++++++++++++++++++++++ 5 files changed, 649 insertions(+), 2 deletions(-) create mode 100644 fire.lua create mode 100644 pixelation.lua create mode 100644 sparkler.lua create mode 100644 sparkler_energycontrolled.lua diff --git a/config.h b/config.h index 736f8f7..7be11e8 100644 --- a/config.h +++ b/config.h @@ -28,8 +28,11 @@ // Number of parts in the sample buffer #define BUFFER_PARTS 2 -// update rate for the led strip (in seconds) -#define LED_INTERVAL 0.01 +// Update rate for the led strip (in seconds) +// Must be a little faster than the hardware update rate to ensure there’s +// always a packet in the queue +//#define LED_INTERVAL 0.01 +#define LED_INTERVAL (1.0/61.0) // frequency ranges for the base colors #define RED_MIN_FREQ 0 diff --git a/fire.lua b/fire.lua new file mode 100644 index 0000000..0d37e18 --- /dev/null +++ b/fire.lua @@ -0,0 +1,144 @@ +COOLDOWN_FACTOR = 0.9998 +MAX_ENERGY_PROPAGATION = 0.4 +RM_ENERGY=0.0100 +EXPONENT=1.5 +W_EXPONENT=2.2 +OVERDRIVE=1.5 + +num_modules = 1 +num_strips = 1 + +-- maximum energy values for each band +maxRedEnergy = 1 +maxGreenEnergy = 1 +maxBlueEnergy = 1 +maxWhiteEnergy = 1 + +-- array storing the flame’s energy for each pixel +fireRedEnergy = {} +fireGreenEnergy = {} +fireBlueEnergy = {} +fireWhiteEnergy = {} + +-- output color buffers +red = {} +green = {} +blue = {} +white = {} + +function limit(val) + if val > 1 then + return 1 + elseif val < 0 then + return 0 + else + return val + end +end + +function updateFire(newEnergy, energyArray) + avgEnergyPerStrip = newEnergy + + for s = 1,num_strips do + -- Add new energy in the bottom row + i = idx(s, 1) + energyArray[i] = energyArray[i] + math.random() * avgEnergyPerStrip + + -- remove energy at the top + i = idx(s, num_modules) + energyArray[i] = energyArray[i] * (1.0 - math.random() * MAX_ENERGY_PROPAGATION) + + -- move energy upwards + for m_out = num_modules,2,-1 do + i_out = idx(s, m_out) + i_in = idx(s, m_out - 1) + + energyMoved = energyArray[i_in] * math.random() * MAX_ENERGY_PROPAGATION + + energyArray[i_in] = energyArray[i_in] - energyMoved + energyArray[i_out] = energyArray[i_out] + energyMoved + end + + -- globally remove energy + for m = 1,num_modules do + i = idx(s, m) + if energyArray[i] > RM_ENERGY then + energyArray[i] = energyArray[i] - RM_ENERGY + else + energyArray[i] = 0 + end + end + end +end + +function periodic() + local redEnergy = get_energy_in_band(0, 400); + local greenEnergy = get_energy_in_band(400, 4000); + local blueEnergy = get_energy_in_band(4000, 12000); + local whiteEnergy = get_energy_in_band(12000, 22000); + + maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR + if redEnergy > maxRedEnergy then + maxRedEnergy = redEnergy + end + + maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR + if greenEnergy > maxGreenEnergy then + maxGreenEnergy = greenEnergy + end + + maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR + if blueEnergy > maxBlueEnergy then + maxBlueEnergy = blueEnergy + end + + maxWhiteEnergy = maxWhiteEnergy * COOLDOWN_FACTOR + if whiteEnergy > maxWhiteEnergy then + maxWhiteEnergy = whiteEnergy + end + + updateFire((redEnergy / maxRedEnergy)^EXPONENT, fireRedEnergy) + updateFire((greenEnergy / maxGreenEnergy)^EXPONENT, fireGreenEnergy) + updateFire((blueEnergy / maxBlueEnergy)^EXPONENT, fireBlueEnergy) + updateFire((whiteEnergy / maxWhiteEnergy)^W_EXPONENT, fireWhiteEnergy) + + -- make colors more exciting + remove the first (flickering) mass + for m = 1,num_modules do + for s = 1,num_strips do + i = idx(s, m) + + rval = limit(OVERDRIVE * fireRedEnergy[i])--^EXPONENT) + gval = limit(OVERDRIVE * fireGreenEnergy[i])--^EXPONENT) + bval = limit(OVERDRIVE * fireBlueEnergy[i])--^EXPONENT) + wval = limit(OVERDRIVE * fireWhiteEnergy[i])--^W_EXPONENT) + + red[i] = rval + green[i] = gval + blue[i] = bval + white[i] = wval + end + end + + -- return the 4 color arrays + return red, green, blue, white +end + +function init(nstrip, nmod, cmod) + num_strips = nstrip + num_modules = nmod + + for i = 1,(nmod*nstrip) do + red[i] = 0 + green[i] = 0 + blue[i] = 0 + white[i] = 0 + + fireRedEnergy[i] = 0 + fireGreenEnergy[i] = 0 + fireBlueEnergy[i] = 0 + fireWhiteEnergy[i] = 0 + end + + -- don't use fading + return 0 +end diff --git a/pixelation.lua b/pixelation.lua new file mode 100644 index 0000000..2764c2f --- /dev/null +++ b/pixelation.lua @@ -0,0 +1,134 @@ +COOLDOWN_FACTOR = 0.9998 +MAX_ENERGY_PROPAGATION = 0.5 +EXPONENT=1.0 +W_EXPONENT=1.0 +OVERDRIVE=1 + +num_modules = 1 +num_strips = 1 + +-- maximum energy values for each band +maxRedEnergy = 1 +maxGreenEnergy = 1 +maxBlueEnergy = 1 +maxWhiteEnergy = 1 + +-- array storing the flame’s energy for each pixel +fireRedEnergy = {} +fireGreenEnergy = {} +fireBlueEnergy = {} +fireWhiteEnergy = {} + +-- output color buffers +red = {} +green = {} +blue = {} +white = {} + +function limit(val) + if val > 1 then + return 1 + elseif val < 0 then + return 0 + else + return val + end +end + +function updateFire(newEnergy, energyArray) + avgEnergyPerStrip = newEnergy * 2 / num_strips + + for s = 1,num_strips do + -- Add new energy in the bottom row + i = idx(s, 1) + energyArray[i] = energyArray[i] + math.random() * avgEnergyPerStrip + + -- remove energy at the top + i = idx(s, num_modules) + energyArray[i] = energyArray[i] * (1.0 - math.random() * MAX_ENERGY_PROPAGATION) + + -- move energy upwards + for m_out = num_modules,2,-1 do + i_out = idx(s, m_out) + i_in = idx(s, m_out - 1) + + energyMoved = energyArray[i_in] * math.random() * MAX_ENERGY_PROPAGATION + + energyArray[i_in] = energyArray[i_in] - energyMoved + energyArray[i_out] = energyArray[i_out] + energyMoved + end + end +end + +function periodic() + local redEnergy = get_energy_in_band(0, 400); + local greenEnergy = get_energy_in_band(400, 4000); + local blueEnergy = get_energy_in_band(4000, 12000); + local whiteEnergy = get_energy_in_band(12000, 22000); + + maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR + if redEnergy > maxRedEnergy then + maxRedEnergy = redEnergy + end + + maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR + if greenEnergy > maxGreenEnergy then + maxGreenEnergy = greenEnergy + end + + maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR + if blueEnergy > maxBlueEnergy then + maxBlueEnergy = blueEnergy + end + + maxWhiteEnergy = maxWhiteEnergy * COOLDOWN_FACTOR + if whiteEnergy > maxWhiteEnergy then + maxWhiteEnergy = whiteEnergy + end + + updateFire(redEnergy / maxRedEnergy, fireRedEnergy) + updateFire(greenEnergy / maxGreenEnergy, fireGreenEnergy) + updateFire(blueEnergy / maxBlueEnergy, fireBlueEnergy) + updateFire(whiteEnergy / maxWhiteEnergy, fireWhiteEnergy) + + -- make colors more exciting + remove the first (flickering) mass + -- TODO: update + for m = 1,num_modules do + for s = 1,num_strips do + i = idx(s, m) + + rval = limit(OVERDRIVE * fireRedEnergy[i]^EXPONENT) + gval = limit(OVERDRIVE * fireGreenEnergy[i]^EXPONENT) + bval = limit(OVERDRIVE * fireBlueEnergy[i]^EXPONENT) + wval = limit(OVERDRIVE * fireWhiteEnergy[i]^W_EXPONENT) + + red[i] = rval + green[i] = gval + blue[i] = bval + white[i] = wval + end + end + + -- return the 4 color arrays + return red, green, blue, white +end + +function init(nstrip, nmod, cmod) + num_strips = nstrip + num_modules = nmod + + for i = 1,(nmod*nstrip) do + red[i] = 0 + green[i] = 0 + blue[i] = 0 + white[i] = 0 + + fireRedEnergy[i] = 0 + fireGreenEnergy[i] = 0 + fireBlueEnergy[i] = 0 + fireWhiteEnergy[i] = 0 + end + + -- don't use fading + return 0 +end diff --git a/sparkler.lua b/sparkler.lua new file mode 100644 index 0000000..de714b1 --- /dev/null +++ b/sparkler.lua @@ -0,0 +1,159 @@ +COOLDOWN_FACTOR = 0.9998 +MAX_ENERGY_PROPAGATION = 0.3 +RM_ENERGY=0.0200 +EXPONENT=1.5 +W_EXPONENT=2.2 +OVERDRIVE=1.5 + +num_modules = 1 +num_strips = 1 + +-- maximum energy values for each band +maxRedEnergy = 1 +maxGreenEnergy = 1 +maxBlueEnergy = 1 +maxWhiteEnergy = 1 + +-- array storing the flame’s energy for each pixel +fireRedEnergy = {} +fireGreenEnergy = {} +fireBlueEnergy = {} +fireWhiteEnergy = {} + +-- output color buffers +red = {} +green = {} +blue = {} +white = {} + +function limit(val) + if val > 1 then + return 1 + elseif val < 0 then + return 0 + else + return val + end +end + +function updateFire(newEnergy, energyArray) + avgEnergyPerStrip = newEnergy + + for s = 1,num_strips do + -- Add new energy in the center rows + i = idx(s, num_modules/2) + energyArray[i] = energyArray[i] + math.random() * avgEnergyPerStrip + i = idx(s, num_modules/2+1) + energyArray[i] = energyArray[i] + math.random() * avgEnergyPerStrip + + -- remove energy at the top and the bottom + i = idx(s, num_modules) + energyArray[i] = energyArray[i] * (1.0 - math.random() * MAX_ENERGY_PROPAGATION) + i = idx(s, 1) + energyArray[i] = energyArray[i] * (1.0 - math.random() * MAX_ENERGY_PROPAGATION) + + -- move energy upwards + for m_out = num_modules,num_modules/2+2,-1 do + i_out = idx(s, m_out) + i_in = idx(s, m_out - 1) + + energyMoved = energyArray[i_in] * math.random() * MAX_ENERGY_PROPAGATION + + energyArray[i_in] = energyArray[i_in] - energyMoved + energyArray[i_out] = energyArray[i_out] + energyMoved + end + + -- move energy downwards + for m_out = 1,num_modules/2-1,1 do + i_out = idx(s, m_out) + i_in = idx(s, m_out + 1) + + energyMoved = energyArray[i_in] * math.random() * MAX_ENERGY_PROPAGATION + + energyArray[i_in] = energyArray[i_in] - energyMoved + energyArray[i_out] = energyArray[i_out] + energyMoved + end + + -- globally remove energy + for m = 1,num_modules do + i = idx(s, m) + if energyArray[i] > RM_ENERGY then + energyArray[i] = energyArray[i] - RM_ENERGY + else + energyArray[i] = 0 + end + end + end +end + +function periodic() + local redEnergy = get_energy_in_band(0, 400); + local greenEnergy = get_energy_in_band(400, 4000); + local blueEnergy = get_energy_in_band(4000, 12000); + local whiteEnergy = get_energy_in_band(12000, 22000); + + maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR + if redEnergy > maxRedEnergy then + maxRedEnergy = redEnergy + end + + maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR + if greenEnergy > maxGreenEnergy then + maxGreenEnergy = greenEnergy + end + + maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR + if blueEnergy > maxBlueEnergy then + maxBlueEnergy = blueEnergy + end + + maxWhiteEnergy = maxWhiteEnergy * COOLDOWN_FACTOR + if whiteEnergy > maxWhiteEnergy then + maxWhiteEnergy = whiteEnergy + end + + updateFire((redEnergy / maxRedEnergy)^EXPONENT, fireRedEnergy) + updateFire((greenEnergy / maxGreenEnergy)^EXPONENT, fireGreenEnergy) + updateFire((blueEnergy / maxBlueEnergy)^EXPONENT, fireBlueEnergy) + updateFire((whiteEnergy / maxWhiteEnergy)^W_EXPONENT, fireWhiteEnergy) + + -- make colors more exciting + remove the first (flickering) mass + for m = 1,num_modules do + for s = 1,num_strips do + i = idx(s, m) + + rval = limit(OVERDRIVE * (fireRedEnergy[i])) + gval = limit(OVERDRIVE * (fireGreenEnergy[i])) + bval = limit(OVERDRIVE * (fireBlueEnergy[i])) + wval = limit(OVERDRIVE * (fireWhiteEnergy[i])) + + red[i] = rval + green[i] = gval + blue[i] = bval + white[i] = wval + end + end + + -- return the 4 color arrays + return red, green, blue, white +end + +function init(nstrip, nmod, cmod) + num_strips = nstrip + num_modules = nmod + + for i = 1,(nmod*nstrip) do + red[i] = 0 + green[i] = 0 + blue[i] = 0 + white[i] = 0 + + fireRedEnergy[i] = 0 + fireGreenEnergy[i] = 0 + fireBlueEnergy[i] = 0 + fireWhiteEnergy[i] = 0 + end + + -- don't use fading + return 0 +end diff --git a/sparkler_energycontrolled.lua b/sparkler_energycontrolled.lua new file mode 100644 index 0000000..fc055c0 --- /dev/null +++ b/sparkler_energycontrolled.lua @@ -0,0 +1,207 @@ +COOLDOWN_FACTOR = 0.9998 +MAX_ENERGY_PROPAGATION = 0.3 +RM_ENERGY=0.0100 +EXPONENT=1.5 +W_EXPONENT=2.2 +OVERDRIVE=1.5 + +num_modules = 1 +num_strips = 1 + +max_new_energy_per_strip = 2*RM_ENERGY * num_modules + +-- warning: these must also be updated in init() +max_target_energy = num_strips * num_modules + +-- maximum energy values for each band +maxRedEnergy = 1 +maxGreenEnergy = 1 +maxBlueEnergy = 1 +maxWhiteEnergy = 1 + +redMomentum = 0 +greenMomentum = 0 +blueMomentum = 0 +whiteMomentum = 0 + +-- array storing the flame’s energy for each pixel +fireRedEnergy = {} +fireGreenEnergy = {} +fireBlueEnergy = {} +fireWhiteEnergy = {} + +-- output color buffers +red = {} +green = {} +blue = {} +white = {} + +function limit(val) + if val > 1 then + return 1 + elseif val < 0 then + return 0 + else + return val + end +end + +function updateFire(targetEnergy, energyArray, momentum) + local totalEnergy = 0 + local avgEnergyPerStrip + + for s = 1,num_strips do + for m = 1,num_modules do + totalEnergy = totalEnergy + energyArray[idx(s,m)] + end + end + + if targetEnergy > totalEnergy then + avgEnergyPerStrip = (targetEnergy - totalEnergy) / num_strips + + avgEnergyPerStrip = base_new_energy_per_strip * momentum + + if avgEnergyPerStrip > max_new_energy_per_strip then + avgEnergyPerStrip = max_new_energy_per_strip + end + + momentum = momentum + 1 + else + avgEnergyPerStrip = 0 + + momentum = momentum - 2 + + if momentum < 0 then + momentum = 0 + end + end + + for s = 1,num_strips do + -- Add new energy in the center rows + i = idx(s, num_modules/2) + energyArray[i] = energyArray[i] + math.random() * avgEnergyPerStrip + i = idx(s, num_modules/2+1) + energyArray[i] = energyArray[i] + math.random() * avgEnergyPerStrip + + -- remove energy at the top and the bottom + i = idx(s, num_modules) + energyArray[i] = energyArray[i] * (1.0 - math.random() * MAX_ENERGY_PROPAGATION) + i = idx(s, 1) + energyArray[i] = energyArray[i] * (1.0 - math.random() * MAX_ENERGY_PROPAGATION) + + -- move energy upwards + for m_out = num_modules,num_modules/2+2,-1 do + i_out = idx(s, m_out) + i_in = idx(s, m_out - 1) + + energyMoved = energyArray[i_in] * math.random() * MAX_ENERGY_PROPAGATION + + energyArray[i_in] = energyArray[i_in] - energyMoved + energyArray[i_out] = energyArray[i_out] + energyMoved + end + + -- move energy downwards + for m_out = 1,num_modules/2-1,1 do + i_out = idx(s, m_out) + i_in = idx(s, m_out + 1) + + energyMoved = energyArray[i_in] * math.random() * MAX_ENERGY_PROPAGATION + + energyArray[i_in] = energyArray[i_in] - energyMoved + energyArray[i_out] = energyArray[i_out] + energyMoved + end + + -- globally remove energy + for m = 1,num_modules do + i = idx(s, m) + if energyArray[i] > RM_ENERGY then + energyArray[i] = energyArray[i] - RM_ENERGY + else + energyArray[i] = 0 + end + end + end + + return momentum +end + +function periodic() + local redEnergy = get_energy_in_band(0, 400); + local greenEnergy = get_energy_in_band(400, 4000); + local blueEnergy = get_energy_in_band(4000, 12000); + local whiteEnergy = get_energy_in_band(12000, 22000); + + maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR + if redEnergy > maxRedEnergy then + maxRedEnergy = redEnergy + end + + maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR + if greenEnergy > maxGreenEnergy then + maxGreenEnergy = greenEnergy + end + + maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR + if blueEnergy > maxBlueEnergy then + maxBlueEnergy = blueEnergy + end + + maxWhiteEnergy = maxWhiteEnergy * COOLDOWN_FACTOR + if whiteEnergy > maxWhiteEnergy then + maxWhiteEnergy = whiteEnergy + end + + redMomentum = updateFire((redEnergy / maxRedEnergy)^EXPONENT * max_target_energy, fireRedEnergy, redMomentum) + greenMomentum = updateFire((greenEnergy / maxGreenEnergy)^EXPONENT * max_target_energy, fireGreenEnergy, greenMomentum) + blueMomentum = updateFire((blueEnergy / maxBlueEnergy)^EXPONENT * max_target_energy, fireBlueEnergy, blueMomentum) + whiteMomentum = updateFire((whiteEnergy / maxWhiteEnergy)^W_EXPONENT * max_target_energy, fireWhiteEnergy, whiteMomentum) + + --updateFire(2 * max_target_energy, fireRedEnergy) + --updateFire(0 * max_target_energy, fireGreenEnergy) + --updateFire(0 * max_target_energy, fireBlueEnergy) + --updateFire(0 * max_target_energy, fireWhiteEnergy) + + -- make colors more exciting + remove the first (flickering) mass + for m = 1,num_modules do + for s = 1,num_strips do + i = idx(s, m) + + rval = limit(OVERDRIVE * (fireRedEnergy[i])) + gval = limit(OVERDRIVE * (fireGreenEnergy[i])) + bval = limit(OVERDRIVE * (fireBlueEnergy[i])) + wval = limit(OVERDRIVE * (fireWhiteEnergy[i])) + + red[i] = rval + green[i] = gval + blue[i] = bval + white[i] = wval + end + end + + -- return the 4 color arrays + return red, green, blue, white +end + +function init(nstrip, nmod, cmod) + num_strips = nstrip + num_modules = nmod + + max_new_energy_per_strip = num_modules * RM_ENERGY * 2 + base_new_energy_per_strip = num_modules * RM_ENERGY * 0.1 + max_target_energy = num_strips * num_modules + + for i = 1,(nmod*nstrip) do + red[i] = 0 + green[i] = 0 + blue[i] = 0 + white[i] = 0 + + fireRedEnergy[i] = 0 + fireGreenEnergy[i] = 0 + fireBlueEnergy[i] = 0 + fireWhiteEnergy[i] = 0 + end + + -- don't use fading + return 0 +end