public void RequestTree(TreeData treeData, Vector3 Pos, Action <GameObject> callback)
        {
            if (ThreadsAlive.Count >= MaxThreads)
            {
                ThreadMethodsToStart.Enqueue(() => RequestTree(treeData, Pos, callback));
                return;
            }

            TreeThreadReturnData ReturnData = new TreeThreadReturnData();

            treeData.Setup();
            ReturnData.TreePos          = Pos;
            ReturnData.TreeData         = treeData;
            ReturnData.ManagerCallBack  = ManagerCallBack;
            ReturnData.OriginalCallBack = callback;


            Thread t = new Thread(delegate()
            {
                TreeGenerator.Build(ReturnData);
            });

            t.IsBackground = true;
            t.Start();
            ThreadsAlive.Add(t);
        }
 public void ManagerCallBack(TreeThreadReturnData returndata)
 {
     lock (TreesToBeBuilt)
     {
         TreesToBeBuilt.Enqueue(returndata);
     }
 }
        private void BuildTree(TreeThreadReturnData ReturnData)
        {
            MeshObjectData TreeBuildData = ReturnData.TreeBuildData;
            Mesh           TreeMesh      = TreeBuildData.ToMesh();

            TreeMesh.RecalculateBounds();
            TreeMesh.RecalculateNormals();

            string     ObjectName = ReturnData.TreeData.TreeName != null && ReturnData.TreeData.TreeName != "" ? ReturnData.TreeData.TreeName : "Woah!, Some kind of random Tree";
            GameObject treeObject = new GameObject(ObjectName);

            treeObject.AddComponent <MeshFilter>().mesh = TreeMesh;
            treeObject.AddComponent <MeshRenderer>();
            Material mat = new Material(vertexShader);

            mat.SetFloat("_Smoothness", 0f);
            treeObject.GetComponent <Renderer>().material = mat;
            MeshObjectData[] PlantBuildData = ReturnData.FoliagesBuildData;

            for (int i = 0; i < PlantBuildData.Length; i++)
            {
                Mesh plantMesh = PlantBuildData[i].ToMesh();
                plantMesh.RecalculateBounds();
                plantMesh.RecalculateNormals();

                GameObject Foliage = new GameObject("Foliage");
                Foliage.AddComponent <MeshFilter>().mesh = plantMesh;
                Foliage.AddComponent <MeshRenderer>();
                Foliage.GetComponent <Renderer>().material = new Material(mat);
                UnityEngine.Random.InitState(ReturnData.TreeData.TreeSeed + i);
                Foliage.transform.localScale *= UnityEngine.Random.Range(ReturnData.TreeData.foliageScaleMin, ReturnData.TreeData.foliageScaleMax);
                Foliage.transform.position    = PlantBuildData[i].position;
                Foliage.transform.SetParent(treeObject.transform);
            }

            treeObject.transform.position = TreeBuildData.position;

            ReturnData.OriginalCallBack(treeObject);
        }
        public static void Build(TreeThreadReturnData ReturnData)
        {
            TreeData data = ReturnData.TreeData;

            var root = new TreeBranch(
                data.generations,
                data.length,
                data.radius,
                data
                );

            var vertices  = new List <Vector3>();
            var normals   = new List <Vector3>();
            var tangents  = new List <Vector4>();
            var uvs       = new List <Vector2>();
            var triangles = new List <int>();

            List <MeshObjectData> Foliages = new List <MeshObjectData>();

            Rand rand;
            int  FolCheckCount = 0;

            float maxLength = TraverseMaxLength(root);

            Traverse(root, (branch) =>
            {
                var offset = vertices.Count;

                var vOffset = branch.Offset / maxLength;
                var vLength = branch.Length / maxLength;

                for (int i = 0, n = branch.Segments.Count; i < n; i++)
                {
                    var t = 1f * i / (n - 1);
                    var v = vOffset + vLength * t;

                    var segment = branch.Segments[i];
                    var N       = segment.Frame.Normal;
                    var B       = segment.Frame.Binormal;
                    for (int j = 0; j <= data.radialSegments; j++)
                    {
                        // 0.0 ~ 2π
                        var u     = 1f * j / data.radialSegments;
                        float rad = u * PI2;

                        float cos  = Mathf.Cos(rad), sin = Mathf.Sin(rad);
                        var normal = (cos * N + sin * B).normalized;
                        vertices.Add(segment.Position + segment.Radius * normal);
                        normals.Add(normal);

                        var tangent = segment.Frame.Tangent;
                        tangents.Add(new Vector4(tangent.x, tangent.y, tangent.z, 0f));

                        uvs.Add(new Vector2(u, v));
                    }
                }

                for (int j = 1; j <= data.heightSegments; j++)
                {
                    for (int i = 1; i <= data.radialSegments; i++)
                    {
                        int a = (data.radialSegments + 1) * (j - 1) + (i - 1);
                        int b = (data.radialSegments + 1) * j + (i - 1);
                        int c = (data.radialSegments + 1) * j + i;
                        int d = (data.radialSegments + 1) * (j - 1) + i;

                        a += offset;
                        b += offset;
                        c += offset;
                        d += offset;

                        triangles.Add(a); triangles.Add(d); triangles.Add(b);
                        triangles.Add(b); triangles.Add(d); triangles.Add(c);
                    }
                }

                //plants
                if (branch.Children == null || branch.Children.Count == 0)
                {
                    rand         = new Rand(FolCheckCount + data.TreeSeed);
                    float chance = rand.Range(0f, 100f);
                    Debug.Log(chance);
                    if (chance <= data.foliageChance)
                    {
                        Foliages.Add(CreateFoliage(data, branch, Foliages.Count + FolCheckCount));
                    }
                    FolCheckCount++;
                }
            });

            MeshObjectData TreeMeshData = new MeshObjectData();

            TreeMeshData.vertices  = vertices.ToArray();
            TreeMeshData.triangles = triangles.ToArray();
            TreeMeshData.position  = ReturnData.TreePos;

            TreeMeshData.flatShade();

            Color[] treecolor = new Color[TreeMeshData.vertices.Length];

            for (int i = 0; i < TreeMeshData.vertices.Length; i++)
            {
                treecolor[i] = data.branchColor;
            }

            TreeMeshData.colors = treecolor;

            ReturnData.TreeBuildData = TreeMeshData;

            ReturnData.FoliagesBuildData = Foliages.ToArray();
            ReturnData.ManagerCallBack(ReturnData);
        }