コード例 #1
0
        //Divide the curve into equal steps
        public void DivideSegmentIntoSteps(BezierSegment seg)
        {
            //Find the total length of the curve
            float totalLength = SS_Common.GetLengthSimpsons(0f, 1f, seg);

            //How many sections do we want to divide the curve into
            int parts = numSteps;

            //reset the curve steps Array                                               <======= EDIT MIO
            segmentSteps.Clear();
            segmentSteps.Add(transform.TransformPoint(seg.A));


            //What's the length of one section?
            float sectionLength = totalLength / (float)parts;

            //Init the variables we need in the loop
            float currentDistance = 0f + sectionLength;

            //The curve's start position
            Vector3 lastPos = seg.A;

            for (int i = 1; i <= parts; i++)
            {
                //Use Newton–Raphsons method to find the t value from the start of the curve
                //to the end of the distance we have
                float t = SS_Common.FindTValue(currentDistance, totalLength, seg);

                //Get the coordinate on the Bezier curve at this t value
                Vector3 pos = SS_Common.DeCasteljausAlgorithm(t, seg);


                //Save the last position
                lastPos = pos;

                //Add current pos to vector list                                                        <======= EDIT MIO
                segmentSteps.Add(transform.TransformPoint(pos));

                //Add to the distance traveled on the line so far
                currentDistance += sectionLength;
            }
        }
コード例 #2
0
        /// <summary>
        /// Gets the sum of all individuals segments in this curve
        /// </summary>
        /// <returns></returns>
        public static float GetCurveLength(ShapeElement element, Transform theT)
        {
            float TotalLenghtSum = 0;

            //Draw Each Element

            for (int i = 0; i < element.knots.Length - 1; i++)
            {
                //CREATE A BEZIER SEGMENT
                BezierSegment seg = new BezierSegment();
                seg.A = element.knots[i].KWorldPos(theT);              //START POINT
                seg.B = element.knots[i].KHandleOutWorldPos(theT);     //START TANGENT
                seg.C = element.knots[i + 1].KHandleInWorldPos(theT);  //END TANGENT
                seg.D = element.knots[i + 1].KWorldPos(theT);          //END POINT

                float totalLength = GetLengthSimpsons(0f, 1f, seg);
                TotalLenghtSum = TotalLenghtSum + totalLength;
            }

            return(TotalLenghtSum);
        }
コード例 #3
0
        //The De Casteljau's Algorithm
        public static Vector3 DeCasteljausAlgorithm(float t, BezierSegment seg)
        {
            //Linear interpolation = lerp = (1 - t) * A + t * B
            //Could use Vector3.Lerp(A, B, t)

            //To make it faster
            float oneMinusT = 1f - t;

            //Layer 1
            Vector3 Q = oneMinusT * seg.A + t * seg.B;
            Vector3 R = oneMinusT * seg.B + t * seg.C;
            Vector3 S = oneMinusT * seg.C + t * seg.D;

            //Layer 2
            Vector3 P = oneMinusT * Q + t * R;
            Vector3 T = oneMinusT * R + t * S;

            //Final interpolated position
            Vector3 U = oneMinusT * P + t * T;

            return(U);
        }
コード例 #4
0
        //Use Newton–Raphsons method to find the t value at the end of this distance d
        public static float FindTValue(float d, float totalLength, BezierSegment seg)
        {
            //Need a start value to make the method start
            //Should obviously be between 0 and 1
            //We can say that a good starting point is the percentage of distance traveled
            //If this start value is not working you can use the Bisection Method to find a start value
            //https://en.wikipedia.org/wiki/Bisection_method
            float t = d / totalLength;

            //Need an error so we know when to stop the iteration
            float error = 0.001f;

            //We also need to avoid infinite loops
            int iterations = 0;

            while (true)
            {
                //Newton's method
                float tNext = t - ((GetLengthSimpsons(0f, t, seg) - d) / GetArcLengthIntegrand(t, seg));

                //Have we reached the desired accuracy?
                if (Mathf.Abs(tNext - t) < error)
                {
                    break;
                }

                t = tNext;

                iterations += 1;

                if (iterations > 1000)
                {
                    break;
                }
            }

            return(t);
        }
コード例 #5
0
        //Get the length of the curve between two t values with Simpson's rule
        public static float GetLengthSimpsons(float tStart, float tEnd, BezierSegment seg)
        {
            //This is the resolution and has to be even
            int n = 20;

            //Now we need to divide the curve into sections
            float delta = (tEnd - tStart) / (float)n;

            //The main loop to calculate the length

            //Everything multiplied by 1
            float endPoints = GetArcLengthIntegrand(tStart, seg) + GetArcLengthIntegrand(tEnd, seg);

            //Everything multiplied by 4
            float x4 = 0f;

            for (int i = 1; i < n; i += 2)
            {
                float t = tStart + delta * i;

                x4 += GetArcLengthIntegrand(t, seg);
            }

            //Everything multiplied by 2
            float x2 = 0f;

            for (int i = 2; i < n; i += 2)
            {
                float t = tStart + delta * i;

                x2 += GetArcLengthIntegrand(t, seg);
            }

            //The final length
            float length = (delta / 3f) * (endPoints + 4f * x4 + 2f * x2);

            return(length);
        }
コード例 #6
0
        //Divide the curve into equal steps
        public static List <Vector3> ResampleCurve(int numSteps, ShapeElement element, Transform theT)
        {
            float totalLenght   = GetCurveLength(element, theT);
            float sectionLength = totalLenght / numSteps;


            List <Vector3> curveSteps = new List <Vector3>();


            /*
             *      20          8          35                 17                -segmentLenghts     N
             *
             * X -------------X--------X-------------------X-----------X          -theSegs            N
             *
             * 0              20      28                   63          80         -knotDistances      N+1
             *
             */

            //Create A list of Bezier Segment
            List <BezierSegment> theSegs = new List <BezierSegment>();
            //Create A list of Bezier Segment Lengths
            List <float> segmentLenghts = new List <float>();


            for (int i = 0; i < element.knots.Length - 1; i++)
            {
                //CREATE A BEZIER SEGMENT
                BezierSegment seg = new BezierSegment();
                seg.A = element.knots[i].KWorldPos(theT);              //START POINT
                seg.B = element.knots[i].KHandleOutWorldPos(theT);     //START TANGENT
                seg.C = element.knots[i + 1].KHandleInWorldPos(theT);  //END TANGENT
                seg.D = element.knots[i + 1].KWorldPos(theT);          //END POINT

                theSegs.Add(seg);

                segmentLenghts.Add(GetLengthSimpsons(0f, 1f, seg));
            }


            //Create a list of knot Distances
            List <float> knotDistances = new List <float>();
            float        tempDist      = 0;

            knotDistances.Add(tempDist);
            for (int i = 0; i < segmentLenghts.Count; i++)
            {
                tempDist = tempDist + segmentLenghts[i];
                knotDistances.Add(tempDist);
            }

            //Add the first point
            curveSteps.Clear();
            curveSteps.Add(theSegs[0].A);

            //For each step
            for (int i = 1; i < numSteps; i++)
            {
                //Get this point dist
                float distAlong = sectionLength * i;

                //Find out in wich segment it falls
                int currSegIndex = 0;
                for (int f = 0; f < knotDistances.Count - 1; f++)
                {
                    if (distAlong > knotDistances[f])
                    {
                        if (distAlong < knotDistances[f + 1])
                        {
                            currSegIndex = f;
                        }
                    }
                }

                //Find out at which distance along that segment the point falls
                float segPointDist = distAlong - knotDistances[currSegIndex];

                //Use Newton–Raphsons method to find the t value from the start of the curve
                //to the end of the distance we have
                float t = FindTValue(segPointDist, segmentLenghts[currSegIndex], theSegs[currSegIndex]);

                //Get the coordinate on the Bezier curve at this t value
                Vector3 pos = DeCasteljausAlgorithm(t, theSegs[currSegIndex]);

                //Add the next point to the curveSteps list
                curveSteps.Add(pos);
            }
            return(curveSteps);
        }
コード例 #7
0
        ////////////////////////////////////////
        /// DRAWING UI
        /// DRAWING UI
        /// DRAWING UI
        ////////////////////////////////////////

        ////////////////////////////////////////
        /// BEZIER CURVE DRAWING METHODS
        /// BEZIER CURVE DRAWING METHODS
        ////////////////////////////////////////

        void DrawBezierSegment(BezierSegment seg)
        {
            UnityEditor.Handles.DrawBezier(seg.A, seg.D, seg.B, seg.C, curveColor, null, 1);
        }