KingPhantom

Spring.lua

Feb 20th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.59 KB | None | 0 0
  1. --[[
  2. class Spring
  3. Description:
  4.     A physical model of a spring, useful in many applications. Properties only evaluate
  5.     upon index making this model good for lazy applications
  6. API:
  7.     Spring = Spring.new(number position)
  8.         Creates a new spring in 1D
  9.     Spring = Spring.new(Vector3 position)
  10.         Creates a new spring in 3D
  11.     Spring.Position
  12.         Returns the current position
  13.     Spring.Velocity
  14.         Returns the current velocity
  15.     Spring.Target
  16.         Returns the target
  17.     Spring.Damper
  18.         Returns the damper
  19.     Spring.Speed
  20.         Returns the speed
  21.     Spring.Target = number/Vector3
  22.         Sets the target
  23.     Spring.Position = number/Vector3
  24.         Sets the position
  25.     Spring.Velocity = number/Vector3
  26.         Sets the velocity
  27.     Spring.Damper = number [0, 1]
  28.         Sets the spring damper, defaults to 1
  29.     Spring.Speed = number [0, infinity)
  30.         Sets the spring speed, defaults to 1
  31.     Spring:TimeSkip(number DeltaTime)
  32.         Instantly skips the spring forwards by that amount of time
  33.     Spring:Impulse(number/Vector3 velocity)
  34.         Impulses the spring, increasing velocity by the amount given
  35. ]]
  36.  
  37.  
  38. local Spring = {}
  39.  
  40. --- Creates a new spring
  41. -- @param initial A number or Vector3 (anything with * number and addition/subtraction defined)
  42. function Spring.new(initial)
  43.     local self = setmetatable({}, Spring)
  44.  
  45.     local target = initial or 0
  46.     rawset(self, "_time0", tick())
  47.     rawset(self, "_position0", target)
  48.     rawset(self, "_velocity0", 0*target)
  49.     rawset(self, "_target", target)
  50.     rawset(self, "_damper", 1)
  51.     rawset(self, "_speed", 1)
  52.  
  53.     return self
  54. end
  55.  
  56. --- Impulse the spring with a change in velocity
  57. -- @param velocity The velocity to impulse with
  58. function Spring:Impulse(velocity)
  59.     self.Velocity = self.Velocity + velocity
  60. end
  61.  
  62. --- Skip forwards in time
  63. -- @param delta Time to skip forwards
  64. function Spring:TimeSkip(delta)
  65.     local time = tick()
  66.     local position, velocity = self:_positionVelocity(time+delta)
  67.     rawset(self, "_position0", position)
  68.     rawset(self, "_velocity0", velocity)
  69.     rawset(self, "_time0", time)
  70. end
  71.  
  72. function Spring:__index(index)
  73.     if Spring[index] then
  74.         return Spring[index]
  75.     elseif index == "Value" or index == "Position" or index == "p" then
  76.         local position, _ = self:_positionVelocity(tick())
  77.         return position
  78.     elseif index == "Velocity" or index == "v" then
  79.         local _, velocity = self:_positionVelocity(tick())
  80.         return velocity
  81.     elseif index == "Target" or index == "t" then
  82.         return rawget(self, "_target")
  83.     elseif index == "Damper" or index == "d" then
  84.         return rawget(self, "_damper")
  85.     elseif index == "Speed" or index == "s" then
  86.         return rawget(self, "_speed")
  87.     else
  88.         error(("'%s' is not a valid member of Spring"):format(tostring(index)), 2)
  89.     end
  90. end
  91.  
  92. function Spring:__newindex(index, value)
  93.     local time = tick()
  94.  
  95.     if index == "Value" or index == "Position" or index == "p" then
  96.         local _, velocity = self:_positionVelocity(time)
  97.         rawset(self, "_position0", value)
  98.         rawset(self, "_velocity0", velocity)
  99.     elseif index == "Velocity" or index == "v" then
  100.         local position, _ = self:_positionVelocity(time)
  101.         rawset(self, "_position0", position)
  102.         rawset(self, "_velocity0", value)
  103.     elseif index == "Target" or index == "t" then
  104.         local position, velocity = self:_positionVelocity(time)
  105.         rawset(self, "_position0", position)
  106.         rawset(self, "_velocity0", velocity)
  107.         rawset(self, "_target", value)
  108.     elseif index == "Damper" or index == "d" then
  109.         local position, velocity = self:_positionVelocity(time)
  110.         rawset(self, "_position0", position)
  111.         rawset(self, "_velocity0", velocity)
  112.         rawset(self, "_damper", math.clamp(value, 0, 1))
  113.     elseif index == "Speed" or index == "s" then
  114.         local position, velocity = self:_positionVelocity(time)
  115.         rawset(self, "_position0", position)
  116.         rawset(self, "_velocity0", velocity)
  117.         rawset(self, "_speed", value < 0 and 0 or value)
  118.     else
  119.         error(("'%s' is not a valid member of Spring"):format(tostring(index)), 2)
  120.     end
  121.  
  122.     rawset(self, "_time0", time)
  123. end
  124.  
  125. function Spring:_positionVelocity(time)
  126.     local dt = time - rawget(self, "_time0")
  127.     local p0 = rawget(self, "_position0")
  128.     local v0 = rawget(self, "_velocity0")
  129.     local t = rawget(self, "_target")
  130.     local d = rawget(self, "_damper")
  131.     local s = rawget(self, "_speed")
  132.  
  133.     local c0 = p0-t
  134.     if s == 0 then
  135.         return p0, 0
  136.     elseif d<1 then
  137.         local c  = (1-d*d)^0.5
  138.         local c1 = (v0/s+d*c0)/c
  139.         local co = math.cos(c*s*dt)
  140.         local si = math.sin(c*s*dt)
  141.         local e  = 2.718281828459045^(d*s*dt)
  142.         return t+(c0*co+c1*si)/e,
  143.                s*((c*c1-d*c0)*co-(c*c0+d*c1)*si)/e
  144.     else
  145.         local c1 = v0/s+c0
  146.         local e  = 2.718281828459045^(s*dt)
  147.         return t+(c0+c1*s*dt)/e,
  148.                s*(c1-c0-c1*s*dt)/e
  149.     end
  150. end
  151.  
  152. return Spring
Add Comment
Please, Sign In to add comment