GetVelocity() 공개 메소드

public GetVelocity ( float t ) : Vector3
t float
리턴 Vector3
예제 #1
0
파일: Edge.cs 프로젝트: dereksx/Knitting
 public Vector3 GetInitVelocity(Node n)
 {
     if (n == _edgeVertices[0])
     {
         return(curve.GetVelocity(0));
     }
     else
     {
         return(-curve.GetVelocity(1));
     }
 }
예제 #2
0
    private void ShowTangents()
    {
        Handles.color = Color.green;
        var point = spline.GetPoint(0f);

        Handles.DrawLine(point, point + spline.GetVelocity(0f).normalized);
        for (var i = 1; i <= lineSteps; i++)
        {
            point = spline.GetPoint(i / (float)lineSteps);
            Handles.DrawLine(point, point + spline.GetVelocity(i / (float)lineSteps).normalized);
        }
    }
    Vector3 SplineNormal(float val)
    {
        var point      = spline.GetPoint(val);
        var dir        = spline.GetVelocity(val);
        var projection = Vector3.ProjectOnPlane(dir, Vector3.up);

        if (flip)
        {
            return(new Vector3(projection.z, 0, -projection.x).normalized);
        }
        return(new Vector3(-projection.z, 0, projection.x).normalized);
    }
예제 #4
0
    public void disableSplineMovement()
    {
        float speed = this.GetComponent <Rigidbody2D>().velocity.magnitude;

        if (direction == TravelDirection.Backward)
        {
            speed *= -1f;
        }

        this.GetComponent <Rigidbody2D>().velocity = spline.GetVelocity(progress).normalized *speed;
        this.enabled = false;
        this.GetComponent <Rigidbody2D>().isKinematic = false;
    }
    private void ShowVelocity()
    {
        Handles.color = Color.green;
        Vector3 point = master.transform.TransformPoint(spline.GetPoint(0f));

        Handles.DrawLine(point, point + spline.GetVelocity(0f) * directionScale);

        int ls = lineSteps * spline.ControlPointCount;

        for (int i = 1; i <= ls; i++)
        {
            point = master.transform.TransformPoint(spline.GetPoint(i / (float)ls));
            Handles.DrawLine(point, point + spline.GetVelocity(i / (float)ls) * directionScale);
        }
    }
예제 #6
0
    void FixedUpdate()
    {
        if (Vector3.Distance(transform.position, targetPoint) < 15)
        {
            targetAmountAlongSpline += 0.003f;
            targetPoint              = centerLane.GetPoint(targetAmountAlongSpline % 1);

            Vector3 splineDirection = centerLane.GetVelocity(targetAmountAlongSpline % 1);
            Vector3 right           = Vector3.Cross(Vector3.up, splineDirection).normalized;

            targetPoint += right * lane * laneWidth;
        }

        //otherThing.transform.position = targetPoint;

        Vector3 relativePosition = transform.InverseTransformPoint(targetPoint);

        relativePosition.y = 0;

        float angle = Vector3.Angle(Vector3.forward, relativePosition);

        if (relativePosition.x < 0)
        {
            angle = -angle;
        }
        ;

        SetSteer(angle);
    }
예제 #7
0
 // Update is called once per frame
 void Update()
 {
     for (int i = 0; i < transform.childCount; i++)
     {
         Transform child = transform.GetChild(i);
         child.position = spline.GetPoint((float)i / (float)transform.childCount);
         child.up       = spline.GetVelocity((float)i / (float)transform.childCount);
     }
 }
예제 #8
0
        public Vector3 TraversePath(float speed, ref float t)
        {
            t = Mathf.Clamp01(t);
            Vector3 target   = spline.GetPoint(t);
            Vector3 velocity = spline.GetVelocity(t);

            t += Time.deltaTime * speed / velocity.magnitude;
            return(target);
        }
예제 #9
0
    // Update is called once per frame
    void Update()
    {
        if (speed == 0)
        {
            return;
        }

        float progressAmount = Time.deltaTime / (spline.GetVelocity(progress).magnitude / speed);

        if (goingForward)
        {
            progress += progressAmount;
            if (progress > 1f)
            {
                if (mode == SplineWalkerMode.Once)
                {
                    progress = 1.0f;
                }
                else if (mode == SplineWalkerMode.Loop)
                {
                    progress -= 1.0f;
                }
                else
                {
                    progress     = 2f - progress;
                    goingForward = false;
                }
            }
        }
        else
        {
            progress -= progressAmount;
            if (progress < 0f)
            {
                progress     = -progress;
                goingForward = true;
            }
        }

        Vector3 position = spline.GetPoint(progress);

        transform.localPosition = position;
        if (lookForward)
        {
            if (goingForward)
            {
                transform.LookAt(position + spline.GetDirection(progress));
            }
            else
            {
                transform.LookAt(position - spline.GetDirection(progress));
            }
        }
    }
예제 #10
0
 private void FixedUpdate()
 {
     progress += Time.fixedDeltaTime / duration;
     if (progress > 1f)
     {
         progress = 0f;
     }
     transform.localPosition = spline.GetPosition(progress);
     if (faceDirection)
     {
         transform.LookAt((Vector2)transform.position + spline.GetVelocity(progress));
         transform.rotation *= Quaternion.Euler(0, 90, 0);
     }
 }
예제 #11
0
    private Vector3 CalculateNewEulerAngles()
    {
        //get current euler angles
        Vector3 oldEuler = this.transform.rotation.eulerAngles;
        Vector3 newEuler = oldEuler;

        //Get Velocity
        Vector3 splineVelocity = m_Spline.GetVelocity(m_splinePos, true);

        //Calculate Rotation
        switch (m_rotationAxis)
        {
        case RotationAxis.X:
        {
            float newXangle = -Mathf.Rad2Deg * Mathf.Atan2(splineVelocity.y, splineVelocity.z);
            //combine angles
            newEuler.x = newXangle;

            break;
        }

        case RotationAxis.Y:
        {
            float newYangle = -Mathf.Rad2Deg * Mathf.Atan2(splineVelocity.z, splineVelocity.x);
            //combine angles
            newEuler.y = newYangle;

            break;
        }

        case RotationAxis.Z:
        {
            float newZangle = -Mathf.Rad2Deg * Mathf.Atan2(splineVelocity.y, splineVelocity.x);
            //combine angles
            newEuler.z = newZangle;

            break;
        }
        }

        return(newEuler);
    }
예제 #12
0
    // Fixed update is called in sync with physics
    private void FixedUpdate()
    {
        bool up   = Input.GetKey(KeyCode.UpArrow);
        bool down = Input.GetKey(KeyCode.DownArrow);

        Vector3 moveVector = Vector3.zero;

        if (up || down)
        {
            Vector3 splineTangent = Vector3.ProjectOnPlane(spline.GetVelocity(t), Vector3.up);

            //advance t along the line
            float deltaT = 0;
            if (up)
            {
                deltaT = speed / splineTangent.magnitude;
            }
            else if (down)
            {
                deltaT = -speed / splineTangent.magnitude;
            }

            t += deltaT;

            moveVector = spline.pointAt(t) - transform.position;             //vector from character to spline point

            //draw moveVector
            Debug.DrawLine(transform.position, transform.position + moveVector, Color.red);

            //project moveVector onto ground normal
            moveVector = Vector3.ProjectOnPlane(moveVector, Vector3.up);

            //apply movement and rotation
            transform.position += moveVector;
            transform.rotation  = Quaternion.LookRotation(Math.Sign(deltaT) * splineTangent, Vector3.up);
            Debug.Log("moveVector: " + moveVector + ", y rotation: " + transform.rotation.eulerAngles.y);
        }

        // update the animator parameters
        animator.SetFloat("Forward", moveVector.magnitude);
    }
예제 #13
0
    void OnRenderObject()
    {
        // Make sure I have the thigs I need to get the data to deform text
        if (m_TextComponent == null)
        {
            m_TextComponent = gameObject.GetComponent <TextMeshPro>();
        }
        if (vertexCurve == null)
        {
            vertexCurve = gameObject.GetComponent <BezierSpline>();
        }

        if (m_TextComponent)
        {
            Vector3[] vertexPositions;

            m_TextComponent.renderMode = TextRenderFlags.Render;
            m_TextComponent.ForceMeshUpdate();
            m_TextComponent.renderMode = TextRenderFlags.DontRender;

            TMP_TextInfo textInfo       = m_TextComponent.textInfo;
            int          characterCount = textInfo.characterCount;

            if (characterCount >= 0)
            {
                vertexPositions = textInfo.meshInfo[0].vertices;

                float boundsMaxX = m_TextComponent.rectTransform.rect.width * 0.5f;
                float boundsMinX = -boundsMaxX;

                for (int i = 0; i < characterCount; i++)
                {
                    if (!textInfo.characterInfo[i].isVisible)
                    {
                        continue;
                    }

                    int vertexIndex = textInfo.characterInfo[i].vertexIndex;

                    // Compute the baseline mid point for each character
                    Vector3 offsetToMidBaseline = new Vector3((vertexPositions[vertexIndex + 0].x + vertexPositions[vertexIndex + 2].x) / 2, textInfo.characterInfo[i].baseLine);

                    Vector3 c0 = vertexPositions[vertexIndex + 0] - offsetToMidBaseline;
                    Vector3 c1 = vertexPositions[vertexIndex + 1] - offsetToMidBaseline;
                    Vector3 c2 = vertexPositions[vertexIndex + 2] - offsetToMidBaseline;
                    Vector3 c3 = vertexPositions[vertexIndex + 3] - offsetToMidBaseline;

                    float   t     = (offsetToMidBaseline.x - boundsMinX) / (boundsMaxX - boundsMinX);
                    Vector3 point = transform.InverseTransformPoint(vertexCurve.GetPoint(t)) * curveScale;
                    Vector3 xAxis = transform.InverseTransformDirection(vertexCurve.GetVelocity(t)).normalized;
                    Vector3 yAxis = (Vector3.up - xAxis * xAxis.y).normalized;

                    vertexPositions[vertexIndex + 0] = point + c0.x * xAxis + c0.y * yAxis;
                    vertexPositions[vertexIndex + 1] = point + c1.x * xAxis + c1.y * yAxis;
                    vertexPositions[vertexIndex + 2] = point + c2.x * xAxis + c2.y * yAxis;
                    vertexPositions[vertexIndex + 3] = point + c3.x * xAxis + c3.y * yAxis;
                }

                // Upload the mesh with the revised information
                m_TextComponent.mesh.vertices = vertexPositions;
                m_TextComponent.mesh.uv       = textInfo.meshInfo[0].uvs0;
                m_TextComponent.mesh.uv2      = textInfo.meshInfo[0].uvs2;
                m_TextComponent.mesh.colors32 = textInfo.meshInfo[0].colors32;

                m_TextComponent.mesh.RecalculateBounds(); // We need to update the bounds of the text object.
            }
        }
    }
예제 #14
0
    public void CreateMeshWithClosedStart()
    {
        Vector3    positionStart  = spline.GetPoint(0);
        Vector3    directionStart = spline.GetVelocity(0).normalized;
        Vector3    position;
        Vector3    direction;
        Vector3    pt;
        Quaternion FromToRotation;

        vertices = CreateCircleEdge();

        progress = 0f;

        mesh.Clear();

        Array.Resize(ref meshVertices, pointsOnCircle * 2 + 1); // +1 to close start point side

        for (int j = 0, k = 0; j < 2; j++)
        {
            position       = spline.GetPoint(progress);
            direction      = spline.GetVelocity(progress);
            FromToRotation = Quaternion.FromToRotation(directionStart, direction);

            for (int i = 0; i < pointsOnCircle; i++, k++)
            {
                pt = FromToRotation * transform.rotation * vertices[i];
                meshVertices[k] = pt + position;
            }

            progress += 1f / splineSteps;
        }
        meshVertices[meshVertices.Length - 1] = positionStart;


        Array.Resize(ref meshTriangles, pointsOnCircle * 9);// old *6

        for (int ti = 0, vi = 0, x = 0; x < pointsOnCircle; x++, ti += 9, vi++)
        {
            meshTriangles[ti + 6] = meshTriangles[ti] = vi;

            meshTriangles[ti + 4] = meshTriangles[ti + 1] = vi + pointsOnCircle;

            if (vi < pointsOnCircle - 1)
            {
                meshTriangles[ti + 3] = meshTriangles[ti + 2] = vi + 1;
                meshTriangles[ti + 5] = vi + pointsOnCircle + 1;
            }
            else
            {
                meshTriangles[ti + 3] = meshTriangles[ti + 2] = 0;
                meshTriangles[ti + 5] = pointsOnCircle;
            }
            meshTriangles[ti + 7] = meshTriangles[ti + 2];
            meshTriangles[ti + 8] = meshVertices.Length - 1;
        }

        mesh.vertices  = meshVertices;
        mesh.triangles = meshTriangles;

        mesh.RecalculateNormals();
    }
예제 #15
0
    private IEnumerator Generate()
    {
        GetComponent <MeshFilter>().mesh = mesh = new Mesh();
        mesh.name = "Procedural Grid";
        rings.Clear();
        while (transform.childCount > 0)
        {
            GameObject.DestroyImmediate(transform.GetChild(transform.childCount - 1));
        }


        Vector3 LastDirection = spline.GetVelocity(0).normalized;
        float   t             = 0;

        while (t < 1)
        {
            t += jumps;
            if (MaxAngle < Vector3.Angle(LastDirection, spline.GetVelocity(t).normalized))
            {
                //rings.Add(Vector3.Angle(LastDirection, spline.GetVelocity(t).normalized));
                rings.Add(t);
                LastDirection = spline.GetVelocity(t).normalized;
            }
            //
        }

        float x, y, angle = 0;

        vertices = new Vector3[circleVertices * (rings.Count + 1)];
        yield return(null);

        Vector2[] uv = new Vector2[vertices.Length];
        for (int j = 0; j < rings.Count + 1; j++)
        {
            int       start     = j * circleVertices;
            Transform tr        = new GameObject("CurvePoint").transform;
            Vector3   direction = spline.GetVelocity(rings[j]).normalized;
            tr.rotation = Quaternion.LookRotation(direction);

            Vector3 point = spline.GetPoint(t) - transform.position;
            tr.parent   = transform;
            tr.position = point;
            for (int i = start; i < start + circleVertices; i++)
            {
                x = radius * Mathf.Cos(angle * Mathf.Deg2Rad);
                y = radius * Mathf.Sin(angle * Mathf.Deg2Rad);
                //print(point);
                vertices[i] = tr.TransformPoint(new Vector3(x, y, 0));
                uv[i]       = new Vector2((float)i / circleVertices, 0);
                angle      += 360 / circleVertices;
                //yield return new WaitForSecondsRealtime(0.01f);
            }
        }

        /*
         * mesh.vertices = vertices;
         * int[] triangles = new int[(circleVertices) * (rings.Count + 1) * 6];
         * int vert = 0, vertRef = 0, circle = 0, total = 0;
         * for(int r = 0; r < rings.Count; r++){
         *      circle = r * circleVertices;
         *      string result;
         *      for(vertRef = 0; vertRef < circleVertices - 1; vertRef++){
         *              vert = (vertRef * 6) + (circleVertices * 6) * r;
         *              result = "[";
         *              result += triangles[(0 + vert)] = vertRef + circle;
         *              result += triangles[(1 + vert)] = vertRef + 1 + circle;
         *              result += triangles[(2 + vert)] = circleVertices + vertRef + circle;
         *              result += "][";
         *              result += triangles[(3 + vert)] = vertRef + 1 + circle;
         *              result += triangles[(5 + vert)] = circleVertices + vertRef + circle;
         *              result += triangles[(4 + vert)] = vertRef + circleVertices + 1 + circle;
         *              //print(result + "]");
         *      }
         *      vert = (vertRef * 6) + (circleVertices * 6) * r;
         *      result = "[";
         *      result += triangles[(2 + vert)] = vertRef + circle;
         *      result += triangles[(1 + vert)] = vertRef + 1 + circle;
         *      result += triangles[(0 + vert)] = circle;
         *      result += "][";
         *      result += triangles[(4 + vert)] = vertRef + 1 + circle;
         *      result += triangles[(5 + vert)] = circleVertices + vertRef + circle;
         *      result += triangles[(3 + vert)] = vertRef + circle;
         *      //print(result + "]");
         * }
         * mesh.triangles = triangles;
         *
         * mesh.RecalculateNormals();
         *
         * mesh.uv = uv;
         */
    }
예제 #16
0
 public void OnDisable()
 {
     gameObject.GetComponent <Rigidbody> ().velocity   = spline.GetVelocity(progress);
     gameObject.GetComponent <Rigidbody>().isKinematic = false;
     gameObject.GetComponent <Rigidbody>().useGravity  = true;
 }
예제 #17
0
    private void Update()
    {
        if (spline && TravellingInPositiveDirection)
        {
            VelocitySystem();
            progress += (speed / (float)curvesInSpline) * Time.deltaTime;
            if (progress > 1f)
            {
                progress = 1f;
            }
            Vector3 position = spline.GetPoint(progress);
            transform.position = position;
            if (lookForward)
            {
                transform.LookAt(position + spline.GetDirection(progress));
            }

            if (progress >= 1f)
            {
                Rigidbody rBody = gameObject.GetComponent <Rigidbody>();
                rBody.velocity = Vector3.zero;

                transform.rotation = Quaternion.Euler(0, transform.rotation.eulerAngles.y, 0);
                rBody.AddForce(spline.GetVelocity(1f) * speed * 14f);
                Debug.Log(rBody.velocity.sqrMagnitude);

                spline   = null;
                speed    = minSpeed;
                progress = 0f;
            }
        }
        else if (spline)
        {
            VelocitySystem();
            progress -= (speed / (float)curvesInSpline) * Time.deltaTime;
            if (progress < 0f)
            {
                progress = 0f;
            }
            Vector3 position = spline.GetPoint(progress);
            transform.position = position;
            if (lookForward)
            {
                transform.LookAt(position + spline.GetDirection(progress) * -1);
            }

            if (progress <= 0f)
            {
                Rigidbody rBody = gameObject.GetComponent <Rigidbody>();
                rBody.velocity = Vector3.zero;
                //StartCoroutine(StandUpRight());

                transform.rotation = Quaternion.Euler(0, transform.rotation.eulerAngles.y, 0);
                rBody.AddForce(spline.GetVelocity(0f) * speed * -14f);

                spline   = null;
                speed    = minSpeed;
                progress = 0f;
            }
        }
    }
예제 #18
0
    private IEnumerator Generate()
    {
        GetComponent <MeshFilter>().mesh = mesh = new Mesh();
        mesh.name = "Procedural Grid";

        float x, y, z = 0, angle = 0, t = 0;

        vertices = new Vector3[circleVertices * (rings + 1)];
        Vector2[] uv = new Vector2[vertices.Length];
        for (int j = 0; j < rings + 1; j++)
        {
            int start = j * circleVertices;
            t = (float)(j) / (float)rings;
            Transform tr        = new GameObject("CurvePoint").transform;
            Vector3   direction = spline.GetVelocity(t).normalized;
            tr.rotation = Quaternion.LookRotation(direction);
            print(direction);
            Vector3 point = spline.GetPoint(t) - transform.position;
            tr.parent   = transform;
            tr.position = point;
            for (int i = start; i < start + circleVertices; i++)
            {
                x = radius * Mathf.Cos(angle * Mathf.Deg2Rad);
                y = radius * Mathf.Sin(angle * Mathf.Deg2Rad);
                //print(point);
                vertices[i] = tr.TransformPoint(new Vector3(x, y, 0));
                uv[i]       = new Vector2((float)i / circleVertices, 0);
                angle      += 360 / circleVertices;
                yield return(new WaitForSecondsRealtime(0.01f));
            }
        }
        mesh.vertices = vertices;
        int[] triangles = new int[(circleVertices) * (rings + 1) * 6];
        int   vert = 0, vertRef = 0, circle = 0, total = 0;

        for (int r = 0; r < rings; r++)
        {
            circle = r * circleVertices;
            string result;
            for (vertRef = 0; vertRef < circleVertices - 1; vertRef++)
            {
                vert    = (vertRef * 6) + (circleVertices * 6) * r;
                result  = "[";
                result += triangles[(0 + vert)] = vertRef + circle;
                result += triangles[(1 + vert)] = vertRef + 1 + circle;
                result += triangles[(2 + vert)] = circleVertices + vertRef + circle;
                result += "][";
                result += triangles[(3 + vert)] = vertRef + 1 + circle;
                result += triangles[(5 + vert)] = circleVertices + vertRef + circle;
                result += triangles[(4 + vert)] = vertRef + circleVertices + 1 + circle;
                //print(result + "]");
            }
            vert    = (vertRef * 6) + (circleVertices * 6) * r;
            result  = "[";
            result += triangles[(2 + vert)] = vertRef + circle;
            result += triangles[(1 + vert)] = vertRef + 1 + circle;
            result += triangles[(0 + vert)] = circle;
            result += "][";
            result += triangles[(4 + vert)] = vertRef + 1 + circle;
            result += triangles[(5 + vert)] = circleVertices + vertRef + circle;
            result += triangles[(3 + vert)] = vertRef + circle;
            //print(result + "]");
        }
        mesh.triangles = triangles;

        mesh.RecalculateNormals();

        mesh.uv = uv;
    }
예제 #19
0
    public Mesh CreateMesh()
    {
        Mesh mesh;

        mesh = new Mesh();

        float          scaling  = 1f;
        float          width    = thickness / 2f;
        List <Vector3> vertList = new List <Vector3>();
        List <int>     triList  = new List <int>();
        List <Vector2> uvList   = new List <Vector2>();
        Vector3        upNormal = new Vector3(0, 0, 1);

        triList.AddRange(new int[] {
            2, 1, 0,    //start face
            0, 3, 2
        });

        for (int s = 0; s < resolution; s++)
        {
            float t       = ((float)s) / resolution;
            float futureT = ((float)s + 1) / resolution;

            Vector3 segmentStart = spline.GetPoint(t);
            Vector3 segmentEnd   = spline.GetPoint(futureT);

            Vector3 segmentDirection = spline.GetVelocity(t) - spline.GetVelocity(futureT);
            segmentDirection.Normalize();

            Vector3 segmentRight = Vector3.ProjectOnPlane(segmentDirection, upNormal);
            segmentRight *= width;
            //Vector3 offset = segmentRight * (width / 2) * scaling;
            Vector3 offset = Vector3.zero;
            Vector3 br     = segmentRight + upNormal * width + offset;
            Vector3 tr     = segmentRight + upNormal * -width + offset;
            Vector3 bl     = -segmentRight + upNormal * width + offset;
            Vector3 tl     = -segmentRight + upNormal * -width + offset;

            int curTriIdx = vertList.Count;

            Vector3[] segmentVerts = new Vector3[]
            {
                segmentStart + br,
                segmentStart + bl,
                segmentStart + tl,
                segmentStart + tr,
            };
            vertList.AddRange(segmentVerts);

            Vector2[] uvs = new Vector2[]
            {
                new Vector2(0, 0),
                new Vector2(0, 1),
                new Vector2(1, 1),
                new Vector2(1, 1)
            };
            uvList.AddRange(uvs);

            int[] segmentTriangles = new int[]
            {
                curTriIdx + 6, curTriIdx + 5, curTriIdx + 1, //left face
                curTriIdx + 1, curTriIdx + 2, curTriIdx + 6,
                curTriIdx + 7, curTriIdx + 3, curTriIdx + 0, //right face
                curTriIdx + 0, curTriIdx + 4, curTriIdx + 7,
                curTriIdx + 1, curTriIdx + 5, curTriIdx + 4, //top face
                curTriIdx + 4, curTriIdx + 0, curTriIdx + 1,
                curTriIdx + 3, curTriIdx + 7, curTriIdx + 6, //bottom face
                curTriIdx + 6, curTriIdx + 2, curTriIdx + 3
            };
            triList.AddRange(segmentTriangles);

            // final segment fenceposting: finish segment and add end face
            if (s == resolution - 1)
            {
                curTriIdx = vertList.Count;

                vertList.AddRange(new Vector3[] {
                    segmentEnd + br,
                    segmentEnd + bl,
                    segmentEnd + tl,
                    segmentEnd + tr
                });

                uvList.AddRange(new Vector2[] {
                    new Vector2(0, 0),
                    new Vector2(0, 1),
                    new Vector2(1, 1),
                    new Vector2(1, 1)
                }
                                );
                triList.AddRange(new int[] {
                    curTriIdx + 0, curTriIdx + 1, curTriIdx + 2, //end face
                    curTriIdx + 2, curTriIdx + 3, curTriIdx + 0
                });
            }
        }

        mesh.vertices  = vertList.ToArray();
        mesh.triangles = triList.ToArray();
        mesh.uv        = uvList.ToArray();
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();


        return(mesh);
    }
예제 #20
0
    public void  CreateMesh()
    {
        Mesh           mesh      = new Mesh();
        List <Vector3> vertices  = new List <Vector3>();
        List <int>     triangles = new List <int>();
        List <Vector3> normals   = new List <Vector3>();

        Vector3    Start    = spline.GetPoint(0f);
        Quaternion rotation = Quaternion.LookRotation(spline.GetVelocity(0));
        Vector3    left     = rotation * Vector3.left * width;
        Vector3    right    = rotation * Vector3.right * width;
        Vector3    up       = rotation * Vector3.up;

        vertices.Add(Start + right);
        vertices.Add(Start + left);
        normals.Add(up);
        normals.Add(up);
        int triIndex = 0;

        // higher number means smoother but also more verts/tris
        for (int i = 0; i <= size; i++)
        {
            float   t   = (float)i / (float)size;
            Vector3 End = spline.GetPoint(t);
            rotation = Quaternion.LookRotation(spline.GetVelocity(t));

            left  = rotation * Vector3.left * width;
            right = rotation * Vector3.right * width;
            up    = rotation * Vector3.up;

            vertices.Add(End + right);
            vertices.Add(End + left);
            normals.Add(up);
            normals.Add(up);

            triangles.Add(triIndex);
            triangles.Add(triIndex + 1);
            triangles.Add(triIndex + 2);

            triangles.Add(triIndex + 2);
            triangles.Add(triIndex + 1);
            triangles.Add(triIndex + 3);

            triIndex += 2;

            Start = End;
        }


        //duplicate for twosided meshes
        int szT = triangles.Count;
        int szV = vertices.Count;

        for (int k = 0; k < szV; k++)
        {
            vertices.Add(vertices[k]);
            normals.Add(normals[k]);
        }
        var newTris = new int[szT * 2]; // double the triangles

        for (int i = 0; i < szT; i += 3)
        {
            // copy the original triangle
            newTris[i]     = triangles[i];
            newTris[i + 1] = triangles[i + 1];
            newTris[i + 2] = triangles[i + 2];
            // save the new reversed triangle
            int j = i + szT;
            newTris[j]     = triangles[i] + szV;
            newTris[j + 2] = triangles[i + 1] + szV;
            newTris[j + 1] = triangles[i + 2] + szV;
        }

        Vector2[] Uvs = new Vector2[vertices.Count];
        //Set UVs
        for (int i = 0; i < vertices.Count; i++)
        {
            Uvs[i] = new Vector2(vertices[i].x, vertices[i].z);
        }

        mesh.SetVertices(vertices);
        mesh.SetNormals(normals);
        mesh.triangles = newTris;
        mesh.uv        = Uvs;
        GetComponent <MeshFilter>().mesh         = mesh;
        GetComponent <MeshCollider>().sharedMesh = mesh;
    }