Building an Interpolation Library in C#: Part 1 – The Basics

In Part 1 of this series we’re going to write an extremely basic Interpolator class that linearly interpolates a value between two numbers.

Before we jump into anything, we need to create the class.

namespace Com.Naut.Math.Interpolation
{

	/// <summary>
	/// A basic interpolator class that tweens a float value between two values using linear interpolation.
	/// This simple interpolator does not loop and clamps the time between 0 and duration.
	/// </summary>
	public class Interpolator
	{
		
	}
}

Now that we have a class, let’s start with what we know- the core members. We need two values to interpolate between, a duration to tween over, and a current time position within the interpolation.

		/// <summary>The duration (in seconds) that the interpolation will take place over. Must be greater than 0.</summary>
		public float duration
		{
			get { return _duration; }
			set
			{
				if (value <= 0f) throw new ArgumentException("Supplied duration must be greater than 0!");
				_duration = value;
			}
		}
		private float _duration = 1f;

		/// <summary>The current elapsed time (in seconds) in the interpolation between 0 and duration.</summary>
		public float time
		{
			get { return _time; }
			set { _time = value; }
		}
		private float _time = 0f;

		/// <summary>The starting value to tween from.</summary>
		public float start
		{
			get { return _start; }
			set { _start = value; }
		}
		private float _start;

		/// <summary>The ending value to tween to.</summary>
		public float end
		{
			get { return _end; }
			set { _end = value; }
		}
		private float _end;

 

Great, let’s create a constructor to set them up.

		/// <summary>
		/// Creates a new interpolator that tweens from start to end over the specified duration.
		/// </summary>
		/// <param name="start">The starting value to tween from.</param>
		/// <param name="end">The ending value to tween to.</param>
		/// <param name="duration">The amount of time to tween over in seconds.</param>
		public Interpolator(float start, float end, float duration)
		{
			this.duration = duration;
			_start = start;
			_end = end;
		}

 

We now have all that we need to define our linear interpolation function. We set it up as a property called value. We’re going to use linear interpolation which boils down to… total amount of change, times current position as a percent of time over duration, plus the starting value. We use our previous two properties to simplify the code.

		/// <summary>The current value of the tween between start and end.</summary>
		public float value
		{
			get { return (_end - _start) * _time / _duration + _start; }
		}

 

That alone will work and we could simply alter the time or percent members to advance the tween, but that isn’t very practical and would make the class cumbersome to use.

Instead, we’re going to add a method to advance the interpolation over time. We add an update method that takes an elapsed time argument. It simply advances the time member and keeps it constrained within the valid portion of the duration.

		/// <summary>
		/// Advances the tween for the specified amount of time and returns the resulting value.
		/// </summary>
		/// <param name="elapsed">The amount of time to step forward or backward (in seconds).</param>
		/// <returns>The resulting value after the step.</returns>
		public float Update(float elapsed)
		{
			_time += elapsed;

			if (_time < 0f) _time = _duration;
			else if (_time > _duration) _time = _duration;

			return value;
		}

 

Voila! We have a complete, albeit very basic, interpolation class. Here is the full class.

using System;

namespace Com.Naut.Math.Interpolation
{

	/// <summary>
	/// A basic interpolator class that tweens a float value between two values using linear interpolation.
	/// This simple interpolator does not loop and clamps the time between 0 and duration.
	/// </summary>
	public class Interpolator
	{

		#region Members
		/// <summary>The duration (in seconds) that the interpolation will take place over. Must be greater than 0.</summary>
		public float duration
		{
			get { return _duration; }
			set
			{
				if (value <= 0f) throw new ArgumentException("Supplied duration must be greater than 0!");
				_duration = value;
			}
		}
		private float _duration = 1f;

		/// <summary>The current elapsed time (in seconds) in the interpolation between 0 and duration.</summary>
		public float time
		{
			get { return _time; }
			set { _time = value; }
		}
		private float _time = 0f;

		/// <summary>The starting value to tween from.</summary>
		public float start
		{
			get { return _start; }
			set { _start = value; }
		}
		private float _start;

		/// <summary>The ending value to tween to.</summary>
		public float end
		{
			get { return _end; }
			set { _end = value; }
		}
		private float _end;
		
		/// <summary>The total change the tween will interpolator over from start to end. </summary>
		public float delta
		{
			get { return _end - _start; }
		}

		/// <summary>The current position of the tween (in terms of percent complete).</summary>
		public float percent
		{
			get
			{
				if (_time <= 0f) return 0f;
				else if (_time >= _duration) return 1f;
				else return _time / _duration;
			}
			set
			{
				if (value < 0f) value = 0f;
				else if (value > 1f) value = 1f;
				_time = value * _duration;
			}
		}

		/// <summary>The current value of the tween between start and end.</summary>
		public float value
		{
			get { return percent * delta + _start; }
		}
		#endregion


		#region Initialization
		/// <summary>
		/// Creates a new interpolator that tweens from start to end over the specified duration.
		/// </summary>
		/// <param name="start">The starting value to tween from.</param>
		/// <param name="end">The ending value to tween to.</param>
		/// <param name="duration">The amount of time to tween over in seconds.</param>
		public Interpolator(float start, float end, float duration)
		{
			this.duration = duration;
			_start = start;
			_end = end;
		}
		#endregion


		#region Updating
		/// <summary>
		/// Advances the tween for the specified amount of time and returns the resulting value.
		/// </summary>
		/// <param name="elapsed">The amount of time to step forward or backward (in seconds).</param>
		/// <returns>The resulting value after the step.</returns>
		public float Update(float elapsed)
		{
			_time += elapsed;

			if (_time < 0f) _time = _duration;
			else if (_time > _duration) _time = _duration;

			return value;
		}
		#endregion

	}
}
Source Code:

C# Interpolation Library – Part 1

I put together a small demo of the interpolation class at work in Unity. If the demo is working you should see a small circle moving from the left to the right.

Good work today! In the next part, we’re going to bring some life to the animation using a few eases.

Continue to: Part 2 – Simple Easing

Leave a Reply

Your email address will not be published. Required fields are marked *