using System; using Unity.Mathematics; namespace UnityEngine.Splines { /// /// 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. /// public struct BezierCurve : IEquatable { /// /// First control point. /// public float3 P0; /// /// Second control point. /// Subtract from to derive the first tangent for a curve. /// public float3 P1; /// /// Third control point. /// Subtract from to derive the second tangent for a curve. /// public float3 P2; /// /// Fourth control point. /// public float3 P3; /// /// The direction and magnitude of the first tangent in a cubic curve. /// public float3 Tangent0 { get => P1 - P0; set => P1 = P0 + value; } /// /// The direction and magnitude of the second tangent in a cubic curve. /// public float3 Tangent1 { get => P2 - P3; set => P2 = P3 + value; } /// /// Construct a cubic Bezier curve from a linear curve. A linear curve is a straight line. /// /// The first control point. This is the start point of the curve. /// The second control point. This is the end point of the curve. public BezierCurve(float3 p0, float3 p1) { P0 = P2 = p0; P1 = P3 = p1; } /// /// Construct a cubic Bezier curve by elevating a quadratic curve. /// /// The first control point. This is the start point of the curve. /// The second control point. /// The third control point. This is the end point of the curve. 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; } /// /// Construct a cubic Bezier curve from a series of control points. /// /// The first control point. This is the start point of the curve. /// The second control point. /// The third control point. /// The fourth control point. This is the end point of the curve. public BezierCurve(float3 p0, float3 p1, float3 p2, float3 p3) { P0 = p0; P1 = p1; P2 = p2; P3 = p3; } /// /// Construct a cubic Bezier curve from a start and end . /// /// The knot to use as the first and second control points. The first control point is equal /// to , and the second control point is equal to /// ( + that's rotated by ). /// The knot to use as the third and fourth control points. The third control point is equal /// to ( + that's rotated by ), and the fourth control point is /// equal to . 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) { } /// /// Multiply the curve positions by a matrix. /// /// The matrix to multiply. /// A new BezierCurve multiplied by matrix. public BezierCurve Transform(float4x4 matrix) { return new BezierCurve( math.transform(matrix, P0), math.transform(matrix, P1), math.transform(matrix, P2), math.transform(matrix, P3)); } /// /// Create a BezierCurve from a start and end point plus tangent directions. /// /// Starting position of the curve. /// The direction and magnitude to the second control point. /// Ending position of the curve. /// The direction and magnitude to the third control point. /// A new BezierCurve from the derived control points. public static BezierCurve FromTangent(float3 pointA, float3 tangentOutA, float3 pointB, float3 tangentInB) { return new BezierCurve(pointA, pointA + tangentOutA, pointB + tangentInB, pointB); } /// /// Gets the same BezierCurve but in the opposite direction. /// /// Returns the BezierCurve struct in the inverse direction. public BezierCurve GetInvertedCurve() { return new BezierCurve(P3, P2, P1, P0); } /// /// Compare two curves for equality. /// /// The curve to compare against. /// Returns true when the control points of each curve are identical. public bool Equals(BezierCurve other) { return P0.Equals(other.P0) && P1.Equals(other.P1) && P2.Equals(other.P2) && P3.Equals(other.P3); } /// /// Compare against an object for equality. /// /// The object to compare against. /// /// Returns true when is a and the control points of each /// curve are identical. /// public override bool Equals(object obj) { return obj is BezierCurve other && Equals(other); } /// /// Calculate a hash code for this curve. /// /// /// A hash code for the curve. /// 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; } } /// /// Compare two curves for equality. /// /// The first curve. /// The second curve. /// Returns true when the control points of each curve are identical. public static bool operator ==(BezierCurve left, BezierCurve right) { return left.Equals(right); } /// /// Compare two curves for inequality. /// /// The first curve. /// The second curve. /// Returns false when the control points of each curve are identical. public static bool operator !=(BezierCurve left, BezierCurve right) { return !left.Equals(right); } } }