local v={}do v.__index=v function v.new(U,L,C)return setmetatable({fRising=U;fFalling=L;g=C,p=C;v=C*0},v)end function v.step(U,v)local L=U.fRising local C=U.fFalling local I=U.g local G=U.p local y=U.v local n=(2*math.pi)*(y>0 and L or C)local k=G-I local l=math.exp(-n*v)local e=(k*(1+n*v)+y*v)*l+I local X=(y*(1-n*v)-k*((n*n)*v))*l U.p=e U.v=X return e end end
-- value damper with separate response frequencies for rising and falling values
local VariableEdgeSpring = {}
do
	VariableEdgeSpring.__index = VariableEdgeSpring

	function VariableEdgeSpring.new(fRising, fFalling, position)
		return setmetatable({
			fRising = fRising,
			fFalling = fFalling,
			g = position,
			p = position,
			v = position * 0,
		}, VariableEdgeSpring)
	end

	function VariableEdgeSpring:step(dt)
		local fRising = self.fRising
		local fFalling = self.fFalling
		local g = self.g
		local p0 = self.p
		local v0 = self.v

		local f = 2 * math.pi * (v0 > 0 and fRising or fFalling)

		local offset = p0 - g
		local decay = math.exp(-f * dt)

		local p1 = (offset * (1 + f * dt) + v0 * dt) * decay + g
		local v1 = (v0 * (1 - f * dt) - offset * (f * f * dt)) * decay

		self.p = p1
		self.v = v1

		return p1
	end
end
