Skip to content

Instantly share code, notes, and snippets.

@badjano
Last active August 25, 2017 22:06
Show Gist options
  • Save badjano/b4cd07eb58d4146b03931f02a09fdce9 to your computer and use it in GitHub Desktop.
Save badjano/b4cd07eb58d4146b03931f02a09fdce9 to your computer and use it in GitHub Desktop.
Bezier Interpolator
using System.Collections.Generic;
using UnityEngine;
using Vuforia;
[ExecuteInEditMode]
public class CurveTrackGenerator : MonoBehaviour
{
[SerializeField] private Color _color;
[SerializeField, Range(1f, 10f)] private float _momentum = 3;
private Vector3[] _points;
private enum CurveType
{
BEZIER,
BEZIER_EXPERIMENTAL,
SMOOTH,
STRAIGHT
}
[SerializeField] private CurveType _curveType;
private Vector3 GetInterpolatedPoint(Vector3[] vectors, float percentage)
{
while (vectors.Length > 2)
{
var newVectors = new Vector3[vectors.Length-1];
for (var i = 0; i < newVectors.Length; i++)
{
newVectors[i] = GetInterpolatedPoint(new[] {vectors[i], vectors[i + 1]}, percentage);
}
vectors = newVectors;
}
var a = vectors[0];
var b = vectors[1];
return a + (b - a) * percentage;
}
public Vector3[] GetPath(int steps)
{
List<Vector3> points = new List<Vector3>();
if (_curveType == CurveType.SMOOTH)
{
for( var k=1; k<transform.childCount-1; k++)
{
var startChild = transform.GetChild(k-1);
var middleChild = transform.GetChild(k);
var endChild = transform.GetChild(k+1);
if (k == 1)
{
var vectors = new Vector3[3];
vectors[0] = startChild.position;
vectors[1] = middleChild.position;
vectors[2] = (endChild.position + middleChild.position) * 0.5f;
for (var j = 0; j < steps; j++)
{
points.Add(GetInterpolatedPoint(vectors, j / (float)steps));
}
}
else
{
var vectors = new Vector3[3];
vectors[0] = (middleChild.position + startChild.position) * 0.5f;
vectors[1] = middleChild.position;
if (k == transform.childCount - 2)
{
vectors[2] = endChild.position;
}
else
{
vectors[2] = (endChild.position + middleChild.position) * 0.5f;
}
for (var j = 0; j < steps; j++)
{
points.Add(GetInterpolatedPoint(vectors, j / (float)steps));
}
if (k == transform.childCount - 2)
{
points.Add(endChild.position);
}
}
}
}
else if (_curveType == CurveType.BEZIER_EXPERIMENTAL)
{
var momentum = 10 / _momentum;
for( var k=1; k<transform.childCount-1; k++)
{
var p1 = transform.GetChild(k-1);
var p2 = transform.GetChild(k);
var p3 = transform.GetChild(k+1);
var d12 = Vector3.Distance(p1.position, p2.position);
var d23 = Vector3.Distance(p2.position, p3.position);
var cp = p2.position - Vector3.Normalize(p3.position - p1.position)*d12/momentum;
if (k == 1)
{
var vectors = new Vector3[3];
vectors[0] = p1.position;
vectors[1] = cp;
vectors[2] = p2.position;
for (var j = 0; j < steps; j++)
{
points.Add(GetInterpolatedPoint(vectors, j / (float) steps));
}
}
else
{
var p0 = transform.GetChild(k - 2);
var d01 = Vector3.Distance(p0.position, p1.position);
var cp1 = p1.position + Vector3.Normalize(p2.position - p0.position)*d12/momentum;
var vectors = new Vector3[4];
vectors[0] = p1.position;
vectors[1] = cp1;
vectors[2] = cp;
vectors[3] = p2.position;
for (var j = 0; j < steps; j++)
{
points.Add(GetInterpolatedPoint(vectors, j / (float) steps));
}
if (k == transform.childCount - 2)
{
var cp2 = p2.position + Vector3.Normalize(p3.position - p1.position)*d23/momentum;
vectors = new Vector3[3];
vectors[0] = p2.position;
vectors[1] = cp2;
vectors[2] = p3.position;
for (var j = 0; j < steps; j++)
{
points.Add(GetInterpolatedPoint(vectors, j / (float) steps));
}
points.Add(p3.position);
}
}
}
}
else if (_curveType == CurveType.BEZIER)
{
if (transform.childCount > 0 && transform.GetChild(0).childCount == 0)
{
var end = (int) (Mathf.Floor((transform.childCount-1) / 2f) * 2 - 1);
for( var k=0; k<end; k+=2)
{
var startChild = transform.GetChild(k);
var middleChild = transform.GetChild(k+1);
var endChild = transform.GetChild(k+2);
var vectors = new Vector3[3];
vectors[0] = startChild.position;
vectors[1] = middleChild.position;
vectors[2] = endChild.position;
for (var j = 0; j < steps; j++)
{
points.Add(GetInterpolatedPoint(vectors, j / (float)steps));
}
if (k == end-1)
{
points.Add(endChild.position);
}
}
}
else
{
for (var k = 0; k < transform.childCount; k++)
{
var child = transform.GetChild(k);
Vector3[] vectors = new Vector3[child.childCount];
if (k > 0)
{
vectors = new Vector3[child.childCount + 1];
var lastchild = transform.GetChild(k - 1);
vectors[0] = lastchild.GetChild(lastchild.childCount - 1).position;
for (var i = 0; i < child.childCount; i++)
{
vectors[i + 1] = child.GetChild(i).position;
}
}
else
{
for (var i = 0; i < child.childCount; i++)
{
vectors[i] = child.GetChild(i).position;
}
}
for (var j = 0; j < steps; j++)
{
points.Add(GetInterpolatedPoint(vectors, j / (float) steps));
}
if (k == transform.childCount - 1)
{
points.Add(vectors[vectors.Length - 1]);
}
}
}
}
else
{
for( var k=0; k<transform.childCount; k++)
{
var child = transform.GetChild(k);
points.Add(child.position);
}
}
return points.ToArray();
}
#if UNITY_EDITOR
void Update ()
{
Vector3[] bezier = GetPath(10);
for (var i = 0; i < bezier.Length-1; i++)
{
Debug.DrawLine(bezier[i],bezier[i+1],_color);
}
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment