2020-05-16 21:51:35 +02:00
|
|
|
|
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
|
|
|
|
|
|
2020-06-05 20:37:18 +02:00
|
|
|
|
max_new_energy_per_strip = 2.00*RM_ENERGY * num_modules
|
2020-05-16 21:51:35 +02:00
|
|
|
|
|
|
|
|
|
-- 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
|
|
|
|
|
|
2020-06-05 20:37:18 +02:00
|
|
|
|
momentum = momentum - 1
|
2020-05-16 21:51:35 +02:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2020-06-05 20:37:18 +02:00
|
|
|
|
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
|
|
|
|
|
|
2020-05-16 21:51:35 +02:00
|
|
|
|
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
|
|
|
|
|
|
2020-06-05 20:37:18 +02:00
|
|
|
|
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)
|
2020-05-16 21:51:35 +02:00
|
|
|
|
|
|
|
|
|
--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
|
2020-06-05 20:37:18 +02:00
|
|
|
|
max_target_energy = 0.2 * num_strips * num_modules
|
2020-05-16 21:51:35 +02:00
|
|
|
|
|
|
|
|
|
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
|