188 lines
7.4 KiB
C#
188 lines
7.4 KiB
C#
using System;
|
|
using Unity.Mathematics;
|
|
|
|
namespace UnityEngine.Splines
|
|
{
|
|
/// <summary>
|
|
/// Control points for a cubic bezier curve.
|
|
///
|
|
/// Points P0 through P3 are in sequential order, describing the starting point, second, third, and ending controls
|
|
/// for a cubic bezier curve.
|
|
/// </summary>
|
|
public struct BezierCurve : IEquatable<BezierCurve>
|
|
{
|
|
/// <summary>
|
|
/// First control point.
|
|
/// </summary>
|
|
public float3 P0;
|
|
|
|
/// <summary>
|
|
/// Second control point.
|
|
/// Subtract <see cref="P0"/> from <see cref="P1"/> to derive the first tangent for a curve.
|
|
/// </summary>
|
|
public float3 P1;
|
|
|
|
/// <summary>
|
|
/// Third control point.
|
|
/// Subtract <see cref="P3"/> from <see cref="P2"/> to derive the second tangent for a curve.
|
|
/// </summary>
|
|
public float3 P2;
|
|
|
|
/// <summary>
|
|
/// Fourth control point.
|
|
/// </summary>
|
|
public float3 P3;
|
|
|
|
/// <summary>
|
|
/// The direction and magnitude of the first tangent in a cubic curve.
|
|
/// </summary>
|
|
public float3 Tangent0
|
|
{
|
|
get => P1 - P0;
|
|
set => P1 = P0 + value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The direction and magnitude of the second tangent in a cubic curve.
|
|
/// </summary>
|
|
public float3 Tangent1
|
|
{
|
|
get => P2 - P3;
|
|
set => P2 = P3 + value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a cubic bezier curve from a linear curve. A linear curve is simply a straight line.
|
|
/// </summary>
|
|
/// <param name="p0">The first control point. This is the start point of the curve.</param>
|
|
/// <param name="p1">The second control point. This is the end point of the curve.</param>
|
|
public BezierCurve(float3 p0, float3 p1)
|
|
{
|
|
P0 = P2 = p0;
|
|
P1 = P3 = p1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a cubic bezier curve by elevating a quadratic curve.
|
|
/// </summary>
|
|
/// <param name="p0">The first control point. This is the start point of the curve.</param>
|
|
/// <param name="p1">The second control point.</param>
|
|
/// <param name="p2">The third control point. This is the end point of the curve.</param>
|
|
public BezierCurve(float3 p0, float3 p1, float3 p2)
|
|
{
|
|
const float k_13 = 1 / 3f;
|
|
const float k_23 = 2 / 3f;
|
|
float3 tan = k_23 * p1;
|
|
|
|
P0 = p0;
|
|
P1 = k_13 * p0 + tan;
|
|
P2 = k_13 * p2 + tan;
|
|
P3 = p2;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a cubic bezier curve from a series of control points.
|
|
/// </summary>
|
|
/// <param name="p0">The first control point. This is the start point of the curve.</param>
|
|
/// <param name="p1">The second control point.</param>
|
|
/// <param name="p2">The third control point.</param>
|
|
/// <param name="p3">The fourth control point. This is the end point of the curve.</param>
|
|
public BezierCurve(float3 p0, float3 p1, float3 p2, float3 p3)
|
|
{
|
|
P0 = p0;
|
|
P1 = p1;
|
|
P2 = p2;
|
|
P3 = p3;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a cubic bezier curve from a start and end <see cref="BezierKnot"/>.
|
|
/// </summary>
|
|
/// <param name="a">The knot to use as the first and second control points. The first control point is equal
|
|
/// to <see cref="BezierKnot.Position"/>, and the second control point is equal to
|
|
/// (<see cref="BezierKnot.Position"/> + <see cref="BezierKnot.TangentOut"/> that's rotated by <see cref="BezierKnot.Rotation"/>).</param>
|
|
/// <param name="b">The knot to use as the third and fourth control points. The third control point is equal
|
|
/// to (<see cref="BezierKnot.Position"/> + <see cref="BezierKnot.TangentIn"/> that's rotated by <see cref="BezierKnot.Rotation"/>), and the fourth control point is
|
|
/// equal to <see cref="BezierKnot.Position"/>.</param>
|
|
public BezierCurve(BezierKnot a, BezierKnot b) :
|
|
this(a.Position, a.Position + math.rotate(a.Rotation, a.TangentOut), b.Position + math.rotate(b.Rotation, b.TangentIn), b.Position)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a BezierCurve from a start and end point plus tangent directions.
|
|
/// </summary>
|
|
/// <param name="pointA">Starting position of the curve.</param>
|
|
/// <param name="tangentOutA">The direction and magnitude to the second control point.</param>
|
|
/// <param name="pointB">Ending position of the curve.</param>
|
|
/// <param name="tangentInB">The direction and magnitude to the third control point.</param>
|
|
/// <returns>A new BezierCurve from the derived control points.</returns>
|
|
public static BezierCurve FromTangent(float3 pointA, float3 tangentOutA, float3 pointB, float3 tangentInB)
|
|
{
|
|
return new BezierCurve(pointA, pointA + tangentOutA, pointB + tangentInB, pointB);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compare two curves for equality.
|
|
/// </summary>
|
|
/// <param name="other">The curve to compare against.</param>
|
|
/// <returns>Returns true when the control points of each curve are identical.</returns>
|
|
public bool Equals(BezierCurve other)
|
|
{
|
|
return P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2) && P3.Equals(other.P3);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compare against an object for equality.
|
|
/// </summary>
|
|
/// <param name="obj">The object to compare against.</param>
|
|
/// <returns>
|
|
/// Returns true when <paramref name="obj"/> is a <see cref="BezierCurve"/> and the control points of each
|
|
/// curve are identical.
|
|
/// </returns>
|
|
public override bool Equals(object obj)
|
|
{
|
|
return obj is BezierCurve other && Equals(other);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a hash code for this curve.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A hash code for the curve.
|
|
/// </returns>
|
|
public override int GetHashCode()
|
|
{
|
|
unchecked
|
|
{
|
|
int hashCode = P0.GetHashCode();
|
|
hashCode = (hashCode * 397) ^ P1.GetHashCode();
|
|
hashCode = (hashCode * 397) ^ P2.GetHashCode();
|
|
hashCode = (hashCode * 397) ^ P3.GetHashCode();
|
|
return hashCode;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compare two curves for equality.
|
|
/// </summary>
|
|
/// <param name="left">The first curve.</param>
|
|
/// <param name="right">The second curve.</param>
|
|
/// <returns>Returns true when the control points of each curve are identical.</returns>
|
|
public static bool operator ==(BezierCurve left, BezierCurve right)
|
|
{
|
|
return left.Equals(right);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compare two curves for inequality.
|
|
/// </summary>
|
|
/// <param name="left">The first curve.</param>
|
|
/// <param name="right">The second curve.</param>
|
|
/// <returns>Returns false when the control points of each curve are identical.</returns>
|
|
public static bool operator !=(BezierCurve left, BezierCurve right)
|
|
{
|
|
return !left.Equals(right);
|
|
}
|
|
}
|
|
}
|