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;
}
}