Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411431 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 20, 2024, 02:59:49 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Game Math: More on Numeric Springing
Pages: [1]
Print
Author Topic: Game Math: More on Numeric Springing  (Read 1584 times)
Allen Chou
Level 0
**



View Profile WWW
« on: April 26, 2015, 12:42:57 AM »

Original Blog Post with Pretty Equations
  
This post is part of my Game Math Series.  
  
Previously, I talked about numeric springing and provided some examples.
  
I have been saving up miscellaneous topics I would like to discuss about numeric spring, and now I have enough to write another post. Here are the topics:  
  
1. Using The Semi-Implicit Euler Method  
2. Numeric Springing vs. Tweening  
3. Half-Life Parameterization  
  
Using The Semi-Implicit Euler Method
  
Recall the differential equation for a damped spring:  
  
(d^2 x)/(d t^2) + 2 zeta omega (d x)(d t) + omega^2 (x - x_t) = 0  
  
And the equations for simulating such system obtained by the implicit Euler method:  
  
x_{i+1} &= Delta_x / Delta  
v_{i+1} &= Delta_v / Delta  
  
where:  
  
Delta = (1 + 2 h zeta) + h^2 omega^2  
Delta_x = (1 + 2 h zeta omega) x_i + h v_i + h^2 omega^2 x_t  
Delta_v = v_i + h ^2 (x_t - x_i)  
  
I presented the equations obtained by the implicit Euler method, because they are always stable. We can obtain a different set of equations that can also be used to simulate a damped spring system by the semi-implicit Euler method[/b]:  
  
v_{i+1} = (1 - 2 h zeta omega) v_i + h omega^2 (x_t - x_i)  
x_{i+1} = x_i + h v_{i+1}  
  
The equations obtained by the semi-implicit Euler method involve much less arithmetic operations, compared to the equations obtained by the implicit Euler method. There is a catch: the equations obtained by the semi-implicit Euler method can be unstable under certain configurations and the simulation will blow up over time. This can happen when you have a large zeta and omega. However, the zeta and omega on most use cases are far from the breaking values. You would almost never use an overdamped spring, so zeta is usually kept under 1. Even if zeta is set to 1 (critically damped spring), omega can be safely set up to 10 pi (5Hz), which is a very fast oscillation you probably would never use on anything.  
  
So, if your choice of zeta and omega result in a stable simulation with the equations obtained by the semi-implicit Euler method, you can use them instead of the equations obtained by the implicit Euler method, making your simulation more efficient.  
  
Here's a sample implementation:  
  
    /*
      x     - value             (input/output)
      v     - velocity          (input/output)
      xt    - target value      (input)
      zeta  - damping ratio     (input)
      omega - angular frequency (input)
      h     - time step         (input)
    */
    void SpringSemiImplicitEuler
    (
      float &x, float &v, float xt,
      float zeta, float omega, float h
    )
    {
      v += -2.0f * h * zeta * omega * v
           + h * omega * omega * (xt - x);
      x += h * v;
    }
  
  
Numeric Springing vs. Tweening
  
Numeric springing and tweening (usually used with the famous Robert Penner's easing equations[\url] might seem very similar at first, as they are both techniques to procedurally animate a numeric value towards a target value; however, they are actually fundamentally different. Tweening requires a pre-determined duration; numeric springing, on the other hand, does not have such requirement: numeric springing provides a simulation that goes on indefinitely. If you were to interrupt a procedural numeric animation and give it a new target value, numeric springing would handle this gracefully and the animation would still look very natural and smooth; it is a non-trivial task to interrupt a tweened animation, set up a new tween animation towards the new target value, and prevent the animation from looking visually jarring.  
  
Don't get me wrong. I'm not saying numeric springing is absolutely superior over tweening. They both have their uses. If your target value can change dynamically and you still want your animation to look nice, use numeric springing. If your animation has a fixed duration with no interruption, then tweening seems to be a better choice; in addition, there are a lot of different easing equations you can choose from that look visually interesting and not necessarily have a springy feel (e.g. sine, circ, bounce, slow-mo).  
  
  
Half-Life Parameterization
  
Previously, I proposed a parameterization for numeric springing that consisted of 3 parameters: the oscillation frequency f in Hz, and the fraction of oscillation magnitude reduced p_d over a specific duration t_d due to damping.  
  
I have received various feedback from forum comments, private messages, friends, and colleagues. The most suggested alternative parameterizatoin was the half-life parameterization, i.e. you specify the duration when the oscillation magnitude is reduced by 50%. This seems like a fair suggestion; thus, I'll to show you how to derive zeta to plug into numeric springing simulations, based on a given half-life.  
  
I'll use lambda to denote half-life. And yes, it is the same symbol from both Chemistry and the game.  
  
As previously discussed, the curve representing the oscillation magnitude decreases exponentially with this curve:  
  
x(t) = e^ {-zeta omega t}  
  
By definition, half-life is the duration of reduction by 50%:  
  
x(lambda) = e^ {-zeta omega lambda} = 0.5  
  
So we have:  
  
zeta omega = -ln(0.5) / lambda  
  
Once we decide the desired lambda, we lock in omega and compute zeta:  
  
zeta = -ln(0.5) / (omega lambda)  
  
And here's a sample implementation:  
  
    void SpringByHalfLife
    (
      float &x, float &v, float xt,
      float omega, float h, float lambda
    )
    {
      const float zeta = (-lambda / omega) * ln(0.5f);
      Spring(x, v, xt, zeta, omega, h);
    }
  
Here's a graph showing lambda = 0.5 and omega = 4 pi (2Hz). You can clearly see that the oscillation magnitude is reduced by 50% every half second, i.e. 25% every second.  
  

  
  
Conclusion
  
I've discussed how to implement numeric springing using the faster but less stable semi-implicit Euler method, the difference between numeric springing versus tweening, and the half-life parameterization of numeric springing.  
  
I hope this post has given you a better understanding of various aspects and applications of numeric springing.
« Last Edit: April 26, 2015, 08:47:53 AM by Allen Chou » Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #1 on: April 26, 2015, 06:58:35 AM »

What are the practical game application?
Logged

Allen Chou
Level 0
**



View Profile WWW
« Reply #2 on: April 26, 2015, 08:41:07 AM »

You can see some visual examples from the example link Smiley

[EDIT]

Oops. Looks like I forgot to make the hyperlink in the original post. Now it's fixed.
And here's the link again.
« Last Edit: April 26, 2015, 08:51:15 AM by Allen Chou » Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #3 on: April 26, 2015, 08:49:05 AM »

thanks Wink
Logged

Shadowspaz
Level 1
*



View Profile WWW
« Reply #4 on: April 27, 2015, 12:38:15 AM »

This is absolutely fantastic. It isn't something I've ever really thought about- I usually just fumble around with the numbers until I get the effect I want. Tongue

But this is really coherent. I'll probably be coming back to this before too long.
Logged

Check out my devlog!
oahda
Level 10
*****



View Profile
« Reply #5 on: April 27, 2015, 01:16:50 AM »

Can't you approximate this with something like sin(x) * (y -= dt) * z?
Logged

Allen Chou
Level 0
**



View Profile WWW
« Reply #6 on: April 27, 2015, 07:24:07 AM »

Can't you approximate this with something like sin(x) * (y -= dt) * z?

Yes, but then you lose the advantage of being able to dynamically change the target value and still maintaining a natural looking animation.
Logged

Allen Chou
Level 0
**



View Profile WWW
« Reply #7 on: May 20, 2015, 10:51:33 PM »

So someone made a script for GameMaker: Studio based on the original article on numeric springing.





YAY Smiley
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic