Created
June 10, 2015 14:01
-
-
Save kschieck/0aa205abad413c0e5654 to your computer and use it in GitHub Desktop.
Unity3d class used to make objects follow a curve
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; // for Vector3 | |
/// <summary> | |
/// A utility for finding points along a bezier curve | |
/// ref: http://en.wikipedia.org/wiki/B%C3%A9zier_curve | |
/// </summary> | |
public class Bezier | |
{ | |
/// <summary> | |
/// Get point a certain distance after point at t | |
/// </summary> | |
/// <param name="iterations">degree of accuracy</param> | |
/// <param name="t">Time associated with the start point (before distance is added)</param> | |
/// <param name="t_out">(out)Time associated with the end point (after distance is added)</param> | |
/// <param name="Distance">How far to travel after point at t</param> | |
/// <param name="Angle">Angle associated with end point</param> | |
/// <param name="Points">Bezier control points</param> | |
/// <returns>Point on Bezier curve</returns> | |
public static Vector3 GetPoint(int iterations, float t, out float t_out, float Distance, out Quaternion Angle, params Vector3[] Points) | |
{ | |
Vector3 start_pos = GetPoint(t, out Angle, Points); | |
float delta_t = Time.deltaTime; | |
Vector3 end_pos = GetPoint(t + delta_t, out Angle, Points); | |
for (int i = 0; i < iterations; i++) | |
{ | |
delta_t *= Distance / (end_pos - start_pos).magnitude; | |
end_pos = GetPoint(t + delta_t, out Angle, Points); | |
} | |
t_out = t + delta_t; | |
return end_pos; | |
} | |
/// <summary> | |
/// Get a point along a Berzier Curve of any degree | |
/// </summary> | |
/// <param name="t">Percentage along the curve [0-1]</param> | |
/// <param name="Angle">3D derivative of the curve at the point</param> | |
/// <param name="Points">Start point, Control point(s), End point</param> | |
/// <returns>Vector3 location along the curve</returns> | |
public static Vector3 GetPoint(float t, out Quaternion Angle, params Vector3[] Points) | |
{ | |
int n = Points.Length-1; | |
//Calculate all t^i (i in 1 to n) | |
float t_ = (1 - t); | |
float[] t_Exp = new float[n+1]; | |
t_Exp[0] = 1; | |
for (int i = 1; i <= n; i++) | |
{ | |
t_Exp[i] = t_Exp[i - 1] * t_; | |
} | |
//Calculate the point | |
Vector3 Point = new Vector3(0f, 0f, 0f); | |
Vector3 AnglePoint = new Vector3(0f, 0f, 0f); | |
float tCoefficient = 1f; | |
for (int i = 0; i <= n; i++) | |
{ | |
//Incorporate next line into position | |
Point += NchooseK(n, i) * t_Exp[n - i] * tCoefficient * Points[i]; | |
//Incorporate next line into angle | |
if (i == n) continue; | |
AnglePoint += NchooseK(n-1, i) * t_Exp[n-1-i] * tCoefficient * (Points[i+1] - Points[i]); | |
//Fix tCoefficient for next loop (t^i) | |
tCoefficient *= t; | |
} | |
Angle = Quaternion.LookRotation(AnglePoint, Vector3.up); | |
return Point; | |
} | |
/// <summary> | |
/// Calculate the choose function with integers | |
/// </summary> | |
/// <param name="n">Number of elements to choose from</param> | |
/// <param name="k">Number of elements to choose</param> | |
/// <returns>Integer result for the mathmatical function n choose k</returns> | |
private static int NchooseK(int n, int k) | |
{ | |
int i = Mathf.Max(n-k, k); | |
int rv = 1; | |
for (int j = i+1; j<= n; j++) { rv *= j; } | |
for (int j = n-i; j>0; j--) { rv /= j; } | |
return rv; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment