WuhuIslandTesting/Library/PackageCache/com.unity.splines@1.0.1/Runtime/BezierCurve.cs
2025-01-07 02:06:59 +01:00

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