musiclight2/sparkler_energycontrolled.lua

222 lines
5.3 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.00*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 flames 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 - 1
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 fractionToEnergy(fract, max)
return math.sqrt(fract) * max
--dB = 20*math.log(fract)/math.log(10)
--result = max * (dB + 40) / 40
--if result > 0 then
-- return result
--else
-- return 0
--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
redMomentum = updateFire(fractionToEnergy(redEnergy / maxRedEnergy, max_target_energy), fireRedEnergy, redMomentum)
greenMomentum = updateFire(fractionToEnergy(greenEnergy / maxGreenEnergy, max_target_energy), fireGreenEnergy, greenMomentum)
blueMomentum = updateFire(fractionToEnergy(blueEnergy / maxBlueEnergy, max_target_energy), fireBlueEnergy, blueMomentum)
whiteMomentum = updateFire(fractionToEnergy((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 = 0.2 * 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