Critically Damped Springs
Saturday 11th of May 2013 10:36:59 AM

This class is one I turn to it again and again, especially when animating OSD components or creating camera controllers.

What it does is update an object's position and velocity towards a target destination over an arbitrary amount of time. The spring velocity will be damped over time meaning it slows down as it reaches its target.

To use it as a camera spring create one for the camera position and another for the target and update these values every frame, then call Update() passing the frame delta.

using Microsoft.Xna.Framework;

namespace Utils
{
    public class CriticallyDampedSpring
    {
        public CriticallyDampedSpring()
        {
            SmoothTime = 100.0f;
        }

        public float SmoothTime { get; set; }
        public Vector3 Current { get; set; }
        public Vector3 SpringVelocity { get; set; }
        public Vector3 Target
        {
            get { return mValTo; }
            set
            {
                mValFrom = Current;
                mValTo = value;
            }
        }

        public void Update(float frameTime)
        {
            Vector3 diff, temp;
            float omega, rX, expo;

            omega = 2.0f / SmoothTime;
            rX = omega * frameTime;
            expo = 1.0f /
                (1.0f + rX +
                (kQuadraticCoef * rX * rX) +
                (kCubicCoef * rX * rX * rX));

            diff = mValFrom - mValTo;
            temp = (SpringVelocity + (diff * omega)) * frameTime;
            SpringVelocity = (SpringVelocity - (temp * omega)) * expo;

            Current = mValTo + ((diff + temp) * expo);
        }

        // Start position of spring head
        private Vector3 mValFrom = Vector3.Zero;
        
        // Target position of spring head
        private Vector3 mValTo = Vector3.Zero;     

        private const float kQuadraticCoef = 0.48f;
        private const float kCubicCoef = 0.235f;

    }
}