using UnityEngine;
using System.Collections.Generic;
namespace UnityEngine.ProBuilder
{
///
/// How bezier handles behave when being manipulated in the scene view.
///
enum BezierTangentMode
{
Free,
Aligned,
Mirrored
}
enum BezierTangentDirection
{
In,
Out
}
///
/// A bezier knot.
///
[System.Serializable]
struct BezierPoint
{
public Vector3 position;
public Vector3 tangentIn;
public Vector3 tangentOut;
public Quaternion rotation;
public BezierPoint(Vector3 position, Vector3 tangentIn, Vector3 tangentOut, Quaternion rotation)
{
this.position = position;
this.tangentIn = tangentIn;
this.tangentOut = tangentOut;
this.rotation = rotation;
}
public void EnforceTangentMode(BezierTangentDirection master, BezierTangentMode mode)
{
if (mode == BezierTangentMode.Aligned)
{
if (master == BezierTangentDirection.In)
tangentOut = position + (tangentOut - position).normalized * (tangentIn - position).magnitude;
else
tangentIn = position + (tangentIn - position).normalized * (tangentOut - position).magnitude;
}
else if (mode == BezierTangentMode.Mirrored)
{
if (master == BezierTangentDirection.In)
tangentOut = position - (tangentIn - position);
else
tangentIn = position - (tangentOut - position);
}
}
///
/// Set the position while also moving tangent points.
///
///
public void SetPosition(Vector3 position)
{
Vector3 delta = position - this.position;
this.position = position;
this.tangentIn += delta;
this.tangentOut += delta;
}
public void SetTangentIn(Vector3 tangent, BezierTangentMode mode)
{
this.tangentIn = tangent;
EnforceTangentMode(BezierTangentDirection.In, mode);
}
public void SetTangentOut(Vector3 tangent, BezierTangentMode mode)
{
this.tangentOut = tangent;
EnforceTangentMode(BezierTangentDirection.Out, mode);
}
public static Vector3 QuadraticPosition(BezierPoint a, BezierPoint b, float t)
{
float x = (1f - t) * (1f - t) * a.position.x + 2f * (1f - t) * t * a.tangentOut.x + t * t * b.position.x;
float y = (1f - t) * (1f - t) * a.position.y + 2f * (1f - t) * t * a.tangentOut.y + t * t * b.position.y;
float z = (1f - t) * (1f - t) * a.position.z + 2f * (1f - t) * t * a.tangentOut.z + t * t * b.position.z;
return new Vector3(x, y, z);
}
public static Vector3 CubicPosition(BezierPoint a, BezierPoint b, float t)
{
t = Mathf.Clamp01(t);
float oneMinusT = 1f - t;
return oneMinusT * oneMinusT * oneMinusT * a.position +
3f * oneMinusT * oneMinusT * t * a.tangentOut +
3f * oneMinusT * t * t * b.tangentIn +
t * t * t * b.position;
}
public static Vector3 GetLookDirection(IList points, int index, int previous, int next)
{
if (previous < 0)
{
return (points[index].position - QuadraticPosition(points[index], points[next], .1f)).normalized;
}
else if (next < 0)
{
return (QuadraticPosition(points[index], points[previous], .1f) - points[index].position).normalized;
}
else if (next > -1 && previous > -1)
{
Vector3 a = (QuadraticPosition(points[index], points[previous], .1f) - points[index].position).normalized;
Vector3 b = (QuadraticPosition(points[index], points[next], .1f) - points[index].position).normalized;
return ((a + b) * .5f).normalized;
}
else
{
return Vector3.forward;
}
}
}
}