Skip to content

Instantly share code, notes, and snippets.

@Bradshaw
Created November 28, 2014 10:18
Show Gist options
  • Save Bradshaw/6bbe0059f39c50393577 to your computer and use it in GitHub Desktop.
Save Bradshaw/6bbe0059f39c50393577 to your computer and use it in GitHub Desktop.
Unity Implementation of the 1€ filter for input smoothing
using UnityEngine;
using System.Collections;
public struct FloatOneEuroData
{
public float dx;
public float edx;
public float cutoff;
public float filthatxprev;
public float dfilthatxprev;
public bool firstTime;
}
public struct V2OneEuroData
{
public Vector2 dx;
public Vector2 edx;
public float cutoff;
public Vector2 filthatxprev;
public Vector2 dfilthatxprev;
public bool firstTime;
}
public struct V3OneEuroData
{
public Vector3 dx;
public Vector3 edx;
public float cutoff;
public Vector3 filthatxprev;
public Vector3 dfilthatxprev;
public bool firstTime;
}
public static class OneEuroExtensions {
public static Vector3 identity(this Vector3 v)
{
return v;
}
static float alpha(float rate, float cutoff)
{
float tau = 1 / (2 * Mathf.PI * cutoff);
float te = 1 / rate;
return 1 / (1 + tau / te);
}
public static float oneEuro(this float input, ref FloatOneEuroData euroData, float minCutoff = 1, float beta = 0.007f, float dCutoff = 1, float rate = 50)
{
if (euroData.firstTime)
{
euroData.dx = 0;
euroData.filthatxprev = input;
euroData.dfilthatxprev = 0;
euroData.firstTime = false;
}
else
{
euroData.dx = (input - euroData.filthatxprev) * rate;
}
euroData.edx = euroData.dx.filter(alpha(rate, dCutoff), ref euroData.dfilthatxprev);
euroData.cutoff = minCutoff + beta * Mathf.Abs(euroData.edx);
return input.filter(alpha(rate, euroData.cutoff), ref euroData.filthatxprev);
}
public static Vector2 oneEuro(this Vector2 input, ref V2OneEuroData euroData, float minCutoff = 1, float beta = 0.007f, float dCutoff = 1, float rate = 50)
{
if (euroData.firstTime)
{
euroData.dx = Vector2.zero;
euroData.filthatxprev = input;
euroData.dfilthatxprev = Vector2.zero;
euroData.firstTime = false;
}
else
{
euroData.dx = (input - euroData.filthatxprev) * rate;
}
euroData.edx = euroData.dx.filter(alpha(rate, dCutoff), ref euroData.dfilthatxprev);
euroData.cutoff = minCutoff + beta * euroData.edx.magnitude;
return input.filter(alpha(rate, euroData.cutoff), ref euroData.filthatxprev);
}
public static Vector3 oneEuro(this Vector3 input, ref V3OneEuroData euroData, float minCutoff = 1, float beta = 0.007f, float dCutoff = 1, float rate = 50)
{
if (euroData.firstTime)
{
euroData.dx = Vector3.zero;
euroData.filthatxprev = input;
euroData.dfilthatxprev = Vector3.zero;
euroData.firstTime = false;
}
else
{
euroData.dx = (input - euroData.filthatxprev) * rate;
}
euroData.edx = euroData.dx.filter(alpha(rate, dCutoff), ref euroData.dfilthatxprev);
euroData.cutoff = minCutoff + beta * euroData.edx.magnitude;
return input.filter(alpha(rate, euroData.cutoff), ref euroData.filthatxprev);
}
static float filter(this float input, float alpha, ref float hatxprev)
{
float hatx = input * alpha + hatxprev * (1 - alpha);
hatxprev = hatx;
return hatx;
}
static Vector2 filter(this Vector2 input, float alpha, ref Vector2 hatxprev)
{
Vector2 hatx = input * alpha + hatxprev * (1 - alpha);
hatxprev = hatx;
return hatx;
}
static Vector3 filter(this Vector3 input, float alpha, ref Vector3 hatxprev)
{
Vector3 hatx = input * alpha + hatxprev * (1 - alpha);
hatxprev = hatx;
return hatx;
}
}
using UnityEngine;
using System.Collections;
public class Wobbly : MonoBehaviour {
public GameObject go;
V3OneEuroData euroData;
// Use this for initialization
void Start () {
euroData.firstTime = true;
}
// Update is called once per frame
void Update () {
this.transform.position = go.transform.position.oneEuro(ref euroData);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment