Beispiel #1
0
 /// <summary>
 /// Adds a node at the end of the spline.
 /// </summary>
 /// <param name="node"></param>
 public void AddNode(SplineNode node)
 {
     nodes.Add(node);
     if (nodes.Count != 1)
     {
         SplineNode       previousNode = nodes[nodes.IndexOf(node) - 1];
         CubicBezierCurve curve        = new CubicBezierCurve(previousNode, node);
         curve.Changed.AddListener(() => UpdateAfterCurveChanged());
         curves.Add(curve);
     }
     RaiseNodeCountChanged();
     UpdateAfterCurveChanged();
 }
Beispiel #2
0
 public CurveSample(Vector3 location, Vector3 tangent, Vector3 up, Vector2 scale, float roll, float distanceInCurve, float timeInCurve, CubicBezierCurve curve)
 {
     this.location        = location;
     this.tangent         = tangent;
     this.up              = up;
     this.roll            = roll;
     this.scale           = scale;
     this.distanceInCurve = distanceInCurve;
     this.timeInCurve     = timeInCurve;
     this.curve           = curve;
     index    = -1;
     rotation = Quaternion.identity;
 }
Beispiel #3
0
 /// <summary>
 /// Set the cubic Bézier curve to use to bend the source mesh, and begin to listen to curve control points for changes.
 /// </summary>
 /// <param name="curve"></param>
 /// <param name="update">If let to true, update the resulting mesh immediatly.</param>
 public void SetCurve(CubicBezierCurve curve, bool update = true)
 {
     if (this.curve != null)
     {
         this.curve.Changed.RemoveListener(() => Compute());
     }
     this.curve = curve;
     curve.Changed.AddListener(() => Compute());
     if (update)
     {
         Compute();
     }
 }
Beispiel #4
0
        private void OnEnable()
        {
            curves.Clear();
            for (int i = 0; i < nodes.Count - 1; i++)
            {
                SplineNode n    = nodes[i];
                SplineNode next = nodes[i + 1];

                CubicBezierCurve curve = new CubicBezierCurve(n, next);
                curve.Changed.AddListener(() => UpdateAfterCurveChanged());
                curves.Add(curve);
            }
            RaiseNodeCountChanged();
            UpdateAfterCurveChanged();
        }
Beispiel #5
0
        /// <summary>
        /// Refreshes the spline's internal list of curves.
        // </summary>
        public void RefreshCurves()
        {
            curves.Clear();
            for (int i = 0; i < nodes.Count - 1; i++)
            {
                SplineNode n    = nodes[i];
                SplineNode next = nodes[i + 1];

                CubicBezierCurve curve = new CubicBezierCurve(n, next);
                curve.Changed.AddListener(UpdateAfterCurveChanged);
                curves.Add(curve);
            }
            RaiseNodeListChanged(new ListChangedEventArgs <SplineNode>()
            {
                type = ListChangeType.clear
            });
            UpdateAfterCurveChanged();
        }
Beispiel #6
0
 /// <summary>
 /// Sets a curve along which the mesh will be bent.
 /// The mesh will be updated if the curve changes.
 /// </summary>
 /// <param name="curve">The <see cref="CubicBezierCurve"/> to bend the source mesh along.</param>
 public void SetInterval(CubicBezierCurve curve)
 {
     if (this.curve == curve)
     {
         return;
     }
     if (curve == null)
     {
         throw new ArgumentNullException("curve");
     }
     if (this.curve != null)
     {
         this.curve.Changed.RemoveListener(SetDirty);
     }
     this.curve = curve;
     spline     = null;
     curve.Changed.AddListener(SetDirty);
     useSpline = false;
     SetDirty();
 }
Beispiel #7
0
        /// <summary>
        /// Insert the given node in the spline at index. Index must be greater than 0 and less than node count.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="node"></param>
        public void InsertNode(int index, SplineNode node)
        {
            if (index == 0)
            {
                throw new Exception("Can't insert a node at index 0");
            }

            SplineNode previousNode = nodes[index - 1];
            SplineNode nextNode     = nodes[index];

            nodes.Insert(index, node);

            curves[index - 1].ConnectEnd(node);

            CubicBezierCurve curve = new CubicBezierCurve(node, nextNode);

            curve.Changed.AddListener(() => UpdateAfterCurveChanged());
            curves.Insert(index, curve);
            RaiseNodeCountChanged();
            UpdateAfterCurveChanged();
        }
Beispiel #8
0
        /// <summary>
        /// Adds a node at the end of the spline.
        /// </summary>
        /// <param name="node"></param>
        public void AddNode(SplineNode node)
        {
            nodes.Add(node);
            if (nodes.Count != 1)
            {
                SplineNode       previousNode = nodes[nodes.IndexOf(node) - 1];
                CubicBezierCurve curve        = new CubicBezierCurve(previousNode, node);
                curve.Changed.AddListener(() => UpdateAfterCurveChanged());
                curves.Add(curve);
            }
            RaiseNodeListeChanged(new ListChangedEventArgs <SplineNode>()
            {
                type     = ListChangeType.Add,
                newItems = new List <SplineNode>()
                {
                    node
                }
            });

            UpdateAfterCurveChanged();
        }
        public void AddMultipleNodes(List <SplineNode> _nodes)
        {
            _nodes.ForEach(node => {
                nodes.Add(node);
                if (nodes.Count != 1)
                {
                    SplineNode previousNode = nodes[nodes.IndexOf(node) - 1];
                    CubicBezierCurve curve  = new CubicBezierCurve(previousNode, node);
                    curve.Changed.AddListener(UpdateAfterCurveChanged);
                    curves.Add(curve);
                }
                RaiseNodeListChanged(new ListChangedEventArgs <SplineNode>()
                {
                    type     = ListChangeType.Add,
                    newItems = new List <SplineNode>()
                    {
                        node
                    }
                });

                UpdateAfterCurveChanged();
                updateLoopBinding();
            });
        }
Beispiel #10
0
        /// <summary>
        /// Remove the given node from the spline. The given node must exist and the spline must have more than 2 nodes.
        /// </summary>
        /// <param name="node"></param>
        public void RemoveNode(SplineNode node)
        {
            int index = nodes.IndexOf(node);

            if (nodes.Count <= 2)
            {
                throw new Exception("Can't remove the node because a spline needs at least 2 nodes.");
            }

            CubicBezierCurve toRemove = index == nodes.Count - 1? curves[index - 1] : curves[index];

            if (index != 0 && index != nodes.Count - 1)
            {
                SplineNode nextNode = nodes[index + 1];
                curves[index - 1].ConnectEnd(nextNode);
            }

            nodes.RemoveAt(index);
            toRemove.Changed.RemoveListener(() => UpdateAfterCurveChanged());
            curves.Remove(toRemove);

            RaiseNodeCountChanged();
            UpdateAfterCurveChanged();
        }
Beispiel #11
0
 /// <summary>
 /// Returns the tangent of spline at distance. Distance must be between 0 and spline length.
 /// </summary>
 /// <param name="d"></param>
 /// <returns></returns>
 public Vector3 GetTangentAlongSplineAtDistance(float d)
 {
     if (d < 0 || d > Length)
     {
         throw new ArgumentException(string.Format("Distance must be between 0 and spline length ({0}). Given distance was {1}.", Length, d));
     }
     for (var i = 0; i < curves.Count; i++)
     {
         CubicBezierCurve curve = curves[i];
         if (d > curve.Length)
         {
             if (i == curves.Count - 1)
             {
                 return(curve.GetTangentAtDistance(curve.Length));
             }
             d -= curve.Length;
         }
         else
         {
             return(curve.GetTangentAtDistance(d));
         }
     }
     throw new Exception("Something went wrong with GetTangentAlongSplineAtDistance");
 }
Beispiel #12
0
        private void Compute()
        {
            if (source == null)
            {
                return;
            }

            if (generatedMesh == null)
            {
                generatedMesh = new Mesh();
            }

            int nbVert = source.vertices.Length;
            // find the bounds along BendAxis
            float minX = float.MaxValue;
            float maxX = float.MinValue;

            foreach (Vertex vert in vertices)
            {
                Vector3 p = vert.v;
                if (sourceRotation != Quaternion.identity)
                {
                    p = sourceRotation * p;
                }

                if (sourceTranslation != Vector3.zero)
                {
                    p += sourceTranslation;
                }

                switch (BendAxis)
                {
                case Axis.X:
                    maxX = Math.Max(maxX, p.x);
                    minX = Math.Min(minX, p.x);
                    break;

                case Axis.Z:
                    maxX = Math.Max(maxX, p.z);
                    minX = Math.Min(minX, p.z);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            float length = Math.Abs(maxX - minX);

            List <Vector3> deformedVerts   = new List <Vector3>(nbVert);
            List <Vector3> deformedNormals = new List <Vector3>(nbVert);

            // for each mesh vertex, we have to find its projection on the curve
            foreach (Vertex vert in vertices)
            {
                Vector3 p = vert.v;
                Vector3 n = vert.n;
                //  application of rotation
                if (sourceRotation != Quaternion.identity)
                {
                    p = sourceRotation * p;
                    n = sourceRotation * n;
                }

                if (sourceTranslation != Vector3.zero)
                {
                    p += sourceTranslation;
                }

                float distanceRate;

                switch (BendAxis)
                {
                case Axis.X:
                    distanceRate = Math.Abs(p.x - minX) / length;
                    break;

                case Axis.Z:
                    distanceRate = Math.Abs(p.z - minX) / length;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                Vector3    curvePoint   = curve.GetLocationAtDistance(curve.Length * distanceRate);
                Vector3    curveTangent = curve.GetTangentAtDistance(curve.Length * distanceRate);
                Quaternion q            = CubicBezierCurve.GetRotationFromTangent(curveTangent);

                // application of scale
                float scaleAtDistance = startScale + (endScale - startScale) * distanceRate;
                p *= scaleAtDistance;

                // application of roll
                float rollAtDistance = startRoll + (endRoll - startRoll) * distanceRate;

                switch (BendAxis)
                {
                case Axis.X:
                    p = Quaternion.AngleAxis(rollAtDistance, Vector3.right) * p;
                    n = Quaternion.AngleAxis(rollAtDistance, Vector3.right) * n;
                    // reset X value of p
                    p = new Vector3(0, p.y, p.z);
                    break;

                case Axis.Z:
                    p = Quaternion.AngleAxis(rollAtDistance, Vector3.forward) * p;
                    n = Quaternion.AngleAxis(rollAtDistance, Vector3.forward) * n;
                    // reset Z value of p
                    p = new Vector3(p.x, p.y, 0);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                Vector3 fvert = q * p + curvePoint;
                deformedVerts.Add(fvert);
                deformedNormals.Add(q * n);
            }

            generatedMesh.vertices           = deformedVerts.ToArray();
            generatedMesh.normals            = deformedNormals.ToArray();
            generatedMesh.uv                 = source.uv;
            generatedMesh.triangles          = source.triangles;
            GetComponent <MeshFilter>().mesh = generatedMesh;
        }