166 lines
6.2 KiB
C#
166 lines
6.2 KiB
C#
|
using System.Collections.Generic;
|
||
|
using Unity.Mathematics;
|
||
|
|
||
|
namespace UnityEngine.Splines
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// A Component that holds a <see cref="Spline"/> object.
|
||
|
/// </summary>
|
||
|
#if UNITY_2021_2_OR_NEWER
|
||
|
[Icon(k_IconPath)]
|
||
|
#endif
|
||
|
[AddComponentMenu("Splines/Spline")]
|
||
|
public sealed class SplineContainer : MonoBehaviour, ISplineProvider
|
||
|
{
|
||
|
const string k_IconPath = "Packages/com.unity.splines/Editor/Resources/Icons/SplineComponent.png";
|
||
|
|
||
|
readonly Spline[] m_SplineArray = new Spline[1];
|
||
|
|
||
|
[SerializeField]
|
||
|
Spline m_Spline = new Spline();
|
||
|
|
||
|
IEnumerable<Spline> ISplineProvider.Splines
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
m_SplineArray[0] = Spline;
|
||
|
return m_SplineArray;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool IsScaled => transform.lossyScale != Vector3.one;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The instantiated <see cref="Spline"/> object attached to this component.
|
||
|
/// </summary>
|
||
|
public Spline Spline
|
||
|
{
|
||
|
get => m_Spline;
|
||
|
set => m_Spline = value;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Compute interpolated position, direction and upDirection at ratio t. Calling this method to get the
|
||
|
/// 3 vectors is faster than calling independently EvaluateSplinePosition, EvaluateSplineTangent and EvaluateSplineUpVector
|
||
|
/// for the same time t as it reduces some redundant computation.
|
||
|
/// </summary>
|
||
|
/// <param name="t">A value between 0 and 1 representing the ratio along the curve.</param>
|
||
|
/// <param name="position">Output variable for the float3 position at t.</param>
|
||
|
/// <param name="tangent">Output variable for the float3 tangent at t.</param>
|
||
|
/// <param name="upVector">Output variable for the float3 up direction at t.</param>
|
||
|
/// <returns>Boolean value, true if a valid set of output variables as been computed.</returns>
|
||
|
public bool Evaluate(float t, out float3 position, out float3 tangent, out float3 upVector)
|
||
|
{
|
||
|
if (Spline == null)
|
||
|
{
|
||
|
position = float3.zero;
|
||
|
tangent = new float3(0, 0, 1);
|
||
|
upVector = new float3(0, 1, 0);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (IsScaled)
|
||
|
{
|
||
|
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
|
||
|
return SplineUtility.Evaluate(nativeSpline, t, out position, out tangent, out upVector);
|
||
|
}
|
||
|
|
||
|
var evaluationStatus = SplineUtility.Evaluate(Spline, t, out position, out tangent, out upVector);
|
||
|
if (evaluationStatus)
|
||
|
{
|
||
|
position = transform.TransformPoint(position);
|
||
|
tangent = transform.TransformVector(tangent);
|
||
|
upVector = transform.TransformDirection(upVector);
|
||
|
}
|
||
|
|
||
|
return evaluationStatus;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Evaluate a tangent vector on a curve at a specific t in world space.
|
||
|
/// </summary>
|
||
|
/// <param name="t">A value between 0 and 1 representing a percentage of the curve.</param>
|
||
|
/// <returns>A tangent vector.</returns>
|
||
|
public float3 EvaluatePosition(float t)
|
||
|
{
|
||
|
if(Spline == null)
|
||
|
return float.PositiveInfinity;
|
||
|
|
||
|
if(IsScaled)
|
||
|
{
|
||
|
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
|
||
|
return SplineUtility.EvaluatePosition(nativeSpline, t);
|
||
|
}
|
||
|
return transform.TransformPoint(SplineUtility.EvaluatePosition(Spline, t));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Evaluate a tangent vector at a specific t in world space.
|
||
|
/// </summary>
|
||
|
/// <param name="t">A value between 0 and 1 representing a percentage of entire spline</param>
|
||
|
/// <returns>A tangent vector</returns>
|
||
|
public float3 EvaluateTangent(float t)
|
||
|
{
|
||
|
if (Spline == null)
|
||
|
return 0;
|
||
|
|
||
|
if(IsScaled)
|
||
|
{
|
||
|
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
|
||
|
return SplineUtility.EvaluateTangent(nativeSpline, t);
|
||
|
}
|
||
|
return transform.TransformVector(SplineUtility.EvaluateTangent(Spline, t));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Evaluate an up vector direction at a specific t
|
||
|
/// </summary>
|
||
|
/// <param name="t">A value between 0 and 1 representing a percentage of entire spline</param>
|
||
|
/// <returns>An up direction.</returns>
|
||
|
public float3 EvaluateUpVector(float t)
|
||
|
{
|
||
|
if (Spline == null)
|
||
|
return float.PositiveInfinity;
|
||
|
|
||
|
if(IsScaled)
|
||
|
{
|
||
|
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
|
||
|
return SplineUtility.EvaluateUpVector(nativeSpline, t);
|
||
|
}
|
||
|
|
||
|
//Using TransformDirection as up direction is Not sensible to scale
|
||
|
return transform.TransformDirection(SplineUtility.EvaluateUpVector(Spline, t));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Evaluate an acceleration vector at a specific t
|
||
|
/// </summary>
|
||
|
/// <param name="t">A value between 0 and 1 representing a percentage of entire spline</param>
|
||
|
/// <returns>An acceleration vector.</returns>
|
||
|
public float3 EvaluateAcceleration(float t)
|
||
|
{
|
||
|
if (Spline == null)
|
||
|
return float.PositiveInfinity;
|
||
|
|
||
|
if(IsScaled)
|
||
|
{
|
||
|
using var nativeSpline = new NativeSpline(Spline, transform.localToWorldMatrix);
|
||
|
return SplineUtility.EvaluateAcceleration(nativeSpline, t);
|
||
|
}
|
||
|
return transform.TransformVector(SplineUtility.EvaluateAcceleration(Spline, t));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Calculate the length of <see cref="Spline"/> in world space.
|
||
|
/// </summary>
|
||
|
/// <returns>The length of <see cref="Spline"/> in world space</returns>
|
||
|
public float CalculateLength()
|
||
|
{
|
||
|
if(Spline == null)
|
||
|
return 0;
|
||
|
|
||
|
return SplineUtility.CalculateLength(Spline, transform.localToWorldMatrix);
|
||
|
}
|
||
|
}
|
||
|
}
|