Ejemplo n.º 1
0
        /// <summary>
        /// Creates a new bezier path along the given waypoints. The algorithm will automatically create new control points
        /// between the given <paramref name="points"/> to guarantee a smooth curve along the path.
        /// </summary>
        /// <param name="points">The waypoints to use as bezier points for the newly created bezier path.</param>
        /// <returns>A bezier path through the given bezier points.</returns>
        public static BezierPath Interpolate(Vector3[] points)
        {
            if (points.Length < 2)
            {
                throw new ArgumentOutOfRangeException("There are at least two points required to interpolate a bezier path.", "points");
            }

            BezierPath path = new BezierPath();

            for (int i = 0; i < points.Length; i++)
            {
                if (i == 0)
                {
                    Vector3 p1 = points[i];
                    Vector3 p2 = points[i + 1];

                    Vector3 tangent = (p2 - p1);
                    Vector3 q1      = p1 + tangent;

                    path.points.Add(p1);
                    path.points.Add(q1);
                }
                else if (i == points.Length - 1)
                {
                    Vector3 p0      = points[i - 1];
                    Vector3 p1      = points[i];
                    Vector3 tangent = (p1 - p0);
                    Vector3 q0      = p1 - tangent;

                    path.points.Add(q0);
                    path.points.Add(p1);
                }
                else
                {
                    Vector3 p0      = points[i - 1];
                    Vector3 p1      = points[i];
                    Vector3 p2      = points[i + 1];
                    Vector3 tangent = (p2 - p0).normalized;
                    Vector3 q0      = p1 - tangent * (p1 - p0).magnitude;
                    Vector3 q1      = p1 + tangent * (p2 - p1).magnitude;

                    path.points.Add(q0);
                    path.points.Add(p1);
                    path.points.Add(q1);
                }
            }

            return(path);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reduces the number of bezier points in the bezierpath and adjusts the corresponding control
        /// handle points to generate a mostly accurate curve to the original one.
        /// </summary>
        /// <param name="minSqrDistance">Minimum square distance between two points.</param>
        /// <param name="maxSqrDistance">Maximum square distance between two points.</param>
        public void Optimize(float minSqrDistance, float maxSqrDistance)
        {
            if (this.points.Count < 4 || (this.points.Count - 1) % 3 != 0)
            {
                return;
            }

            Stack <Vector3> newPoints = new Stack <Vector3>();

            Vector3[] bezierPoints = this.BezierPoints;

            newPoints.Push(bezierPoints[0]);

            Vector3 potentialNewPoint = bezierPoints[1];

            for (int i = 2; i < bezierPoints.Length; i++)
            {
                if (((potentialNewPoint - bezierPoints[i]).sqrMagnitude > minSqrDistance) &&
                    ((newPoints.Peek() - bezierPoints[i]).sqrMagnitude < maxSqrDistance))
                {
                    newPoints.Push(potentialNewPoint);
                }

                potentialNewPoint = bezierPoints[i];
            }

            // Correct last few points of the bezier path
            Vector3 p1      = newPoints.Pop();
            Vector3 p0      = newPoints.Peek();
            Vector3 tangent = (p0 - potentialNewPoint).normalized;

            float d2 = (potentialNewPoint - p1).magnitude;
            float d1 = (p1 - p0).magnitude;

            p1 = p1 + tangent * ((d1 - d2) / 2);

            newPoints.Push(p1);
            newPoints.Push(potentialNewPoint);

            this.Points = BezierPath.Interpolate(newPoints.ToArray()).Points.ToArray();
        }