Skip to content

Commit

Permalink
Changes and new methods by nothke and bgr
Browse files Browse the repository at this point in the history
  • Loading branch information
bgr committed Oct 11, 2018
1 parent a4f8d24 commit cf2685e
Show file tree
Hide file tree
Showing 2 changed files with 250 additions and 15 deletions.
31 changes: 28 additions & 3 deletions Assets/BezierCurves/Editor/BezierCurveEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public override void OnInspectorGUI()
{
serializedObject.Update();

if (curve.resolution < 2) curve.resolution = 2;

EditorGUILayout.PropertyField(resolutionProp);
EditorGUILayout.PropertyField(closeProp);
EditorGUILayout.PropertyField(colorProp);
Expand All @@ -39,28 +41,51 @@ public override void OnInspectorGUI()

for (int i = 0; i < pointCount; i++)
{
if (curve[i] == null)
{
Debug.LogWarning("Point is missing, please clean up manually");
continue;
}

DrawPointInspector(curve[i], i);
}

if (GUILayout.Button("Add Point"))
{
GameObject pointObject = new GameObject("Point " + pointsProp.arraySize);
pointObject.transform.parent = curve.transform;
pointObject.transform.localPosition = Vector3.zero;

Undo.RegisterCreatedObjectUndo(pointObject, "Add Point");

Vector3 direction;
Vector3 pos;
if (pointCount >= 1)
{
direction = (curve.GetAnchorPoints()[pointCount - 1].handle2 - curve.GetAnchorPoints()[pointCount - 1].handle1).normalized;
pointObject.transform.localPosition = curve.GetAnchorPoints()[pointCount - 1].localPosition + direction * 2;
}
else
{
direction = Vector3.forward;
pointObject.transform.localPosition = Vector3.zero;
}

BezierPoint newPoint = pointObject.AddComponent<BezierPoint>();

newPoint.curve = curve;
newPoint.handle1 = Vector3.right * 0.1f;
newPoint.handle2 = -Vector3.right * 0.1f;
newPoint.handle1 = -direction;
newPoint.handle2 = direction;

pointsProp.InsertArrayElementAtIndex(pointsProp.arraySize);
pointsProp.GetArrayElementAtIndex(pointsProp.arraySize - 1).objectReferenceValue = newPoint;
}
}

if (GUILayout.Button("Clean-up null points"))
{
curve.CleanupNullPoints();
}

if (GUI.changed)
{
serializedObject.ApplyModifiedProperties();
Expand Down
234 changes: 222 additions & 12 deletions Assets/BezierCurves/Scripts/BezierCurve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,27 @@ public void AddPoint(BezierPoint point)
dirty = true;
}

public void InsertPoint(int index, BezierPoint point)
{
List<BezierPoint> tempArray = new List<BezierPoint>(points);
tempArray.Insert(index, point);
points = tempArray.ToArray();
dirty = true;
}

public BezierPoint CreatePointAt(Vector3 position)
{
GameObject pointObject = new GameObject("Point " + pointCount);

pointObject.transform.parent = transform;
pointObject.transform.position = position;

BezierPoint newPoint = pointObject.AddComponent<BezierPoint>();
newPoint.curve = this;

return newPoint;
}

/// <summary>
/// - Adds a point at position
/// </summary>
Expand All @@ -177,17 +198,34 @@ public void AddPoint(BezierPoint point)
/// </param>
public BezierPoint AddPointAt(Vector3 position)
{
GameObject pointObject = new GameObject("Point " + pointCount);
BezierPoint newPoint = CreatePointAt(position);

pointObject.transform.parent = transform;
pointObject.transform.position = position;
AddPoint(newPoint);

BezierPoint newPoint = pointObject.AddComponent<BezierPoint>();
newPoint.curve = this;
return newPoint;
}

public BezierPoint AddPointBehind(Vector3 position)
{
BezierPoint newPoint = CreatePointAt(position);

newPoint.transform.SetAsFirstSibling();
InsertPoint(0, newPoint);

return newPoint;
}

public BezierPoint InsertPointAt(int index, Vector3 position)
{
BezierPoint newPoint = CreatePointAt(position);

newPoint.transform.SetSiblingIndex(index);
InsertPoint(index, newPoint);

return newPoint;
}


/// <summary>
/// - Removes the given point from the curve ("points" array)
/// </summary>
Expand All @@ -202,6 +240,29 @@ public void RemovePoint(BezierPoint point)
dirty = false;
}

public void RemovePoint(int index)
{
List<BezierPoint> tempArray = new List<BezierPoint>(points);
tempArray.RemoveAt(index);
points = tempArray.ToArray();
dirty = false;
}

/// <summary>
/// To be called when errors start flying.
/// </summary>
public void CleanupNullPoints()
{
List<BezierPoint> cleanPoints = new List<BezierPoint>();

foreach (var p in points)
{
if (p != null) cleanPoints.Add(p);
}
points = cleanPoints.ToArray();
dirty = false;
}

/// <summary>
/// - Gets a copy of the bezier point array used to define this curve
/// </summary>
Expand All @@ -213,6 +274,12 @@ public BezierPoint[] GetAnchorPoints()
return (BezierPoint[])points.Clone();
}


public BezierPoint Last()
{
return this[points.Length - 1];
}

/// <summary>
/// - Gets the point at 't' percent along this curve
/// </summary>
Expand All @@ -233,17 +300,38 @@ public Vector3 GetPointAt(float t)
BezierPoint p1 = null;
BezierPoint p2 = null;

for (int i = 0; i < points.Length - 1; i++)
// code below modified by nothke

int approxResolution = 10;

int index = 0;
int maxIters = 10;

while (p1 == null && p2 == null)
{
curvePercent = ApproximateLength(points[i], points[i + 1], 10) / length;
if (totalPercent + curvePercent > t)
for (int i = 0; i < points.Length - 1; i++)
{
p1 = points[i];
p2 = points[i + 1];
break;
curvePercent = ApproximateLength(points[i], points[i + 1], approxResolution) / length;

if (totalPercent + curvePercent > t)
{
p1 = points[i];
p2 = points[i + 1];
break;
}

else totalPercent += curvePercent;
}

else totalPercent += curvePercent;
index++;

approxResolution += 10;

if (index >= maxIters)
{
Debug.LogWarning("TOO MUCH ITERATIONS!!!");
return Vector3.zero;
}
}

if (close && p1 == null)
Expand All @@ -254,9 +342,111 @@ public Vector3 GetPointAt(float t)

t -= totalPercent;

if (p1 == null) Debug.LogError("p1 is null");
if (p2 == null) Debug.LogError("p2 is null");

return GetPoint(p1, p2, t / curvePercent);
}

public Vector3 GetTangentAt(float t)
{
if (t <= 0) return points[0].position;
else if (t >= 1) return points[points.Length - 1].position;

float totalPercent = 0;
float curvePercent = 0;

BezierPoint p1 = null;
BezierPoint p2 = null;

int approxResolution = 10; // added by nothke

int index = 0;
int maxIters = 10;

while (p1 == null && p2 == null)
{
for (int i = 0; i < points.Length - 1; i++)
{
curvePercent = ApproximateLength(points[i], points[i + 1], approxResolution) / length;

if (totalPercent + curvePercent > t)
{
p1 = points[i];
p2 = points[i + 1];
break;
}

else totalPercent += curvePercent;
}

index++;

approxResolution += 10;

if (index >= maxIters)
{
Debug.LogWarning("TOO MUCH ITERATIONS!!!");
return Vector3.zero;
}
}

if (close && p1 == null)
{
p1 = points[points.Length - 1];
p2 = points[0];
}

t -= totalPercent;

if (p1 == null) Debug.LogError("p1 is null");
if (p2 == null) Debug.LogError("p2 is null");

return GetTangent(p1, p2, t / curvePercent);
}

public Vector3 GetTangent(BezierPoint bp1, BezierPoint bp2, float t)
{
if (bp1.handleStyle == BezierPoint.HandleStyle.None &&
bp2.handleStyle == BezierPoint.HandleStyle.None)
{
return (bp2.position - bp1.position).normalized;
}

Vector3 a = bp1.position;
Vector3 b = bp1.globalHandle2;
Vector3 c = bp2.globalHandle1;
Vector3 d = bp2.position;

return Tangent(a, b, c, d, t);
}

public Vector3 GetLocalTangent(BezierPoint bp1, BezierPoint bp2, float t)
{
if (bp1.handleStyle == BezierPoint.HandleStyle.None &&
bp2.handleStyle == BezierPoint.HandleStyle.None)
{
return (bp2.localPosition - bp1.localPosition).normalized;
}

Vector3 a = bp1.localPosition;
Vector3 b = bp1.localPosition + bp1.handle2;
Vector3 c = bp2.localPosition + bp2.handle1;
Vector3 d = bp2.localPosition;

return Tangent(a, b, c, d, t);
}

public static Vector3 Tangent(Vector3 a, Vector3 b, Vector3 c, Vector3 d, float t)
{
Vector3 C1 = (d - (3.0f * c) + (3.0f * b) - a);
Vector3 C2 = ((3.0f * c) - (6.0f * b) + (3.0f * a));
Vector3 C3 = ((3.0f * b) - (3.0f * a));
//Vector3 C4 = (a);

return ((3.0f * C1 * t * t) + (2.0f * C2 * t) + C3);
}

/// <summary>
/// - Get the index of the given point in this curve
/// </summary>
Expand Down Expand Up @@ -352,6 +542,26 @@ public static Vector3 GetPoint(BezierPoint p1, BezierPoint p2, float t)
}
}

public static Vector3 GetPointLocal(BezierPoint p1, BezierPoint p2, float t)
{
//Vector3 p1H1 = p1.localPosition + p1.handle1;
Vector3 p1H2 = p1.localPosition + p1.handle2;
Vector3 p2H1 = p2.localPosition + p2.handle1;
//Vector3 p2H2 = p2.localPosition + p2.handle2;

if (p1.handle2 != Vector3.zero)
{
if (p2.handle1 != Vector3.zero) return GetCubicCurvePoint(p1.localPosition, p1H2, p2H1, p2.localPosition, t);
else return GetQuadraticCurvePoint(p1.localPosition, p1H2, p2.localPosition, t);
}

else
{
if (p2.handle1 != Vector3.zero) return GetQuadraticCurvePoint(p1.localPosition, p2H1, p2.localPosition, t);
else return GetLinearPoint(p1.localPosition, p2.localPosition, t);
}
}

/// <summary>
/// - Gets the point 't' percent along a third-order curve
/// </summary>
Expand Down

0 comments on commit cf2685e

Please sign in to comment.