175 lines
3.9 KiB
Lua
175 lines
3.9 KiB
Lua
COOLDOWN_FACTOR = 0.9995
|
|
OVERDRIVE = 1.70
|
|
EXPONENT = 1.5
|
|
|
|
M = {2.3, 1.3, 1.0} -- mass
|
|
D = {1, 1, 1} -- spring strength
|
|
DAMPING = {} -- filled in init()
|
|
|
|
num_modules = 128
|
|
center_module = 64
|
|
|
|
num_masses = math.floor(num_modules/2)
|
|
excitement_pos = 1
|
|
|
|
-- maximum energy values for each band
|
|
maxRedEnergy = 1
|
|
maxGreenEnergy = 1
|
|
maxBlueEnergy = 1
|
|
|
|
-- spring-mass-grid values
|
|
pos_r = {}
|
|
pos_g = {}
|
|
pos_b = {}
|
|
|
|
vel_r = {}
|
|
vel_g = {}
|
|
vel_b = {}
|
|
|
|
acc_r = {}
|
|
acc_g = {}
|
|
acc_b = {}
|
|
|
|
-- output color buffers
|
|
red = {}
|
|
green = {}
|
|
blue = {}
|
|
|
|
r_tmp = {}
|
|
g_tmp = {}
|
|
b_tmp = {}
|
|
|
|
function limit(val)
|
|
if val > 1 then
|
|
return 1
|
|
elseif val < 0 then
|
|
return 0
|
|
else
|
|
return val
|
|
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, 22000);
|
|
local centerIndex = 2 * center_module + 1;
|
|
|
|
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
|
|
|
|
-- update the spring-mass string
|
|
|
|
-- the outside masses are special, as they are auto-returned to 0 position
|
|
-- { spring-mass pendulum } { friction }
|
|
--acc_r[1] = (-pos_r[1] + (pos_r[2] - pos_r[1])) * D / M
|
|
--acc_g[1] = (-pos_g[1] + (pos_g[2] - pos_g[1])) * D / M
|
|
--acc_b[1] = (-pos_b[1] + (pos_b[2] - pos_b[1])) * D / M
|
|
|
|
acc_r[num_masses] = (-pos_r[num_masses] + (pos_r[num_masses-1] - pos_r[num_masses])) * D[1] / M[1]
|
|
acc_g[num_masses] = (-pos_g[num_masses] + (pos_g[num_masses-1] - pos_g[num_masses])) * D[2] / M[2]
|
|
acc_b[num_masses] = (-pos_b[num_masses] + (pos_b[num_masses-1] - pos_b[num_masses])) * D[3] / M[3]
|
|
|
|
-- inside masses are only influenced by their neighbors
|
|
for i = 2,num_masses-1 do
|
|
acc_r[i] = (pos_r[i-1] + pos_r[i+1] - 2 * pos_r[i]) * D[1] / M[1]
|
|
acc_g[i] = (pos_g[i-1] + pos_g[i+1] - 2 * pos_g[i]) * D[2] / M[2]
|
|
acc_b[i] = (pos_b[i-1] + pos_b[i+1] - 2 * pos_b[i]) * D[3] / M[3]
|
|
end
|
|
|
|
-- update velocity and position
|
|
for i = 1,num_masses do
|
|
vel_r[i] = DAMPING[i] * (vel_r[i] + acc_r[i])
|
|
vel_g[i] = DAMPING[i] * (vel_g[i] + acc_g[i])
|
|
vel_b[i] = DAMPING[i] * (vel_b[i] + acc_b[i])
|
|
|
|
pos_r[i] = pos_r[i] + vel_r[i]
|
|
pos_g[i] = pos_g[i] + vel_g[i]
|
|
pos_b[i] = pos_b[i] + vel_b[i]
|
|
end
|
|
|
|
-- set the new position for the center module
|
|
newRed = redEnergy / maxRedEnergy
|
|
pos_r[excitement_pos] = newRed
|
|
vel_r[excitement_pos] = 0
|
|
acc_r[excitement_pos] = 0
|
|
|
|
newGreen = greenEnergy / maxGreenEnergy
|
|
pos_g[excitement_pos] = newGreen
|
|
vel_b[excitement_pos] = 0
|
|
acc_b[excitement_pos] = 0
|
|
|
|
newBlue = blueEnergy / maxBlueEnergy
|
|
pos_b[excitement_pos] = newBlue
|
|
vel_b[excitement_pos] = 0
|
|
acc_b[excitement_pos] = 0
|
|
|
|
-- map to LED modules
|
|
for i = 1,num_masses do
|
|
r_tmp[i] = pos_r[i]
|
|
g_tmp[i] = pos_g[i]
|
|
b_tmp[i] = pos_b[i]
|
|
|
|
r_tmp[num_modules-i+1] = pos_r[i]
|
|
g_tmp[num_modules-i+1] = pos_g[i]
|
|
b_tmp[num_modules-i+1] = pos_b[i]
|
|
|
|
--print(i, pos_r[i])
|
|
end
|
|
|
|
-- make colors more exciting
|
|
for i = 1,num_modules do
|
|
red[i] = limit(OVERDRIVE * math.pow(r_tmp[i], EXPONENT))
|
|
green[i] = limit(OVERDRIVE * math.pow(g_tmp[i], EXPONENT))
|
|
blue[i] = limit(OVERDRIVE * math.pow(b_tmp[i], EXPONENT))
|
|
end
|
|
|
|
-- return the 3 color arrays
|
|
return red, green, blue
|
|
end
|
|
|
|
function init(nmod, cmod)
|
|
num_modules = nmod
|
|
center_module = cmod
|
|
|
|
num_masses = math.floor(nmod/2)
|
|
excitement_pos = 1
|
|
|
|
for i = 1,nmod do
|
|
red[i] = 0
|
|
green[i] = 0
|
|
blue[i] = 0
|
|
end
|
|
|
|
for i = 1,num_masses do
|
|
pos_r[i] = 0
|
|
pos_g[i] = 0
|
|
pos_b[i] = 0
|
|
|
|
vel_r[i] = 0
|
|
vel_g[i] = 0
|
|
vel_b[i] = 0
|
|
|
|
acc_r[i] = 0
|
|
acc_g[i] = 0
|
|
acc_b[i] = 0
|
|
|
|
DAMPING[i] = 1 - 0.08 * math.pow(math.abs((i - excitement_pos) / num_masses), 2)
|
|
end
|
|
|
|
-- don't use fading
|
|
return 0
|
|
end
|