Leitris

Damped Springs

Feb 20th, 2016
279
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.40 KB | None | 0 0
  1. --******************************************************************************
  2. -- CalcDampedSimpleHarmonicMotion
  3. -- This function will update the supplied position and velocity values over
  4. -- the given time according to the spring parameters.
  5. -- - An angular frequency is given to control how fast the spring oscillates.
  6. -- - A damping ratio is given to control how fast the motion decays.
  7. --     damping ratio > 1: over damped
  8. --     damping ratio = 1: critically damped
  9. --     damping ratio < 1: under damped
  10. --******************************************************************************
  11. function CalcDampedSimpleHarmonicMotion()
  12.     local pPos              = -- position value to update
  13.     local pVel              = -- velocity value to update
  14.     local equilibriumPos    = -- position to approach
  15.     local deltaTime         = -- time to update over
  16.     local angularFrequency  = -- angular frequency of motion
  17.     local dampingRatio      = -- damping ratio of motion
  18.     local initialPos        = 0
  19.     local initialVel        = 0
  20.    
  21.     local epsilon = 0.0001
  22.      
  23.     -- if there is no angular frequency, the spring will not move
  24.     if angularFrequency < epsilon then
  25.         return
  26.     end
  27.    
  28.     -- clamp the damping ratio in legal range
  29.     if dampingRatio < 0.0 then
  30.         dampingRatio = 0.0
  31.         -- calculate initial state in equilibrium relative space
  32.         initialPos = pPos - equilibriumPos
  33.         initialVel = pVel
  34.     end
  35.    
  36.     -- if over-damped
  37.     if dampingRatio > (1.0 + epsilon) then
  38.         -- calculate constants based on motion parameters
  39.         -- Note: These could be cached off between multiple calls using the same
  40.         -- parameters for deltaTime, angularFrequency and dampingRatio.
  41.         local za        = -angularFrequency * dampingRatio
  42.         local zb        = angularFrequency * math.sqrt(dampingRatio*dampingRatio - 1.0)
  43.         local z1        = za - zb
  44.         local z2        = za + zb
  45.         local expTerm1  = math.exp(z1 * deltaTime)
  46.         local expTerm2  = math.exp(z2 * deltaTime)
  47.      
  48.         --update motion
  49.         local c1    = (initialVel - initialPos*z2) / (-2.0*zb) -- z1 - z2 = -2*zb
  50.         local c2    = initialPos - c1
  51.         pPos        = equilibriumPos + c1*expTerm1 + c2*expTerm2
  52.         pVel        = c1*z1*expTerm1 + c2*z2*expTerm2
  53.        
  54.     -- else if critically damped
  55.     elseif dampingRatio > (1.0 - epsilon) then
  56.         -- calculate constants based on motion parameters
  57.         -- Note: These could be cached off between multiple calls using the same
  58.         -- parameters for deltaTime, angularFrequency and dampingRatio.
  59.         local expTerm = math.exp(-angularFrequency * deltaTime)
  60.        
  61.         --update motion
  62.         local c1    = initialVel + angularFrequency * initialPos
  63.         local c2    = initialPos
  64.         local c3    = (c1*deltaTime + c2) * expTerm
  65.         pPos        = equilibriumPos + c3
  66.         pVel        = (c1*expTerm) - (c3*angularFrequency)
  67.    
  68.     --else under-damped
  69.     else
  70.         -- calculate constants based on motion parameters
  71.         -- Note: These could be cached off between multiple calls using the same
  72.         -- parameters for deltaTime, angularFrequency and dampingRatio.
  73.         local omegaZeta = angularFrequency * dampingRatio
  74.         local alpha     = angularFrequency * math.sqrt(1.0 - (dampingRatio*dampingRatio))
  75.         local expTerm   = math.exp(-omegaZeta * deltaTime)
  76.         local cosTerm   = math.cos(alpha * deltaTime)
  77.         local sinTerm   = math.sin(alpha * deltaTime)
  78.        
  79.         -- update motion
  80.         local c1    = initialPos
  81.         local c2    = (initialVel + (omegaZeta*initialPos)) / alpha
  82.         pPos        = equilibriumPos + (expTerm*((c1*cosTerm) + (c2*sinTerm)))
  83.         pVel        = -expTerm*(((c1*omegaZeta) - (c2*alpha))*cosTerm + ((c1*alpha) + (c2*omegaZeta))*sinTerm)
  84.     end
  85. end
Add Comment
Please, Sign In to add comment