diff --git a/wave.lua b/wave.lua index d8383ed..bd97a5d 100644 --- a/wave.lua +++ b/wave.lua @@ -59,6 +59,7 @@ end --Derivative of the interpolation. local Derivative = function( wave, x ) local re, im = wave.dftre, wave.dftim + local y = 0 for k = 1, N / 2 do local c, s = k * math.cos( x * k ), k * math.sin( x * k ) @@ -76,25 +77,45 @@ end --Second derivative of the interpolation. local SecondDerivative = function( wave, x ) local re, im = wave.dftre, wave.dftim + local y = 0 for k = 1, N / 2 do local c, s = k * k * math.cos( x * k ), k * k * math.sin( x * k ) y = y - c * re[k + 1] - + s * im[k + 1] + - s * im[k + 1] - c * re[N - k + 1] - - s * im[N - k + 1] + + s * im[N - k + 1] end - return y end +--Bandlimited impulse located at angle theta. +local function AliasedSinc( theta, x ) + local n, d = math.sin( N * 0.5 * ( x - theta ) ), N * math.sin( 0.5 * ( x - theta ) ) + if d < 0.0001 and d > -0.0001 then return 1.0 end + return n / d +end + +--Apply bandlimited impulse to wave. +local Impulse = function( wave, location, magnitude ) + local speed = wave.vrad + + for i = 0, N - 1 do + speed[ i + 1 ] = speed[ i + 1 ] + magnitude * AliasedSinc( 2.0 * math.pi * i, location ) + end + +end + local mt = { __index = { DFT = DFT, Interpolate = Interpolate, Derivative = Derivative, - SecondDerivative = SecondDerivative } } + SecondDerivative = SecondDerivative, + Impulse = Impulse } } + + local function Wave( ) local t = { @@ -138,12 +159,26 @@ local function Draw() love.graphics.setColor( 0, 0, 0, 0.5 ) love.graphics.circle( "fill", cx, cy, 0.02 ) - love.graphics.setColor( 1.0, 0, 0, 0.5 ) + for k = 0.1, 1.0, 0.1 do + --Interpolant. + love.graphics.setColor( 1.0, 0, 0, 0.5 ) th = ( i - 1 + k ) * 2.0 * math.pi / N r = cur:Interpolate( th ) x, y = r * math.cos( th ), r * math.sin( th ) love.graphics.circle( "fill", x, y, 0.01 ) + + --First derivative. + love.graphics.setColor( 0, 1.0, 0, 0.5 ) + r = 1.0 + cur:Derivative( th ) + x, y = r * math.cos( th ), r * math.sin( th ) + love.graphics.circle( "fill", x, y, 0.01 ) + + --Second derivative. + love.graphics.setColor( 0, 0, 1.0, 0.5 ) + r = 1.0 + cur:SecondDerivative( th ) + x, y = r * math.cos( th ), r * math.sin( th ) + love.graphics.circle( "fill", x, y, 0.01 ) end end @@ -154,6 +189,19 @@ local function Draw() end local function Update() + local t = love.timer.getTime() + for i = 1, N do + local rxx = old:SecondDerivative( 2.0 * math.pi * (i - 1) / N ) + cur.vrad[i] = 0.7 * old.vrad[i] + 0.5 * step * rxx + cur.radii[i] = old.radii[i] + step * cur.vrad[i] + end + + cur:DFT( ) + + if love.math.random( 120 ) < 3 then + cur:Impulse( 0, 0.2 ) + end + --Deep copy of current state to old state. for name, t in pairs( cur ) do for i = 1, 13 do @@ -161,14 +209,6 @@ local function Update() end end - local t = love.timer.getTime() - for i = 1, N do - cur.radii[i] = cur.radii[i] + old.vrad[i] * step - cur.vrad[i] = cur.vrad[i] - cur:SecondDerivative( ( i - 1 ) / N ) - end - - cur:DFT( ) - end local function DetectCollision( px, py, vpx, vpy )