Unity dynamically creates Mesh tracks

Preface

Through Bezier curve, we get many groups of curves. Now we need to draw a track on the curve.

thinking

The nodes on the curve are calculated by cross multiplication.
Cross multiplication of the first node and the next node
The middle node calculates the cross product of the previous node and the next node, and then does the mean processing
Cross multiply the last node with the previous node
The effect is as follows:


Mesh mesh drawing

The core code is as follows:

public class LineMeshCreater : MonoBehaviour
{

    public Mesh GetMesh(Vector3[] posarray, float width , Vector3 world, Vector3 nextNode = default)
    {
        Mesh mesh = new Mesh();
        DrawMesh(mesh, posarray, width , world , nextNode);
        return mesh;
    }

    /// <summary>
    //Drawing Mesh
    /// </summary>
    /// <param name="mesh"></param>
    /// <param name="posarray"></param>
    /// <param name="width"></param>
    public void DrawMesh(Mesh mesh, Vector3[] posarray, float width, Vector3 world, Vector3 nextNode = default)
    {
        mesh.Clear();
        mesh.vertices = getVertices(posarray, width , world , nextNode);
        mesh.triangles = getTriangles(mesh.vertexCount);
        mesh.RecalculateNormals();
    }

    /// <summary>
    ///Vertex calculation
    /// </summary>
    /// <returns></returns>
    Vector3[] getVertices(Vector3[] posarray, float width , Vector3 world , Vector3 nextNode = default)
    {
        Vector3[] vector3s = new Vector3[posarray.Length * 2];
        for (int i = 0; i < posarray.Length; i++)
        {
            Vector3 reght = Vector3.zero;

            if (i > 0 && i < posarray.Length - 1)
            {
                Vector3 t_l, t_r;
                t_l = t_r = Vector3.zero;
                //Cross product vector to the left of node
                getCross(posarray[i - 1] - posarray[i], world, ref t_l);
                //Cross product vector to the right of node
                getCross(posarray[i + 1] - posarray[i], world, ref t_r);
                //Mean value
                t_r = -t_r;
                reght = (t_r + t_l) / 2;
            }
            else if (i == posarray.Length - 1)
            {
                if (nextNode != Vector3.zero)
                {
                    //Cross product vector to next node
                    getCross(nextNode - posarray[i], world, ref reght);
                    reght = -reght;
                }
                else {
                    //Cross product vector to the left of node
                    getCross(posarray[i - 1] - posarray[i], world, ref reght);
                }
            }
            else
            {
                //Cross product vector to the right of node
                getCross(posarray[i + 1] - posarray[i], world, ref reght);
                reght = -reght;
            }

            //Right vertex
            vector3s[i * 2] = reght * (width / 2) + posarray[i] - posarray[0];
            //Left vertex
            vector3s[i * 2 + 1] = -reght * (width / 2) + posarray[i] - posarray[0];

            //Debug.DrawLine(vector3s[i * 2] + posarray[0], vector3s[i * 2 + 1] + posarray[0], Color.red);
        }
        return vector3s;
    }

    /// <summary>
    /// fork multiplication
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <param name="vector"></param>
    void getCross(Vector3 a, Vector3 b, ref Vector3 vector)
    {
        vector = new Vector3(
                a.y * b.z - a.z * b.y,
                a.z * b.x - a.x * b.z,
                a.x * b.y - a.y * b.x
            ).normalized;
    }

    /// <summary>
    ///Trigonometric calculation
    /// </summary>
    /// <param name="count"></param>
    /// <returns></returns>
    int[] getTriangles(int count)
    {
        List<int> vector3s = new List<int>();
        for (int i = 0; i < count - 2; i += 2)
        {
            //Lower right triangle
            int p0, p1, p2;
            p0 = i;
            p1 = i + 1;
            p2 = i + 2;
            vector3s.Add(p0);
            vector3s.Add(p1);
            vector3s.Add(p2);

            //Upper left triangle
            p0 = i + 1;
            p1 = i + 3;
            p2 = i + 2;
            vector3s.Add(p0);
            vector3s.Add(p1);
            vector3s.Add(p2);
        }
        return vector3s.ToArray();
    }

}

In addition, it should be noted that the last node of each group of curve nodes and the second node of the next group need to be cross multiplied once, so that they can be perfectly spliced without gaps.
Setting a subdivision value in the Bezier curve can make the actual track smoother, with the following effects:

Subdivision node

Posted by greyhoundcode on Tue, 26 Nov 2019 12:04:59 -0800