/// <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));
            }
        }
Exemple #3
0
        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();
        }