/// <summary> /// Inserts a new <see cref="Knot"/> at the <paramref name="index"/> position in the collection. /// </summary> /// <param name="index"></param> /// <param name="knot"></param> public void InsertKnot(int index, Knot knot) { Bezier3DCurve curve; if (index == 0) { curve = new Bezier3DCurve( knot.position, knot.handleOut, -_curves[0].FirstHandle, _curves[0].StartPoint, InterpolationStepsPerCurve); } else if (index == CurveCount) { curve = GetCurve(index - 1); } else { curve = GetCurve(index); } var curveList = new List <Bezier3DCurve>(_curves); curveList.Insert(index, curve); _curves = curveList.ToArray(); _autoKnotsCache.Insert(index, knot.auto); _knotRotations.Insert(index, knot.rotation); SetKnot(index, knot); }
/// <summary> /// Removes the <see cref="Knot"/> at the <paramref name="index"/> position in the collection. /// </summary> /// <param name="index"></param> public void RemoveKnot(int index) { if (index == 0) { var knot = GetKnot(1); var curveList = new List <Bezier3DCurve>(_curves); curveList.RemoveAt(0); _curves = curveList.ToArray(); _autoKnotsCache.RemoveAt(0); _knotRotations.RemoveAt(0); SetKnot(0, knot); } else if (index == CurveCount) { var curveList = new List <Bezier3DCurve>(_curves); curveList.RemoveAt(index - 1); _curves = curveList.ToArray(); _autoKnotsCache.RemoveAt(index); _knotRotations.RemoveAt(index); if (Math.Abs(_autoKnotsCache[KnotCount - 1]) > 0.00001f) { SetKnot(KnotCount - 1, GetKnot(KnotCount - 1)); } } else { int preCurveIndex, postCurveIndex; GetCurveIndicesForKnot(index, out preCurveIndex, out postCurveIndex); var curve = new Bezier3DCurve( _curves[preCurveIndex].StartPoint, _curves[preCurveIndex].FirstHandle, _curves[postCurveIndex].SecondHandle, _curves[postCurveIndex].EndPoint, InterpolationStepsPerCurve); _curves[preCurveIndex] = curve; var curveList = new List <Bezier3DCurve>(_curves); curveList.RemoveAt(postCurveIndex); _curves = curveList.ToArray(); _autoKnotsCache.RemoveAt(index); _knotRotations.RemoveAt(index); int preKnotIndex, postKnotIndex; GetKnotIndicesForKnot(index, out preKnotIndex, out postKnotIndex); SetKnot(preKnotIndex, GetKnot(preKnotIndex)); } }
public static void DrawCurveLinesGizmos(IBezier3DSplineData splineData, Transform transform = null) { Gizmos.color = Color.white; //Loop through each curve in spline var segments = splineData.InterpolationStepsPerCurve; var spacing = 1f / segments; for (var i = 0; i < splineData.CurveCount; i++) { var curve = splineData.GetCurve(i); //Get curve in world space Vector3 a, b, c, d; if (transform != null) { a = transform.TransformPoint(curve.StartPoint); b = transform.TransformPoint(curve.FirstHandle + curve.StartPoint); c = transform.TransformPoint(curve.SecondHandle + curve.EndPoint); d = transform.TransformPoint(curve.EndPoint); } else { a = curve.StartPoint; b = curve.FirstHandle + curve.StartPoint; c = curve.SecondHandle + curve.EndPoint; d = curve.EndPoint; } var prev = Bezier3DCurve.GetPoint( a, b, c, d, 0f); for (var k = 0; k <= segments; k++) { var cur = Bezier3DCurve.GetPoint( a, b, c, d, k * spacing); Gizmos.DrawLine(prev, cur); prev = cur; } } }
/// <summary> /// Recache all individual curves with new interpolation step count. /// </summary> /// <param name = "stepCount"> Number of steps per curve to cache position and rotation. </param> public void SetStepsPerCurve(int stepCount) { _interpolationStepsPerCurve = stepCount; for (var i = 0; i < CurveCount; i++) { _curves[i] = new Bezier3DCurve( _curves[i].StartPoint, _curves[i].FirstHandle, _curves[i].SecondHandle, _curves[i].EndPoint, _interpolationStepsPerCurve); } _totalLength = GetTotalLength(); }
/// <summary> /// Flip the spline direction. /// </summary> public void Flip() { var curves = new Bezier3DCurve[CurveCount]; for (var i = 0; i < CurveCount; i++) { curves[CurveCount - 1 - i] = new Bezier3DCurve( _curves[i].EndPoint, _curves[i].SecondHandle, _curves[i].FirstHandle, _curves[i].StartPoint, InterpolationStepsPerCurve); } _curves = curves; _autoKnotsCache.Reverse(); _knotRotations.Reverse(); }
/// <summary> /// Adds a new <see cref="Knot"/> <paramref name="knot"/> to the end of the spline. /// </summary> /// <param name="knot"></param> public void AddKnot(Knot knot) { var curve = new Bezier3DCurve( _curves[CurveCount - 1].EndPoint, -_curves[CurveCount - 1].SecondHandle, knot.handleIn, knot.position, InterpolationStepsPerCurve); var curveList = new List <Bezier3DCurve>(_curves); curveList.Add(curve); _curves = curveList.ToArray(); _autoKnotsCache.Add(knot.auto); _knotRotations.Add(knot.rotation); SetKnot(KnotCount - 1, knot); }
/// <summary> /// Set <see cref="Knot"/> <paramref name="knot"/> info in local coordinates at the <paramref name="index"/> /// position in the collection. /// </summary> public void SetKnot(int index, Knot knot) { //If knot is set to auto, adjust handles accordingly _knotRotations[index] = knot.rotation; _autoKnotsCache[index] = knot.auto; if (knot.IsUsingAutoHandles) { PositionAutoHandles(index, ref knot); } //Automate knots around this knot int preKnotIndex, postKnotIndex; GetKnotIndicesForKnot(index, out preKnotIndex, out postKnotIndex); var preKnot = new Knot(); if (preKnotIndex != -1) { preKnot = GetKnot(preKnotIndex); if (preKnot.IsUsingAutoHandles) { int preKnotPreCurveIndex, preKnotPostCurveIndex; GetCurveIndicesForKnot(preKnotIndex, out preKnotPreCurveIndex, out preKnotPostCurveIndex); if (preKnotPreCurveIndex != -1) { PositionAutoHandles( preKnotIndex, ref preKnot, _curves[preKnotPreCurveIndex].StartPoint, knot.position); _curves[preKnotPreCurveIndex] = new Bezier3DCurve( _curves[preKnotPreCurveIndex].StartPoint, _curves[preKnotPreCurveIndex].FirstHandle, preKnot.handleIn, preKnot.position, InterpolationStepsPerCurve); } else { PositionAutoHandles( preKnotIndex, ref preKnot, Vector3.zero, knot.position); } } } var postKnot = new Knot(); if (postKnotIndex != -1) { postKnot = GetKnot(postKnotIndex); if (postKnot.IsUsingAutoHandles) { int postKnotPreCurveIndex, postKnotPostCurveIndex; GetCurveIndicesForKnot(postKnotIndex, out postKnotPreCurveIndex, out postKnotPostCurveIndex); if (postKnotPostCurveIndex != -1) { PositionAutoHandles( postKnotIndex, ref postKnot, knot.position, _curves[postKnotPostCurveIndex].EndPoint); _curves[postKnotPostCurveIndex] = new Bezier3DCurve( postKnot.position, postKnot.handleOut, _curves[postKnotPostCurveIndex].SecondHandle, _curves[postKnotPostCurveIndex].EndPoint, InterpolationStepsPerCurve); } else { PositionAutoHandles( postKnotIndex, ref postKnot, knot.position, Vector3.zero); } } } //Get the curve indices in direct contact with knot int preCurveIndex, postCurveIndex; GetCurveIndicesForKnot(index, out preCurveIndex, out postCurveIndex); //Adjust curves in direct contact with the knot if (preCurveIndex != -1) { _curves[preCurveIndex] = new Bezier3DCurve( preKnot.position, preKnot.handleOut, knot.handleIn, knot.position, InterpolationStepsPerCurve); } if (postCurveIndex != -1) { _curves[postCurveIndex] = new Bezier3DCurve( knot.position, knot.handleOut, postKnot.handleIn, postKnot.position, InterpolationStepsPerCurve); } _totalLength = GetTotalLength(); }