Created
October 4, 2020 12:40
-
-
Save estama/74da0ad4fe92803143628e05a3d02d14 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --== Spring based temporal ==-- | |
| local temporalSpring = {} | |
| temporalSpring.__index = temporalSpring | |
| function newTemporalSpring(spring, damp, startingValue) | |
| local data = {spring = spring or 10, damp = damp or 2, state = startingValue or 0, vel = 0} | |
| setmetatable(data, temporalSpring) | |
| return data | |
| end | |
| function temporalSpring:get(sample, dt) | |
| self.vel = self.vel * max(1 - self.damp * dt, 0) + (sample - self.state) * min(self.spring * dt, 1/dt) | |
| self.state = self.state + self.vel * dt | |
| return self.state | |
| end | |
| function temporalSpring:getWithSpringDamp(sample, dt, spring, damp) | |
| self.vel = self.vel * max(1 - damp * dt, 0) + (sample - self.state) * min(spring * dt, 1/dt) | |
| self.state = self.state + self.vel * dt | |
| return self.state | |
| end | |
| function temporalSpring:set(sample) | |
| self.state = sample | |
| self.vel = 0 | |
| end | |
| function temporalSpring:value() | |
| return self.state | |
| end | |
| --== S-curve temporal ==-- | |
| local temporalSigmoidSmoothing = {} | |
| temporalSigmoidSmoothing.__index = temporalSigmoidSmoothing | |
| function newTemporalSigmoidSmoothing(inRate, startAccel, stopAccel, outRate, startingValue) | |
| local rate = inRate or 1 | |
| local startaccel = startAccel or math.huge | |
| local data = {[false] = rate, [true] = outRate or rate, startAccel = startaccel, stopAccel = stopAccel or startaccel, state = startingValue or 0, prevvel = 0} | |
| setmetatable(data, temporalSigmoidSmoothing) | |
| return data | |
| end | |
| function temporalSigmoidSmoothing:get(sample, dt) | |
| local dif = sample - self.state | |
| local prevvel = self.prevvel * max(fsign(self.prevvel * dif), 0) | |
| local vsq = prevvel * prevvel | |
| local absdif = abs(dif) | |
| local difsign = sign(dif) | |
| local acceldt | |
| local absdif2 = absdif * 2 | |
| if vsq > absdif2 * self.stopAccel then | |
| acceldt = -difsign * min((vsq / absdif2) * dt, abs(prevvel)) | |
| else | |
| acceldt = difsign * self.startAccel * dt | |
| end | |
| local ratelimit = self[dif * self.state >= 0] | |
| self.state = self.state + difsign * min(min(abs(prevvel + 0.5 * acceldt), ratelimit) * dt, absdif) | |
| self.prevvel = difsign * min(abs(prevvel + acceldt), ratelimit) | |
| return self.state | |
| end | |
| function temporalSigmoidSmoothing:getWithRateAccel(sample, dt, ratelimit, startAccel, stopAccel) | |
| local dif = sample - self.state | |
| local prevvel = self.prevvel * max(fsign(self.prevvel * dif), 0) | |
| local vsq = prevvel * prevvel | |
| local absdif = abs(dif) | |
| local difsign = sign(dif) | |
| local acceldt | |
| local absdif2 = absdif * 2 | |
| if vsq > absdif2 * (stopAccel or startAccel) then | |
| acceldt = -difsign * min((vsq / absdif2) * dt, abs(prevvel)) | |
| else | |
| acceldt = difsign * startAccel * dt | |
| end | |
| self.state = self.state + difsign * min(min(abs(prevvel + 0.5 * acceldt), ratelimit) * dt, absdif) | |
| self.prevvel = difsign * min(abs(prevvel + acceldt), ratelimit) | |
| return self.state | |
| end | |
| function temporalSigmoidSmoothing:set(sample) | |
| self.state = sample | |
| self.prevvel = 0 | |
| end | |
| function temporalSigmoidSmoothing:value() | |
| return self.state | |
| end | |
| --== Exponential/Non Linear temporal==-- | |
| local temporalSmoothingNonLinear = {} | |
| temporalSmoothingNonLinear.__index = temporalSmoothingNonLinear | |
| function newTemporalSmoothingNonLinear(inRate, outRate, startingValue) | |
| local rate = inRate or 1 | |
| local data = {[false] = rate, [true] = outRate or rate, state = startingValue or 0} | |
| setmetatable(data, temporalSmoothingNonLinear) | |
| return data | |
| end | |
| function temporalSmoothingNonLinear:get(sample, dt) | |
| local st = self.state | |
| local dif = sample - st | |
| local ratedt = self[dif * st >= 0] * dt | |
| st = st + dif * ratedt / (1 + ratedt) | |
| self.state = st | |
| return st | |
| end | |
| function temporalSmoothingNonLinear:getWithRate(sample, dt, rate) | |
| local st = self.state | |
| local ratedt = rate * dt | |
| st = st + (sample - st) * ratedt / (1 + ratedt) | |
| self.state = st | |
| return st | |
| end | |
| function temporalSmoothingNonLinear:set(sample) | |
| self.state = sample | |
| end | |
| function temporalSmoothingNonLinear:value() | |
| return self.state | |
| end | |
| function temporalSmoothingNonLinear:reset() | |
| self.state = 0 | |
| end | |
| --== Linear temporal ==-- | |
| local temporalSmoothing = {} | |
| temporalSmoothing.__index = temporalSmoothing | |
| function newTemporalSmoothing(inRate, outRate, autoCenterRate, startingValue) | |
| inRate = max(inRate or 1, 1e-307) | |
| startingValue = startingValue or 0 | |
| local data = {[false] = inRate, [true] = max(outRate or inRate, 1e-307), | |
| autoCenterRate = max(autoCenterRate or inRate, 1e-307), | |
| _startingValue = startingValue, | |
| state = startingValue} | |
| setmetatable(data, temporalSmoothing) | |
| if data.autoCenterRate ~= inRate then | |
| data.getUncapped = data.getUncappedAutoCenter | |
| end | |
| return data | |
| end | |
| function temporalSmoothing:getUncappedAutoCenter(sample, dt) | |
| local st = self.state | |
| local dif = (sample - st) | |
| local rate | |
| if sample == 0 then | |
| rate = self.autoCenterRate -- autocentering | |
| else | |
| rate = self[dif * st >= 0] | |
| end | |
| st = st + dif * min(rate * dt / abs(dif), 1) | |
| self.state = st | |
| return st | |
| end | |
| function temporalSmoothing:getUncapped(sample, dt) -- no autocenter | |
| local st = self.state | |
| local dif = sample - st | |
| st = st + dif * min(self[dif * st >= 0] * dt / abs(dif), 1) | |
| self.state = st | |
| return st | |
| end | |
| function temporalSmoothing:get(sample, dt) | |
| return max(min(self:getUncapped(sample, dt), 1), -1) | |
| end | |
| function temporalSmoothing:getWithRateUncapped(sample, dt, rate) | |
| local st = self.state | |
| local dif = (sample - st) | |
| st = st + dif * min(rate * dt / (abs(dif) + 1e-307), 1) | |
| self.state = st | |
| return st | |
| end | |
| function temporalSmoothing:getWithRate(sample, dt, rate) | |
| return max(min(self:getWithRateUncapped(sample, dt, rate), 1), -1) | |
| end | |
| function temporalSmoothing:reset() | |
| self.state = self._startingValue | |
| end | |
| function temporalSmoothing:value() | |
| return self.state | |
| end | |
| function temporalSmoothing:set(v) | |
| self.state = v | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment