// fill a mesh object with triangle data.
    public static void RebuildTreeMesh(TetrahedronTreeNode tree, Mesh mesh)
    {
        List <Vector3> vertices = new List <Vector3>();
        List <Vector3> normals  = new List <Vector3>();
        List <Vector2> uvs      = new List <Vector2>();
        List <int>     indices  = new List <int>();

        int vCount = 0;

        CreateMeshData(tree, vertices, normals, uvs, indices, ref vCount);
        mesh.Clear();
        mesh.SetVertices(vertices);
        mesh.SetNormals(normals);
        mesh.SetUVs(0, uvs);
        mesh.SetTriangles(indices, 0);
        mesh.UploadMeshData(false);
    }
    // create tree and build mesh
    public void CreateTree()
    {
        tree = new TetrahedronTreeNode(
            new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(0, 0, 1),
            new Vector3(0.25f, 1, 0.25f));

        if (randomSeed)
        {
            seed = Random.Range(int.MinValue, int.MaxValue);
        }

        Random.InitState(seed);
        TetrahedronTreeGenerator.GenerateTree(tree, maxDepth);
        RebuildTreeMesh(tree, mesh);
    }
    void DrawNodeGizmo(TetrahedronTreeNode node)
    {
        if (node == null)
        {
            return;
        }

        for (int i = 0; i < 3; i++)
        {
            Vector3 n   = node.GetFaceNormal(i);
            Vector3 avg = node.GetFaceAvg(i);
            Gizmos.DrawLine(avg, avg + n * 0.1f);

            DrawNodeGizmo(node.children[i]);
        }

        for (int i = 0; i < 4; i++)
        {
            Vector3 v = node.vertices[i];
            Gizmos.DrawSphere(v, 0.01f);
        }
    }
    public static void GenerateTree(TetrahedronTreeNode node, int maxDepth)
    {
        float chance = BranchChance(node);

        if (maxDepth <= 0)
        {
            return;
        }

        // for each face of this node
        for (int i = 0; i < 3; i++)
        {
            // determine if we should branch or not
            if (i == 0 || Random.value < chance)
            {
                // start a new branch by creating a new TetTreeNode
                // get vertices of base face
                Vector3[] verts = node.GetFace(i);

                // determine the position of the last vertex -and the overall shape- for the new tetrahedron.
                // (this to a large extend determines how the final tree will look like)
                Vector3 basepos = node.GetFaceAvg(i);
                Vector3 dir     = BranchLength(node) * (node.dir + node.GetFaceNormal(i));
                float   maxDev  = BranchMaxDeviation(node);
                // rotate direction vector some random amount
                Quaternion rot = Quaternion.Euler(Random.value * maxDev, Random.value * maxDev, Random.value * maxDev);
                dir = rot * dir;
                // apply upwards tendency, because we want this to look like a tree and not a shrubbery.
                dir.y += BranchUpwardsStrength(node);
                Vector3 d = basepos + dir;

                // create the new tree node and continue generating
                TetrahedronTreeNode child = new TetrahedronTreeNode(verts[2], verts[1], verts[0], d);
                node.children[i] = child;
                GenerateTree(child, maxDepth - 1);
            }
        }
    }
    // Creates triangle mesh data for the specified node and its children by filling the given lists with triangle data.
    private static void CreateMeshData(TetrahedronTreeNode node, List <Vector3> vertices, List <Vector3> normals, List <Vector2> uvs, List <int> indices, ref int vCount)
    {
        for (int i = 0; i < 3; i++)
        {
            TetrahedronTreeNode child = node.children[i];
            if (child != null)
            {
                CreateMeshData(child, vertices, normals, uvs, indices, ref vCount);
            }
            else
            {
                // This triangle face does not have a child treenode, so let's draw it
                Vector3[] faceverts = node.GetFace(i);
                vertices.Add(faceverts[0]);
                vertices.Add(faceverts[1]);
                vertices.Add(faceverts[2]);

                Vector3 n = node.GetFaceNormal(i);
                normals.Add(n);
                normals.Add(n);
                normals.Add(n);

                // let's not care too much about uvs right now, so set it to zero.
                // Maybe later, if we decide to do texturing mapping or other stuff.
                Vector2 uv = Vector2.zero;
                uvs.Add(uv);
                uvs.Add(uv);
                uvs.Add(uv);

                indices.Add(vCount + 0);
                indices.Add(vCount + 1);
                indices.Add(vCount + 2);
                vCount = vCount + 3;
            }
        }
    }
 private static float BranchUpwardsStrength(TetrahedronTreeNode node)
 {
     return(Mathf.Clamp01(-0.5f * node.basepos.y + 1));
 }
 private static float BranchMaxDeviation(TetrahedronTreeNode node)
 {
     return(10f * 0.1f * node.basepos.y);
 }
 private static float BranchLength(TetrahedronTreeNode node)
 {
     return(1);
 }
 private static float BranchChance(TetrahedronTreeNode node)
 {
     return(0.075f * node.basepos.y);
 }