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);
}
}
}