Пример #1
0
        public static PathSplitData SplitBezierPathEvenly(BezierPath bezierPath, float spacing, float accuracy)
        {
            PathSplitData splitData = new PathSplitData();

            splitData.vertices.Add(bezierPath.GetPoint(0));
            splitData.tangents.Add(CubicBezierUtility.EvaluateCurveDerivative(bezierPath.GetPointsInSegment(0), 0).normalized);
            splitData.cumulativeLength.Add(0);
            splitData.anchorVertexMap.Add(0);
            splitData.minMax.AddValue(bezierPath.GetPoint(0));

            Vector3 prevPointOnPath = bezierPath.GetPoint(0);
            Vector3 lastAddedPoint  = bezierPath.GetPoint(0);

            float currentPathLength  = 0;
            float dstSinceLastVertex = 0;

            // Go through all segments and split up into vertices
            for (int segmentIndex = 0; segmentIndex < bezierPath.NumSegments; segmentIndex++)
            {
                Vector3[] segmentPoints          = bezierPath.GetPointsInSegment(segmentIndex);
                float     estimatedSegmentLength = CubicBezierUtility.EstimateCurveLength(segmentPoints[0], segmentPoints[1], segmentPoints[2], segmentPoints[3]);
                int       divisions = Mathf.CeilToInt(estimatedSegmentLength * accuracy);
                float     increment = 1f / divisions;

                for (float t = increment; t <= 1; t += increment)
                {
                    bool isLastPointOnPath = (t + increment > 1 && segmentIndex == bezierPath.NumSegments - 1);
                    if (isLastPointOnPath)
                    {
                        t = 1;
                    }
                    Vector3 pointOnPath = CubicBezierUtility.EvaluateCurve(segmentPoints, t);
                    dstSinceLastVertex += (pointOnPath - prevPointOnPath).magnitude;

                    // If vertices are now too far apart, go back by amount we overshot by
                    if (dstSinceLastVertex > spacing)
                    {
                        float overshootDst = dstSinceLastVertex - spacing;
                        pointOnPath += (prevPointOnPath - pointOnPath).normalized * overshootDst;
                        t           -= increment;
                    }

                    if (dstSinceLastVertex >= spacing || isLastPointOnPath)
                    {
                        currentPathLength += (lastAddedPoint - pointOnPath).magnitude;
                        splitData.cumulativeLength.Add(currentPathLength);
                        splitData.vertices.Add(pointOnPath);
                        splitData.tangents.Add(CubicBezierUtility.EvaluateCurveDerivative(segmentPoints, t).normalized);
                        splitData.minMax.AddValue(pointOnPath);
                        dstSinceLastVertex = 0;
                        lastAddedPoint     = pointOnPath;
                    }
                    prevPointOnPath = pointOnPath;
                }
                splitData.anchorVertexMap.Add(splitData.vertices.Count - 1);
            }
            return(splitData);
        }
Пример #2
0
        public static Bounds CalculateSegmentBounds(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
        {
            MinMax3D minMax = new MinMax3D();

            minMax.AddValue(p0);
            minMax.AddValue(p3);

            List <float> extremePointTimes = ExtremePointTimes(p0, p1, p2, p3);

            foreach (float t in extremePointTimes)
            {
                minMax.AddValue(CubicBezierUtility.EvaluateCurve(p0, p1, p2, p3, t));
            }

            return(new Bounds((minMax.Min + minMax.Max) / 2, minMax.Max - minMax.Min));
        }
        public static Bounds CalculateBounds(Vector3[] points)
        {
            MinMax3D minMax = new MinMax3D();

            minMax.AddValue(points[0]);
            minMax.AddValue(points[3]);

            List <float> extremePointTimes = ExtremePointTimes(points[0], points[1], points[2], points[3]);

            foreach (float t in extremePointTimes)
            {
                minMax.AddValue(CubicBezierUtility.EvaluateCurve(points, t));
            }

            return(new Bounds((minMax.Min + minMax.Max) / 2, minMax.Max - minMax.Min));
        }
Пример #4
0
        public static Bounds CalculateBounds(Vector3[] points)
        {
            Debug.Assert(points.Length == 4, "Incorrect number of points supplied to cubic bezier function (expected 4)");
            MinMax3D minMax = new MinMax3D();

            if (points.Length >= 4)
            {
                minMax.AddValue(points[0]);
                minMax.AddValue(points[3]);

                List <float> extremePointTimes = ExtremePointTimes(points[0], points[1], points[2], points[3]);
                foreach (float t in extremePointTimes)
                {
                    minMax.AddValue(CubicBezierUtility.EvaluateCurve(points, t));
                }
            }

            return(new Bounds((minMax.Min + minMax.Max) / 2, minMax.Max - minMax.Min));
        }
Пример #5
0
        public static PathSplitData SplitBezierPathByAngleError(BezierPath bezierPath, float maxAngleError, float minVertexDst, float accuracy)
        {
            PathSplitData splitData = new PathSplitData();

            splitData.vertices.Add(bezierPath.GetPoint(0));
            splitData.tangents.Add(CubicBezierUtility.EvaluateCurveDerivative(bezierPath.GetPointsInSegment(0), 0).normalized);
            splitData.cumulativeLength.Add(0);
            splitData.anchorVertexMap.Add(0);
            splitData.minMax.AddValue(bezierPath.GetPoint(0));

            Vector3 prevPointOnPath = bezierPath.GetPoint(0);
            Vector3 lastAddedPoint  = bezierPath.GetPoint(0);

            float currentPathLength  = 0;
            float dstSinceLastVertex = 0;

            // Go through all segments and split up into vertices
            for (int segmentIndex = 0; segmentIndex < bezierPath.NumSegments; segmentIndex++)
            {
                Vector3[] segmentPoints          = bezierPath.GetPointsInSegment(segmentIndex);
                float     estimatedSegmentLength = CubicBezierUtility.EstimateCurveLength(segmentPoints[0], segmentPoints[1], segmentPoints[2], segmentPoints[3]);
                int       divisions = Mathf.CeilToInt(estimatedSegmentLength * accuracy);
                float     increment = 1f / divisions;

                for (float t = increment; t <= 1; t += increment)
                {
                    bool isLastPointOnPath = (t + increment > 1 && segmentIndex == bezierPath.NumSegments - 1);
                    if (isLastPointOnPath)
                    {
                        t = 1;
                    }
                    Vector3 pointOnPath     = CubicBezierUtility.EvaluateCurve(segmentPoints, t);
                    Vector3 nextPointOnPath = CubicBezierUtility.EvaluateCurve(segmentPoints, t + increment);

                    // angle at current point on path
                    float localAngle = 180 - MathUtility.MinAngle(prevPointOnPath, pointOnPath, nextPointOnPath);
                    // angle between the last added vertex, the current point on the path, and the next point on the path
                    float angleFromPrevVertex = 180 - MathUtility.MinAngle(lastAddedPoint, pointOnPath, nextPointOnPath);
                    float angleError          = Mathf.Max(localAngle, angleFromPrevVertex);


                    if ((angleError > maxAngleError && dstSinceLastVertex >= minVertexDst) || isLastPointOnPath)
                    {
                        currentPathLength += (lastAddedPoint - pointOnPath).magnitude;
                        splitData.cumulativeLength.Add(currentPathLength);
                        splitData.vertices.Add(pointOnPath);
                        splitData.tangents.Add(CubicBezierUtility.EvaluateCurveDerivative(segmentPoints, t).normalized);
                        splitData.minMax.AddValue(pointOnPath);
                        dstSinceLastVertex = 0;
                        lastAddedPoint     = pointOnPath;
                    }
                    else
                    {
                        dstSinceLastVertex += (pointOnPath - prevPointOnPath).magnitude;
                    }
                    prevPointOnPath = pointOnPath;
                }
                splitData.anchorVertexMap.Add(splitData.vertices.Count - 1);
            }
            return(splitData);
        }