void Start()
 {
     if (waypoints.Length > 0)
     {
         // Create a new bezier path from the waypoints.
         BezierPath bezierPath = new BezierPath(waypoints, closedLoop, PathSpace.xyz);
         GetComponent <PathCreator> ().bezierPath = bezierPath;
     }
 }
        void CreateBezier(Vector3 centre, bool defaultIs2D = false)
        {
            if (_bezierPath != null)
            {
                _bezierPath.OnModified -= BezierPathEdited;
            }

            var space = (defaultIs2D) ? PathSpace.xy : PathSpace.xyz;

            _bezierPath = new BezierPath(centre, false, space);

            _bezierPath.OnModified += BezierPathEdited;
            vertexPathUpToDate      = false;

            if (bezierOrVertexPathModified != null)
            {
                bezierOrVertexPathModified();
            }
            if (bezierCreated != null)
            {
                bezierCreated();
            }
        }
Beispiel #3
0
        /// Internal contructor
        VertexPath(BezierPath bezierPath, VertexPathUtility.PathSplitData pathSplitData, Transform transform)
        {
            this.transform = transform;
            space          = bezierPath.Space;
            isClosedLoop   = bezierPath.IsClosed;
            int numVerts = pathSplitData.vertices.Count;

            length = pathSplitData.cumulativeLength[numVerts - 1];

            localPoints   = new Vector3[numVerts];
            localNormals  = new Vector3[numVerts];
            localTangents = new Vector3[numVerts];
            cumulativeLengthAtEachVertex = new float[numVerts];
            times  = new float[numVerts];
            bounds = new Bounds((pathSplitData.minMax.Min + pathSplitData.minMax.Max) / 2, pathSplitData.minMax.Max - pathSplitData.minMax.Min);

            // Figure out up direction for path
            up = (bounds.size.z > bounds.size.y) ? Vector3.up : -Vector3.forward;
            Vector3 lastRotationAxis = up;

            // Loop through the data and assign to arrays.
            for (int i = 0; i < localPoints.Length; i++)
            {
                localPoints[i]   = pathSplitData.vertices[i];
                localTangents[i] = pathSplitData.tangents[i];
                cumulativeLengthAtEachVertex[i] = pathSplitData.cumulativeLength[i];
                times[i] = cumulativeLengthAtEachVertex[i] / length;

                // Calculate normals
                if (space == PathSpace.xyz)
                {
                    if (i == 0)
                    {
                        localNormals[0] = Vector3.Cross(lastRotationAxis, pathSplitData.tangents[0]).normalized;
                    }
                    else
                    {
                        // First reflection
                        Vector3 offset = (localPoints[i] - localPoints[i - 1]);
                        float   sqrDst = offset.sqrMagnitude;
                        Vector3 r      = lastRotationAxis - offset * 2 / sqrDst * Vector3.Dot(offset, lastRotationAxis);
                        Vector3 t      = localTangents[i - 1] - offset * 2 / sqrDst * Vector3.Dot(offset, localTangents[i - 1]);

                        // Second reflection
                        Vector3 v2 = localTangents[i] - t;
                        float   c2 = Vector3.Dot(v2, v2);

                        Vector3 finalRot = r - v2 * 2 / c2 * Vector3.Dot(v2, r);
                        Vector3 n        = Vector3.Cross(finalRot, localTangents[i]).normalized;
                        localNormals[i]  = n;
                        lastRotationAxis = finalRot;
                    }
                }
                else
                {
                    localNormals[i] = Vector3.Cross(localTangents[i], up) * ((bezierPath.FlipNormals) ? 1 : -1);
                }
            }

            // Apply correction for 3d normals along a closed path
            if (space == PathSpace.xyz && isClosedLoop)
            {
                // Get angle between first and last normal (if zero, they're already lined up, otherwise we need to correct)
                float normalsAngleErrorAcrossJoin = Vector3.SignedAngle(localNormals[localNormals.Length - 1], localNormals[0], localTangents[0]);
                // Gradually rotate the normals along the path to ensure start and end normals line up correctly
                if (Mathf.Abs(normalsAngleErrorAcrossJoin) > 0.1f) // don't bother correcting if very nearly correct
                {
                    for (int i = 1; i < localNormals.Length; i++)
                    {
                        float      t     = (i / (localNormals.Length - 1f));
                        float      angle = normalsAngleErrorAcrossJoin * t;
                        Quaternion rot   = Quaternion.AngleAxis(angle, localTangents[i]);
                        localNormals[i] = rot * localNormals[i] * ((bezierPath.FlipNormals) ? -1 : 1);
                    }
                }
            }

            // Rotate normals to match up with user-defined anchor angles
            if (space == PathSpace.xyz)
            {
                for (int anchorIndex = 0; anchorIndex < pathSplitData.anchorVertexMap.Count - 1; anchorIndex++)
                {
                    int nextAnchorIndex = (isClosedLoop) ? (anchorIndex + 1) % bezierPath.NumSegments : anchorIndex + 1;

                    float startAngle = bezierPath.GetAnchorNormalAngle(anchorIndex) + bezierPath.GlobalNormalsAngle;
                    float endAngle   = bezierPath.GetAnchorNormalAngle(nextAnchorIndex) + bezierPath.GlobalNormalsAngle;
                    float deltaAngle = Mathf.DeltaAngle(startAngle, endAngle);

                    int startVertIndex = pathSplitData.anchorVertexMap[anchorIndex];
                    int endVertIndex   = pathSplitData.anchorVertexMap[anchorIndex + 1];

                    int num = endVertIndex - startVertIndex;
                    if (anchorIndex == pathSplitData.anchorVertexMap.Count - 2)
                    {
                        num += 1;
                    }
                    for (int i = 0; i < num; i++)
                    {
                        int        vertIndex = startVertIndex + i;
                        float      t         = i / (num - 1f);
                        float      angle     = startAngle + deltaAngle * t;
                        Quaternion rot       = Quaternion.AngleAxis(angle, localTangents[vertIndex]);
                        localNormals[vertIndex] = (rot * localNormals[vertIndex]) * ((bezierPath.FlipNormals) ? -1 : 1);
                    }
                }
            }
        }
Beispiel #4
0
 /// <summary> Splits bezier path into array of vertices along the path.</summary>
 ///<param name="maxAngleError">How much can the angle of the path change before a vertex is added. This allows fewer vertices to be generated in straighter sections.</param>
 ///<param name="minVertexDst">Vertices won't be added closer together than this distance, regardless of angle error.</param>
 ///<param name="accuracy">Higher value means the change in angle is checked more frequently.</param>
 public VertexPath(BezierPath bezierPath, Transform transform, float vertexSpacing) :
     this(bezierPath, VertexPathUtility.SplitBezierPathEvenly(bezierPath, Mathf.Max(vertexSpacing, minVertexSpacing), VertexPath.accuracy), transform)
 {
 }
Beispiel #5
0
 /// <summary> Splits bezier path into array of vertices along the path.</summary>
 ///<param name="maxAngleError">How much can the angle of the path change before a vertex is added. This allows fewer vertices to be generated in straighter sections.</param>
 ///<param name="minVertexDst">Vertices won't be added closer together than this distance, regardless of angle error.</param>
 public VertexPath(BezierPath bezierPath, Transform transform, float maxAngleError = 0.3f, float minVertexDst = 0) :
     this(bezierPath, VertexPathUtility.SplitBezierPathByAngleError(bezierPath, maxAngleError, minVertexDst, VertexPath.accuracy), transform)
 {
 }