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;
            }
        }
    }