/// <summary> /// Gets the tangents. /// </summary> /// <param name="inTangent">In tangent.</param> /// <param name="outTangent">Out tangent.</param> /// <param name="previousPoint">Previous point.</param> /// <param name="point">Point.</param> /// <param name="nextPoint">Next point.</param> public static void GetTangents(out Vector3 inTangent, out Vector3 outTangent, IBezierPoint previousPoint, IBezierPoint point, IBezierPoint nextPoint) { switch (point.tangentMode) { case TangentMode.Smooth: inTangent = point.inTangent; outTangent = point.inTangent * -1.0f; break; case TangentMode.Corner: inTangent = point.inTangent; outTangent = point.outTangent; break; case TangentMode.Symmetric: GetSymmetricTangents(out inTangent, out outTangent, previousPoint, point, nextPoint); break; case TangentMode.Auto: GetAutoTangents(out inTangent, out outTangent, previousPoint, point, nextPoint); break; default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// Gets the out tangent. /// </summary> /// <returns>The out tangent.</returns> /// <param name="previousPoint">Previous point.</param> /// <param name="point">Point.</param> /// <param name="nextPoint">Next point.</param> public static Vector3 GetOutTangent(IBezierPoint previousPoint, IBezierPoint point, IBezierPoint nextPoint) { Vector3 inTangent; Vector3 outTangent; GetTangents(out inTangent, out outTangent, previousPoint, point, nextPoint); return(outTangent); }
/// <summary> /// Using the curve between pointA and pointB we take a discrete number of line segments /// and return all of the points that make those lines. /// </summary> /// <returns>The segment points.</returns> /// <param name="output">Output.</param> /// <param name="pointA">Point a.</param> /// <param name="pointB">Point b.</param> /// <param name="pointC">Point c.</param> /// <param name="pointD">Point d.</param> public static void GetSegmentPoints(ref Vector3[] output, IBezierPoint pointA, IBezierPoint pointB, IBezierPoint pointC, IBezierPoint pointD) { Array.Resize(ref s_SegmentPointDeltas, LENGTH_LINE_SEGMENTS + 1); for (int index = 0; index < LENGTH_LINE_SEGMENTS + 1; index++) { s_SegmentPointDeltas[index] = DELTA_LINE_SEGMENTS * index; } Interpolate(ref output, pointA, pointB, pointC, pointD, s_SegmentPointDeltas); }
/// <summary> /// Draws the handle for a bezier points tangents. /// </summary> /// <param name="pointA">Point a.</param> /// <param name="pointB">Point b.</param> /// <param name="pointC">Point c.</param> public static void BezierPointTangentsHandle(IBezierPoint pointA, IBezierPoint pointB, IBezierPoint pointC) { if (pointA != null) { Vector3 inTangent = BezierPath.GetInTangent(pointA, pointB, pointC); pointB.inTangent = TangentHandle(pointB.position, inTangent); } if (pointC != null) { Vector3 outTangent = BezierPath.GetOutTangent(pointA, pointB, pointC); pointB.outTangent = TangentHandle(pointB.position, outTangent); } }
/// <summary> /// Returns the positions on the curve between the two points at the given deltas. /// /// This method is faster than calling Interpolate multiple times for the same patch. /// </summary> /// <returns>The interpolated positions.</returns> /// <param name="output">Output.</param> /// <param name="pointA">Point a.</param> /// <param name="pointB">Point b.</param> /// <param name="pointC">Point c.</param> /// <param name="pointD">Point d.</param> /// <param name="deltas">Deltas.</param> public static void Interpolate(ref Vector3[] output, IBezierPoint pointA, IBezierPoint pointB, IBezierPoint pointC, IBezierPoint pointD, float[] deltas) { Array.Resize(ref output, deltas.Length); Vector3 outTangent = GetOutTangent(pointA, pointB, pointC); Vector3 inTangent = GetInTangent(pointB, pointC, pointD); for (int index = 0; index < deltas.Length; index++) { float delta = deltas[index]; float x = ComputeBezier(pointB.position.x, outTangent.x, inTangent.x, pointC.position.x, delta); float y = ComputeBezier(pointB.position.y, outTangent.y, inTangent.y, pointC.position.y, delta); float z = ComputeBezier(pointB.position.z, outTangent.z, inTangent.z, pointC.position.z, delta); output[index] = new Vector3(x, y, z); } }
/// <summary> /// Draws the bezier segment between pointB and pointC. /// </summary> /// <param name="pointA">Point a.</param> /// <param name="pointB">Point b.</param> /// <param name="pointC">Point c.</param> /// <param name="pointD">Point d.</param> public static void BezierSegmentHandle(IBezierPoint pointA, IBezierPoint pointB, IBezierPoint pointC, IBezierPoint pointD) { if (Event.current.type != EventType.Repaint) { return; } BezierPath.GetSegmentPoints(ref s_BezierPoints, pointA, pointB, pointC, pointD); HandleUtils.BeginGL(GL.LINES, HandleUtils.handleWireMaterial); for (int index = 0; index < s_BezierPoints.Length - 1; index++) { GL.Vertex(s_BezierPoints[index]); GL.Vertex(s_BezierPoints[index + 1]); } HandleUtils.EndGL(); }
/// <summary> /// Draws the handles. /// </summary> public static void DrawHandles(SerializedProperty prop) { FindProperties(prop); for (int index = 0; index < s_PointsProp.arraySize; index++) { // Get all of the points to draw the patch IBezierPoint pointA = GetPoint(ref s_PointA, index - 1); IBezierPoint pointB = GetPoint(ref s_PointB, index); IBezierPoint pointC = GetPoint(ref s_PointC, index + 1); IBezierPoint pointD = GetPoint(ref s_PointD, index + 2); BezierPointHandle(pointB); if (pointC != null) { BezierSegmentHandle(pointA, pointB, pointC, pointD); } switch (pointB.tangentMode) { case TangentMode.Corner: BezierPointTangentsHandle(pointA, pointB, pointC); break; case TangentMode.Smooth: BezierPointTangentsHandle(pointA, pointB, pointC); break; case TangentMode.Auto: break; case TangentMode.Symmetric: break; default: throw new ArgumentOutOfRangeException(); } } }
/// <summary> /// Gets the symmetric tangents. /// </summary> /// <param name="inTangent">In tangent.</param> /// <param name="outTangent">Out tangent.</param> /// <param name="previousPoint">Previous point.</param> /// <param name="point">Point.</param> /// <param name="nextPoint">Next point.</param> private static void GetSymmetricTangents(out Vector3 inTangent, out Vector3 outTangent, IBezierPoint previousPoint, IBezierPoint point, IBezierPoint nextPoint) { Vector3 previousToNext; Vector3 thisToPrevious = Vector3.zero; Vector3 thisToNext = Vector3.zero; if (previousPoint != null) { thisToPrevious = previousPoint.position - point.position; } if (nextPoint != null) { thisToNext = nextPoint.position - point.position; } if (previousPoint == null) { previousToNext = thisToNext; } else if (nextPoint == null) { previousToNext = thisToPrevious; } else { previousToNext = nextPoint.position - previousPoint.position; } float inTangentMagnitude = thisToPrevious.magnitude / 3.0f; float outTangentMagnitude = thisToNext.magnitude / 3.0f; float averageMagnitude = (inTangentMagnitude + outTangentMagnitude) / 2.0f; inTangent = -1.0f * averageMagnitude * previousToNext.normalized; outTangent = averageMagnitude * previousToNext.normalized; }
/// <summary> /// Gets the out tangent. /// </summary> /// <returns>The out tangent.</returns> /// <param name="previousPoint">Previous point.</param> /// <param name="point">Point.</param> /// <param name="nextPoint">Next point.</param> public static Vector3 GetOutTangent(IBezierPoint previousPoint, IBezierPoint point, IBezierPoint nextPoint) { Vector3 inTangent; Vector3 outTangent; GetTangents(out inTangent, out outTangent, previousPoint, point, nextPoint); return outTangent; }
/// <summary> /// Draws the handle for a bezier points tangents. /// </summary> /// <param name="pointA">Point a.</param> /// <param name="pointB">Point b.</param> /// <param name="pointC">Point c.</param> public static void BezierPointTangentsHandle(IBezierPoint pointA, IBezierPoint pointB, IBezierPoint pointC) { if (pointA != null) { Vector3 inTangent = BezierPath.GetInTangent(pointA, pointB, pointC); pointB.inTangent = TangentHandle(pointB.position, inTangent); } if (pointC != null) { Vector3 outTangent = BezierPath.GetOutTangent(pointA, pointB, pointC); pointB.outTangent = TangentHandle(pointB.position, outTangent); } }
/// <summary> /// Returns the positions on the curve between the two points at the given deltas. /// /// This method is faster than calling Interpolate multiple times for the same patch. /// </summary> /// <returns>The interpolated positions.</returns> /// <param name="output">Output.</param> /// <param name="pointA">Point a.</param> /// <param name="pointB">Point b.</param> /// <param name="pointC">Point c.</param> /// <param name="pointD">Point d.</param> /// <param name="deltas">Deltas.</param> public static void Interpolate(ref Vector3[] output, IBezierPoint pointA, IBezierPoint pointB, IBezierPoint pointC, IBezierPoint pointD, float[] deltas) { Array.Resize(ref output, deltas.Length); Vector3 outTangent = GetOutTangent(pointA, pointB, pointC); Vector3 inTangent = GetInTangent(pointB, pointC, pointD); for (int index = 0; index < deltas.Length; index++) { float delta = deltas[index]; float x = ComputeBezier(pointB.position.x, outTangent.x, inTangent.x, pointC.position.x, delta); float y = ComputeBezier(pointB.position.y, outTangent.y, inTangent.y, pointC.position.y, delta); float z = ComputeBezier(pointB.position.z, outTangent.z, inTangent.z, pointC.position.z, delta); output[index] = new Vector3(x, y, z); } }
/// <summary> /// Draws the handle for a bezier point. /// </summary> /// <param name="point">Point.</param> public static void BezierPointHandle(IBezierPoint point) { float pointSize = HandleUtils.GetDotSize(point.position); point.position = Handles.FreeMoveHandle(point.position, Quaternion.identity, pointSize, Vector3.zero, Handles.DotCap); }
/// <summary> /// Using the curve between pointA and pointB we take a discrete number of line segments /// and return all of the points that make those lines. /// </summary> /// <returns>The segment points.</returns> /// <param name="output">Output.</param> /// <param name="pointA">Point a.</param> /// <param name="pointB">Point b.</param> /// <param name="pointC">Point c.</param> /// <param name="pointD">Point d.</param> public static void GetSegmentPoints(ref Vector3[] output, IBezierPoint pointA, IBezierPoint pointB, IBezierPoint pointC, IBezierPoint pointD) { Array.Resize(ref s_SegmentPointDeltas, LENGTH_LINE_SEGMENTS + 1); for (int index = 0; index < LENGTH_LINE_SEGMENTS + 1; index++) s_SegmentPointDeltas[index] = DELTA_LINE_SEGMENTS * index; Interpolate(ref output, pointA, pointB, pointC, pointD, s_SegmentPointDeltas); }
/// <summary> /// Gets the auto tangents. /// </summary> /// <param name="inTangent">In tangent.</param> /// <param name="outTangent">Out tangent.</param> /// <param name="previousPoint">Previous point.</param> /// <param name="point">Point.</param> /// <param name="nextPoint">Next point.</param> private static void GetAutoTangents(out Vector3 inTangent, out Vector3 outTangent, IBezierPoint previousPoint, IBezierPoint point, IBezierPoint nextPoint) { Vector3 previousToNext; Vector3 thisToPrevious = Vector3.zero; Vector3 thisToNext = Vector3.zero; if (previousPoint != null) thisToPrevious = previousPoint.position - point.position; if (nextPoint != null) thisToNext = nextPoint.position - point.position; if (previousPoint == null) previousToNext = thisToNext; else if (nextPoint == null) previousToNext = thisToPrevious; else previousToNext = nextPoint.position - previousPoint.position; float inTangentMagnitude = thisToPrevious.magnitude / 3.0f; float outTangentMagnitude = thisToNext.magnitude / 3.0f; inTangent = -1.0f * inTangentMagnitude * previousToNext.normalized; outTangent = outTangentMagnitude * previousToNext.normalized; }
/// <summary> /// Gets the tangents. /// </summary> /// <param name="inTangent">In tangent.</param> /// <param name="outTangent">Out tangent.</param> /// <param name="previousPoint">Previous point.</param> /// <param name="point">Point.</param> /// <param name="nextPoint">Next point.</param> public static void GetTangents(out Vector3 inTangent, out Vector3 outTangent, IBezierPoint previousPoint, IBezierPoint point, IBezierPoint nextPoint) { switch (point.tangentMode) { case TangentMode.Smooth: inTangent = point.inTangent; outTangent = point.inTangent * -1.0f; break; case TangentMode.Corner: inTangent = point.inTangent; outTangent = point.outTangent; break; case TangentMode.Symmetric: GetSymmetricTangents(out inTangent, out outTangent, previousPoint, point, nextPoint); break; case TangentMode.Auto: GetAutoTangents(out inTangent, out outTangent, previousPoint, point, nextPoint); break; default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// Draws the bezier segment between pointB and pointC. /// </summary> /// <param name="pointA">Point a.</param> /// <param name="pointB">Point b.</param> /// <param name="pointC">Point c.</param> /// <param name="pointD">Point d.</param> public static void BezierSegmentHandle(IBezierPoint pointA, IBezierPoint pointB, IBezierPoint pointC, IBezierPoint pointD) { if (Event.current.type != EventType.Repaint) return; BezierPath.GetSegmentPoints(ref s_BezierPoints, pointA, pointB, pointC, pointD); HandleUtils.BeginGL(GL.LINES, HandleUtils.handleWireMaterial); for (int index = 0; index < s_BezierPoints.Length - 1; index++) { GL.Vertex(s_BezierPoints[index]); GL.Vertex(s_BezierPoints[index + 1]); } HandleUtils.EndGL(); }
/// <summary> /// Draws the handle for a bezier point. /// </summary> /// <param name="point">Point.</param> public static void BezierPointHandle(IBezierPoint point) { float pointSize = HandleUtils.GetDotSize(point.position); point.position = Handles.FreeMoveHandle(point.position, Quaternion.identity, pointSize, Vector3.zero, Handles.DotCap); }