private float GetWorldSpaceMaxTreeHeight()
        {
            float maxTreeHeight = 0;

            if (VegetationSystem)
            {
                for (int i = 0; i <= VegetationSystem.CurrentVegetationPackage.VegetationInfoList.Count - 1; i++)
                {
                    VegetationItemInfo vegetationItemInfo = VegetationSystem.CurrentVegetationPackage.VegetationInfoList[i];
                    if (vegetationItemInfo.VegetationType == VegetationType.Tree && vegetationItemInfo.UseHeightLevel) //&& vegetationInfo.IncludeInTerrain)
                    {
                        if (vegetationItemInfo.MaximumHeight > maxTreeHeight)
                        {
                            maxTreeHeight = vegetationItemInfo.MaximumHeight;
                        }
                    }

                    if (vegetationItemInfo.VegetationType == VegetationType.Tree && !vegetationItemInfo.UseHeightLevel)// && vegetationInfo.IncludeInTerrain)
                    {
                        maxTreeHeight = VegetationSystem.UnityTerrainData.MaxTerrainHeight;
                        break;
                    }
                }
            }

            if (maxTreeHeight > VegetationSystem.UnityTerrainData.MaxTerrainHeight)
            {
                maxTreeHeight = VegetationSystem.UnityTerrainData.MaxTerrainHeight;
            }

            return(maxTreeHeight + //+ VegetationSystem.unityTerrainData.terrainPosition.y
                   VegetationSystem.GetWaterLevel());
        }
        private void UpdateBillboardClipping()
        {
            if (!VegetationSystem.InitDone)
            {
                return;
            }
            if (_vegetationItemBillboardMaterialList.Count !=
                VegetationSystem.CurrentVegetationPackage.VegetationInfoList.Count)
            {
                return;
            }

            var cullDistance = Mathf.RoundToInt(VegetationSystem.GetVegetationDistance() +
                                                VegetationSystem.GetTreeDistance() - VegetationSystem.CellSize);
            var farCullDistance = Mathf.RoundToInt(VegetationSystem.GetTotalDistance());

            for (var i = 0; i <= _vegetationItemBillboardMaterialList.Count - 1; i++)
            {
                if (_vegetationItemBillboardMaterialList[i] == null)
                {
                    continue;
                }

                if (VegetationSystem)
                {
                    VegetationItemInfo vegetationItemInfo =
                        VegetationSystem.CurrentVegetationPackage.VegetationInfoList[i];

                    _vegetationItemBillboardMaterialList[i].SetFloat("_Cutoff", vegetationItemInfo.BillboardCutoff);
                    _vegetationItemBillboardMaterialList[i].SetInt("_CullDistance", cullDistance - 1);
                    _vegetationItemBillboardMaterialList[i].SetInt("_FarCullDistance", farCullDistance);


                    _vegetationItemBillboardMaterialList[i]
                    .SetVector("_CameraPosition", VegetationSystem.GetCameraPosition());

                    if (vegetationItemInfo.ShaderType ==
                        VegetationShaderType.Speedtree)
                    {
                        Color tempColor = vegetationItemInfo.BillboardTintColor * vegetationItemInfo.ColorTint1;
                        tempColor.r = Mathf.Clamp01(tempColor.r * 1.3f);
                        tempColor.g = Mathf.Clamp01(tempColor.g * 1.3f);
                        tempColor.b = Mathf.Clamp01(tempColor.b * 1.3f);
                        _vegetationItemBillboardMaterialList[i].SetColor("_Color", tempColor);
                        _vegetationItemBillboardMaterialList[i].SetColor("_HueVariation", vegetationItemInfo.Hue);
                    }
                    else
                    {
                        _vegetationItemBillboardMaterialList[i].SetColor("_Color", vegetationItemInfo.BillboardTintColor);
                    }
                    _vegetationItemBillboardMaterialList[i].SetFloat("_Brightness", vegetationItemInfo.BillboardBrightness);
                    _vegetationItemBillboardMaterialList[i].SetFloat("_MipmapBias", vegetationItemInfo.BillboardMipmapBias);
                }
            }
        }
        public void AddVegetationCells(List <VegetationCell> vegetationCellList, Vector3 terrainPosition)
        {
            for (int i = 0; i <= BillboardMeshGeneratorList.Count - 1; i++)
            {
                VegetationItemInfo vegetationItemInfo = CurrentvegetationPackage.VegetationInfoList[i];
                if (vegetationItemInfo.VegetationType != VegetationType.Tree ||
                    !vegetationItemInfo.UseBillboards)
                {
                    continue;                                    //||!CurrentvegetationPackage.VegetationInfoList[i].IncludeInTerrain) continue;
                }
                for (int j = 0; j <= vegetationCellList.Count - 1; j++)
                {
                    //vegetationCellList[j].Preprocess();
                    //var currentVegetationList = vegetationCellList[j].GetCurrentVegetationList(i);// = new List<Matrix4x4>();
                    List <Matrix4x4> currentVegetationList;

                    //if (vegetationItemInfo.VegetationRenderType == VegetationRenderType.InstancedIndirect &&
                    //    Application.isPlaying)
                    //{
                    //    currentVegetationList = vegetationCellList[j].DirectSpawnVegetationIndirectLocalspace(vegetationItemInfo.VegetationItemID,true);



                    //}
                    //else
                    //{
                    currentVegetationList = vegetationCellList[j].DirectSpawnVegetationLocalspace(vegetationItemInfo.VegetationItemID, true);
                    //}

                    //Debug.Log("indirect" + currentVegetationList.Count.ToString());

                    if (currentVegetationList != null)
                    {
                        for (int k = 0; k <= currentVegetationList.Count - 1; k++)
                        {
                            BillboardMeshGeneratorList[i].AddQuad(currentVegetationList[k], terrainPosition, vegetationItemInfo.Bounds.extents.y);
                        }
                    }
                    //vegetationCellList[j].GetVegetationInfoList(i, returnList);
                }
            }
        }
        void AddNavMesObstacle(GameObject go, VegetationItemInfo vegetationItemInfo)
        {
            NavMeshObstacle navMeshObstacle;

            switch (vegetationItemInfo.NavMeshObstacleType)
            {
            case NavMeshObstacleType.Box:
                navMeshObstacle         = go.AddComponent <NavMeshObstacle>();
                navMeshObstacle.shape   = NavMeshObstacleShape.Box;
                navMeshObstacle.center  = vegetationItemInfo.NavMeshObstacleCenter;
                navMeshObstacle.size    = vegetationItemInfo.NavMeshObstacleSize;
                navMeshObstacle.carving = vegetationItemInfo.NavMeshObstacleCarve;
                break;

            case NavMeshObstacleType.Capsule:
                navMeshObstacle         = go.AddComponent <NavMeshObstacle>();
                navMeshObstacle.shape   = NavMeshObstacleShape.Capsule;
                navMeshObstacle.center  = vegetationItemInfo.NavMeshObstacleCenter;
                navMeshObstacle.radius  = vegetationItemInfo.NavMeshObstacleRadius;
                navMeshObstacle.height  = vegetationItemInfo.NavMeshObstacleHeight;
                navMeshObstacle.carving = vegetationItemInfo.NavMeshObstacleCarve;
                break;
            }
        }
        private void CreateBillboardMaterials()
        {
            ClearBillboardMaterials();

            for (int i = 0; i <= VegetationSystem.CurrentVegetationPackage.VegetationInfoList.Count - 1; i++)
            {
                if (VegetationSystem.CurrentVegetationPackage.VegetationInfoList[i].VegetationType ==
                    VegetationType.Tree && VegetationSystem.CurrentVegetationPackage.VegetationInfoList[i].UseBillboards)   //&& VegetationSystem.CurrentVegetationPackage.VegetationInfoList[i].IncludeInTerrain
                {
                    Material billboardMaterial =
                        new Material(Shader.Find("AwesomeTechnologies/Billboards/GroupBillboards"))
                    {
                        enableInstancing = true
                    };

                    if (OverrideRenderQueue)
                    {
                        billboardMaterial.renderQueue = RenderQueue;
                    }
                    VegetationItemInfo vegetationItemInfo =
                        VegetationSystem.CurrentVegetationPackage.VegetationInfoList[i];
                    billboardMaterial.hideFlags = HideFlags.DontSave;
                    billboardMaterial.SetTexture("_MainTex",
                                                 vegetationItemInfo.BillboardTexture);
                    billboardMaterial.SetTexture("_Bump",
                                                 vegetationItemInfo.BillboardNormalTexture);
                    billboardMaterial.SetFloat("_Cutoff", vegetationItemInfo.BillboardCutoff);
                    billboardMaterial.SetFloat("_Brightness", vegetationItemInfo.BillboardBrightness);
                    billboardMaterial.SetInt("_InRow",
                                             BillboardAtlasRenderer.GetBillboardQualityColumnCount(vegetationItemInfo
                                                                                                   .BillboardQuality));
                    billboardMaterial.SetInt("_InCol",
                                             BillboardAtlasRenderer.GetBillboardQualityRowCount(vegetationItemInfo
                                                                                                .BillboardQuality));
                    billboardMaterial.SetInt("_CullDistance", 340);
                    billboardMaterial.SetInt("_FarCullDistance", 5000);
                    billboardMaterial.SetColor("_HueVariation", new Color(1f, 0.5f, 0f, 25f / 256f));
                    billboardMaterial.SetColor("_Color", vegetationItemInfo.BillboardTintColor);
                    billboardMaterial.DisableKeyword("AT_CAMERA_SHADER");
                    billboardMaterial.EnableKeyword("AT_CAMERA_MATERIAL");

                    //billboardMaterial.EnableKeyword("LOD_FADE_CROSSFADE");

                    if (vegetationItemInfo.ShaderType ==
                        VegetationShaderType.Speedtree)
                    {
                        billboardMaterial.EnableKeyword("AT_HUE_VARIATION_ON");
                        billboardMaterial.DisableKeyword("AT_HUE_VARIATION_OFF");
                    }
                    else
                    {
                        billboardMaterial.DisableKeyword("AT_HUE_VARIATION_ON");
                        billboardMaterial.EnableKeyword("AT_HUE_VARIATION_OFF");
                    }
                    _vegetationItemBillboardMaterialList.Add(billboardMaterial);
                }
                else
                {
                    _vegetationItemBillboardMaterialList.Add(null);
                }
            }
        }
        void CreateCollider(Matrix4x4 colliderMatrix, VegetationPackage vegetationPackage, int i, int j, bool bakeNavmesh, VegetationCell vegetationCell, GameObject currentParent, VegetationItemInfo vegetationItemInfo, VegetationCellCollider vegetationCellCollider)
        {
            RuntimeObjectInfo runtimeObjectInfo;
            Vector3           vegetationItemScale;

            //TUDO add pool of colliders
            switch (vegetationPackage.VegetationInfoList[i].ColliderType)
            {
            case ColliderType.Capsule:
                GameObject capsuleColliderObject = new GameObject(vegetationCell.CellIndex + " " + vegetationPackage.VegetationInfoList[i].VegetationType + " CapsuleCollider_" + j);

                if (!bakeNavmesh)
                {
                    capsuleColliderObject.hideFlags = HideColliders ? HideFlags.HideAndDontSave : HideFlags.DontSave;
                }
                capsuleColliderObject.layer = GetColliderLayer(vegetationPackage.VegetationInfoList[i].VegetationType);

                vegetationItemScale = MatrixTools.ExtractScaleFromMatrix(colliderMatrix);

                CapsuleCollider capsuleCollider = capsuleColliderObject.AddComponent <CapsuleCollider>();
                capsuleCollider.height    = vegetationPackage.VegetationInfoList[i].ColliderHeight;
                capsuleCollider.radius    = vegetationPackage.VegetationInfoList[i].ColliderRadius;
                capsuleCollider.isTrigger =
                    vegetationPackage.VegetationInfoList[i].ColliderTrigger;
                capsuleColliderObject.transform.SetParent(currentParent.transform, false);
                capsuleColliderObject.transform.position   = MatrixTools.ExtractTranslationFromMatrix(colliderMatrix) + new Vector3(0, (capsuleCollider.height * vegetationItemScale.y) / 2f, 0);
                capsuleColliderObject.transform.rotation   = MatrixTools.ExtractRotationFromMatrix(colliderMatrix);
                capsuleColliderObject.transform.localScale = vegetationItemScale;


                Vector3 colliderOffset =
                    new Vector3(
                        capsuleColliderObject.transform.localScale.x *
                        vegetationPackage.VegetationInfoList[i].ColliderOffset.x,
                        capsuleColliderObject.transform.localScale.y *
                        vegetationPackage.VegetationInfoList[i].ColliderOffset.y,
                        capsuleColliderObject.transform.localScale.z *
                        vegetationPackage.VegetationInfoList[i].ColliderOffset.z);
                capsuleColliderObject.transform.localPosition += MatrixTools.ExtractRotationFromMatrix(colliderMatrix) * colliderOffset;

                if (!bakeNavmesh)
                {
                    AddNavMesObstacle(capsuleColliderObject, vegetationItemInfo);
                    AddVegetationItemInstanceInfo(capsuleColliderObject, colliderMatrix,
                                                  vegetationItemInfo.VegetationType,
                                                  vegetationItemInfo.VegetationItemID);
                    vegetationCellCollider.ColliderList.Add(capsuleColliderObject);
                    runtimeObjectInfo =
                        capsuleColliderObject.AddComponent <RuntimeObjectInfo>();
                    runtimeObjectInfo.VegetationItemInfo =
                        vegetationPackage.VegetationInfoList[i];
                    if (OnCreateColliderDelegate != null)
                    {
                        OnCreateColliderDelegate(capsuleCollider);
                    }
                }
                break;

            case ColliderType.Sphere:
                GameObject sphereColliderObject = new GameObject(vegetationCell.CellIndex.ToString() + " " + vegetationPackage.VegetationInfoList[i].VegetationType.ToString() + " SphereCollider_" + j.ToString());
                if (!bakeNavmesh)
                {
                    sphereColliderObject.hideFlags = HideColliders ? HideFlags.HideAndDontSave : HideFlags.DontSave;
                }

                sphereColliderObject.layer = GetColliderLayer(vegetationPackage.VegetationInfoList[i].VegetationType);

                vegetationItemScale = MatrixTools.ExtractScaleFromMatrix(colliderMatrix);

                SphereCollider sphereCollider = sphereColliderObject.AddComponent <SphereCollider>();
                sphereCollider.radius    = vegetationPackage.VegetationInfoList[i].ColliderRadius;
                sphereCollider.isTrigger =
                    vegetationPackage.VegetationInfoList[i].ColliderTrigger;
                sphereColliderObject.transform.SetParent(currentParent.transform, false);
                sphereColliderObject.transform.position =
                    MatrixTools.ExtractTranslationFromMatrix(colliderMatrix);    // + vegetationPackage.VegetationInfoList[i].ColliderOffset;
                sphereColliderObject.transform.rotation   = MatrixTools.ExtractRotationFromMatrix(colliderMatrix);
                sphereColliderObject.transform.localScale = vegetationItemScale;

                Vector3 sphereColliderOffset =
                    new Vector3(
                        sphereColliderObject.transform.localScale.x *
                        vegetationPackage.VegetationInfoList[i].ColliderOffset.x,
                        sphereColliderObject.transform.localScale.y *
                        vegetationPackage.VegetationInfoList[i].ColliderOffset.y,
                        sphereColliderObject.transform.localScale.z *
                        vegetationPackage.VegetationInfoList[i].ColliderOffset.z);
                sphereColliderObject.transform.localPosition += MatrixTools.ExtractRotationFromMatrix(colliderMatrix) * sphereColliderOffset;

                if (!bakeNavmesh)
                {
                    AddNavMesObstacle(sphereColliderObject, vegetationItemInfo);
                    AddVegetationItemInstanceInfo(sphereColliderObject, colliderMatrix,
                                                  vegetationItemInfo.VegetationType,
                                                  vegetationItemInfo.VegetationItemID);
                    vegetationCellCollider.ColliderList.Add(sphereColliderObject);
                    runtimeObjectInfo =
                        sphereColliderObject.AddComponent <RuntimeObjectInfo>();
                    runtimeObjectInfo.VegetationItemInfo =
                        vegetationPackage.VegetationInfoList[i];
                    if (OnCreateColliderDelegate != null)
                    {
                        OnCreateColliderDelegate(sphereCollider);
                    }
                }

                break;

            case ColliderType.CustomMesh:
            case ColliderType.Mesh:
                GameObject meshColliderObject = new GameObject(vegetationCell.CellIndex.ToString() + " " + vegetationPackage.VegetationInfoList[i].VegetationType.ToString() + " MeshCollider_" + j.ToString());
                if (!bakeNavmesh)
                {
                    meshColliderObject.hideFlags = HideColliders ? HideFlags.HideAndDontSave : HideFlags.DontSave;
                }
                meshColliderObject.layer = GetColliderLayer(vegetationPackage.VegetationInfoList[i].VegetationType);
                MeshCollider            meshCollider            = meshColliderObject.AddComponent <MeshCollider>();
                VegetationItemModelInfo vegetationItemModelInfo = VegetationSystem.GetVegetationModelInfo(i);
                meshCollider.sharedMesh = vegetationItemInfo.ColliderType == ColliderType.CustomMesh ? vegetationItemInfo.ColliderMesh : vegetationItemModelInfo.VegetationMeshLod0;

                meshColliderObject.transform.SetParent(currentParent.transform, false);
                meshColliderObject.transform.position =
                    MatrixTools.ExtractTranslationFromMatrix(colliderMatrix);// + vegetationPackage.VegetationInfoList[i].ColliderOffset;
                meshColliderObject.transform.rotation   = MatrixTools.ExtractRotationFromMatrix(colliderMatrix);
                meshColliderObject.transform.localScale = MatrixTools.ExtractScaleFromMatrix(colliderMatrix);

                if (!bakeNavmesh)
                {
                    AddNavMesObstacle(meshColliderObject, vegetationItemInfo);
                    AddVegetationItemInstanceInfo(meshColliderObject, colliderMatrix,
                                                  vegetationItemInfo.VegetationType,
                                                  vegetationItemInfo.VegetationItemID);
                    vegetationCellCollider.ColliderList.Add(meshColliderObject);
                    runtimeObjectInfo = meshColliderObject.AddComponent <RuntimeObjectInfo>();
                    runtimeObjectInfo.VegetationItemInfo = vegetationPackage.VegetationInfoList[i];
                    if (OnCreateColliderDelegate != null)
                    {
                        OnCreateColliderDelegate(meshCollider);
                    }
                }
                break;
            }
        }
        private void AddVegetationCellCollider(VegetationCell vegetationCell, GameObject parentGameObject = null,
                                               bool bakeNavmesh = false)
        {
            vegetationCell.OnSpawnVegetationDelegate += OnSpawnVegetation;

            GameObject currentParent = ColliderParent;

            if (bakeNavmesh && parentGameObject != null)
            {
                currentParent = parentGameObject;
            }

            VegetationCellCollider vegetationCellCollider =
                new VegetationCellCollider {
                VegetationCell = vegetationCell
            };

            VegetationPackage vegetationPackage = VegetationSystem.CurrentVegetationPackage;

            int colliderCount = 0;

            if (vegetationCell.InitDone)
            {
                for (int i = 0; i <= vegetationPackage.VegetationInfoList.Count - 1; i++)
                {
                    VegetationItemInfo vegetationItemInfo = vegetationPackage.VegetationInfoList[i];
                    if (bakeNavmesh && !vegetationItemInfo.ColliderUseForBake)
                    {
                        continue;
                    }

                    if (vegetationPackage.VegetationInfoList[i].ColliderType != ColliderType.Disabled)
                    {
                        if (vegetationPackage.VegetationInfoList[i].VegetationType == VegetationType.Tree ||
                            vegetationPackage.VegetationInfoList[i].VegetationType == VegetationType.Objects ||
                            vegetationPackage.VegetationInfoList[i].VegetationType == VegetationType.LargeObjects)
                        {
                            if (vegetationItemInfo.VegetationRenderType == VegetationRenderType.InstancedIndirect && Application.isPlaying)
                            {
                                CustomList <Matrix4x4> currentVegetationList;
                                if (bakeNavmesh)
                                {
                                    currentVegetationList = vegetationCell.DirectSpawnVegetationIndirect(vegetationItemInfo.VegetationItemID, true);
                                }
                                else
                                {
                                    currentVegetationList = vegetationCell.GetCurrentIndirectVegetationList(i);
                                }

                                if (currentVegetationList != null)
                                {
                                    colliderCount += currentVegetationList.Count;

                                    for (int j = 0; j <= currentVegetationList.Count - 1; j++)
                                    {
                                        Matrix4x4 colliderMatrix = currentVegetationList[j];
                                        CreateCollider(colliderMatrix, vegetationPackage, i, j, bakeNavmesh, vegetationCell,
                                                       currentParent, vegetationItemInfo, vegetationCellCollider);
                                    }
                                }
                            }
                            else
                            {
                                List <Matrix4x4> currentVegetationList;
                                if (bakeNavmesh)
                                {
                                    currentVegetationList = vegetationCell.DirectSpawnVegetation(vegetationItemInfo.VegetationItemID, true);
                                }
                                else
                                {
                                    currentVegetationList = vegetationCell.GetCurrentVegetationList(i);
                                }

                                if (currentVegetationList != null)
                                {
                                    colliderCount += currentVegetationList.Count;

                                    for (int j = 0; j <= currentVegetationList.Count - 1; j++)
                                    {
                                        Matrix4x4 colliderMatrix = currentVegetationList[j];
                                        CreateCollider(colliderMatrix, vegetationPackage, i, j, bakeNavmesh, vegetationCell,
                                                       currentParent, vegetationItemInfo, vegetationCellCollider);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (!bakeNavmesh)
            {
                vegetationCellCollider.ColliderCount = colliderCount;
                _vegetationCellColliderList.Add(vegetationCellCollider);
            }
        }