Beispiel #1
0
        private 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;

            bezierOrVertexPathModified?.Invoke();

            bezierCreated?.Invoke();
        }
Beispiel #2
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 #3
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 #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>
 public VertexPath(BezierPath bezierPath, Transform transform, float maxAngleError = 0.3f,
                   float minVertexDst = 0) : this(bezierPath,
                                                  VertexPathUtility.SplitBezierPathByAngleError(bezierPath, maxAngleError, minVertexDst, VertexPath.accuracy),
                                                  transform)
 {
 }