Beispiel #1
0
        /// <summary>
        /// Remove Grass Map Globally
        /// </summary>
        /// <param name="id"></param>
        public static void RemoveGrassMap(FoliagePrototype prototype)
        {
            if (instance == null)
            {
                return;
            }

            var chunks = instance.sector.foliageChunks;
            FoliageCore_Chunk chunk;

            FoliageManagerInstance mInstance;

            for (int i = 0; i < chunks.Count; i++)
            {
                chunk = chunks[i];

                if (!chunk.isFoliageInstanceAttached)
                {
                    continue;                                   // if no manager instance attached then there's nothing to remove!.
                }
                mInstance = chunk.GetOrCreateFoliageManagerInstance();

                mInstance.RemoveGrassMap(prototype);
            }
        }
        /// <summary>
        /// Create Foliage mesh instances for a certain index and foliage size.
        /// </summary>
        /// <param name="meshInstances"></param>
        /// <param name="prototypeIndex"></param>
        public static void GenerateFoliageMeshInstanceForIndex(int prototypeIndex, FoliageResolutions resolution)
        {
            Dictionary <int, GPUMesh> meshInstances = prototypeMeshInstances[resolution];

            FoliagePrototype prototype = FoliageDB.sortedPrototypes[prototypeIndex];

            if (!FoliageCore_MainManager.instance.enabled)
            {
                return;
            }

            bool prototypeMeshExists = prototypeMeshInstances != null && meshInstances.ContainsKey(prototypeIndex);

            if (prototypeMeshExists)
            {
                meshInstances[prototypeIndex].Destroy();
                meshInstances.Remove(prototypeIndex);
            }

            Mesh[] meshes    = new Mesh[prototype.meshLodsCount];
            int[]  densities = new int[prototype.meshLodsCount];
            List <UNPhysicsTemplate>[] physicsObjects = new List <UNPhysicsTemplate> [prototype.meshLodsCount];

            for (int i = 0; i < prototype.meshLodsCount; i++)
            {
                meshes[i]    = CreateNewMesh();
                densities[i] = Mathf.FloorToInt((float)prototype.maxGeneratedDensity / (i + 1));

                FoliageMeshInstance.CreateGPUMesh(prototype, meshes[i], densities[i]);
            }
            meshInstances.Add(prototypeIndex, new GPUMesh(meshes, densities, prototypeIndex, physicsObjects, resolution));
        }
        private void DebugPrototypeInformation(int prototypeID)
        {
            FoliagePrototype prototype = FoliageDB.sortedPrototypes[prototypeID];

            GUILayout.Label(string.Format("{0} (ID: {1})", prototype.name, prototypeID), UNStandaloneUtility.boldLabel);

            GUILayout.Space(5);

            UNStandaloneUtility.BeginHorizontalOffset(25);

            GUILayout.Label("GPU Generated Density: " + prototype.maxGeneratedDensity);
            GUILayout.Label("Generation Radius: " + prototype.FoliageGenerationRadius.ToString().Replace("_", "")); //show radius and remove the "_" character.

            GUILayout.Label(string.Format("Width Noise: {0} ~ {1}", System.Math.Round(prototype.minimumWidth, 2), System.Math.Round(prototype.maximumWidth, 2)));
            GUILayout.Label(string.Format("Height Noise: {0} ~ {1}", System.Math.Round(prototype.minimumHeight, 2), System.Math.Round(prototype.maximumHeight, 2)));

            GUILayout.Space(5);

            GUILayout.Label("Wind:");

            UNStandaloneUtility.BeginHorizontalOffset(25);

            GUILayout.Label("Individual Wind: " + prototype.useCustomWind);
            GUILayout.Label("Wind Bending: " + (prototype.useCustomWind == false ? FoliageDB.instance.globalWindSettings.windBending : prototype.customWindSettings.windBending));
            GUILayout.Label("Wind Speed: " + (prototype.useCustomWind == false ? FoliageDB.instance.globalWindSettings.windSpeed : prototype.customWindSettings.windSpeed));

            UNStandaloneUtility.EndHorizontalOffset();

            UNStandaloneUtility.EndHorizontalOffset();
        }
Beispiel #4
0
        internal void Destroy()
        {
            _currentChunk = null;

            prototype = null;

            System.GC.SuppressFinalize(this);
        }
Beispiel #5
0
        /// <summary>
        /// Register a new prototype.
        /// </summary>
        /// <param name="prototype"></param>
        internal void RegisterNewPrototype(FoliagePrototype prototype)
        {
            _prototypes.Add(prototype);

            if (!sortedPrototypes.ContainsKey(prototype.id))
            {
                sortedPrototypes.Add(prototype.id, prototype);
            }
        }
Beispiel #6
0
        public static FoliageMeshInstance CreateFoliageMesh(FoliagePrototype prototype, Vector3 position, int maxInstancesPerMesh)
        {
            FoliageMeshInstance instance = new FoliageMeshInstance();

            instance.prototype           = prototype;
            instance.position            = position;
            instance.maxInstancesPerMesh = maxInstancesPerMesh;

            return(instance);
        }
Beispiel #7
0
        public void RemoveGrassMap(FoliagePrototype prototype)
        {
            if (grassMaps.ContainsKey(prototype))
            {
                FoliageGrassMap grassMap = grassMaps[prototype];

                grassMaps.Remove(prototype);

                #if UNITY_EDITOR
                grassMap.Dispose();
                #endif
            }
        }
Beispiel #8
0
 /// <summary>
 /// Called when the enable state of a prototype is changed
 /// </summary>
 /// <param name="changedPrototype"></param>
 /// <param name="value"></param>
 private void OnFoliagePrototypeChanged(FoliagePrototype changedPrototype, bool value)
 {
     if (value)
     {
         foreach (var meshInstances in prototypeMeshInstances)
         {
             GenerateFoliageMeshInstanceForIndex(changedPrototype.id, meshInstances.Key);
         }
     }
     else
     {
         DestroyMeshInstance(changedPrototype.id);
     }
 }
Beispiel #9
0
        /// <summary>
        /// Create a prototype.
        /// </summary>
        /// <param name="texture"></param>
        /// <param name="prefab"></param>
        /// <param name="minSize"></param>
        /// <param name="maxSize"></param>
        /// <param name="spread"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static FoliagePrototype CreatePrototype(Texture2D texture, GameObject prefab, float minWidth, float minHeight, float maxWidth, float maxHeight, float spread, int layer, int id, Color healthyColor, Color dryColor)
        {
            FoliagePrototype prototype = new FoliagePrototype(texture, prefab, minWidth, minHeight, maxWidth, maxHeight, spread, layer, id);

            FoliageDB.instance.RegisterNewPrototype(prototype);

            prototype.GenerateInstantiatedMesh(healthyColor, dryColor);

            prototype.instancedEuler       = prototype.FoliageInstancedMeshData.eulerAngles;
            prototype.maxFoliageCapability = prototype.CalculateMaxFoliageCapability();
            prototype.UpdateManagerInformation();

            FoliageCore_MainManager.UpdateGrassMap();

            return(prototype);
        }
Beispiel #10
0
        /// <summary>
        /// Calculate the amount of permitted mesh instances per mesh.
        /// </summary>
        /// <param name="prototype"></param>
        /// <returns></returns>
        private static int CalculatePerMeshInstances(FoliagePrototype prototype, int generatableDensity)
        {
            int maxInstancesDensed = Mathf.FloorToInt(Mathf.Sqrt((float)prototype.maxFoliageCapability / generatableDensity));

            float flooredChunkSize = (int)FoliageCore_MainManager.instance.instancesSectorChunkSize;

            for (int i = maxInstancesDensed; i > 0; i--)
            {
                if (((flooredChunkSize / i) % 1) == 0)
                {
                    return(i);
                }
            }

            return(maxInstancesDensed);
        }
Beispiel #11
0
        /// <summary>
        /// Remove an existing Foliage prototype.
        /// </summary>
        public void RemovePrototype(FoliagePrototype prototype)
        {
            _prototypes.Remove(prototype);
            sortedPrototypes.Remove(prototype.id);

            FoliageCore_MainManager.DestroyMeshInstance(prototype.id);
            FoliageCore_MainManager.RemoveGrassMap(prototype);

            #if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                UnityEditor.EditorUtility.SetDirty(this);
            }
            #endif

            FoliageChunk.OnPrototypeDeleted(prototype.id);

            System.GC.SuppressFinalize(prototype);
        }
Beispiel #12
0
        /// <summary>
        /// Add a new Foliage prototype.
        /// </summary>
        public void AddPrototype(Texture2D texture, GameObject prefab, float minWidth, float minHeight, float maxWidth, float maxHeight, float spread, int layer, Color healthyColor, Color dryColor)
        {
            int id = lastID;

            FoliagePrototype.CreatePrototype(texture, prefab, minWidth, minHeight, maxWidth, maxHeight, spread, layer, id, healthyColor, dryColor);

            FoliageCore_MainManager.GenerateFoliageMeshInstances(id);

            FoliageChunk.OnPrototypeCreated(id);

            #if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                UnityEditor.EditorUtility.SetDirty(this);
            }
            #endif

            lastID++;
        }
Beispiel #13
0
        public static FoliageMeshInstancesGroup CreateFoliageInstances(int prototypeIndex, int density, FoliageResolutions resolution)
        {
            float resMultiplier = (float)resolution / FoliageCore_MainManager.FOLIAGE_INSTANCE_AREA_SIZE;

            FoliagePrototype prototype = FoliageDB.sortedPrototypes[prototypeIndex];

            int maxGenerationInstancesPerMesh = (int)(CalculatePerMeshInstances(prototype, density) / resMultiplier);

            int generationAmountPerRadius = GENERATION_AMOUNT_PER_RADIUS(maxGenerationInstancesPerMesh);

            FoliageMeshInstancesGroup meshGroup = new FoliageMeshInstancesGroup();

            Vector3 position;

            int gAmountX = generationAmountPerRadius - (int)prototype.meshInstancesGenerationOffset.x;

            if (gAmountX == 0)
            {
                gAmountX = 1;                // dont clamp, it can be minus
            }
            int gAmountZ = generationAmountPerRadius - (int)prototype.meshInstancesGenerationOffset.y;

            if (gAmountZ == 0)
            {
                gAmountZ = 1;                // dont clamp, it can be minus
            }
            for (int x = 0; x < gAmountX; x++)
            {
                for (int z = 0; z < gAmountZ; z++)
                {
                    position = new Vector3(z * maxGenerationInstancesPerMesh, 0, x * maxGenerationInstancesPerMesh);

                    meshGroup.AddMeshInstance(FoliageMeshInstance.CreateFoliageMesh(prototype, position, maxGenerationInstancesPerMesh));
                }
            }

            return(meshGroup);
        }
Beispiel #14
0
        internal void DrawAndUpdate(Vector3 position, Mesh mesh, Material mat, Camera camera, Vector3 cameraPos, FoliagePrototype prototype, MaterialPropertyBlock matBlock, bool useQualitySettingsShadows, float shadowDistance)
        {
            ShadowCastingMode castMode = prototype.castShadows && (camera == null || (useQualitySettingsShadows || Vector3.Distance(position, cameraPos) < shadowDistance)) ? ShadowCastingMode.On : ShadowCastingMode.Off;

            Graphics.DrawMesh(mesh, GENERATION_OPTIMIZATION_PRE_GENERATED_VECTOR3_ZERO, GENERATION_OPTIMIZATION_PRE_GENERATED_QUATERNION_IDENTITY, mat, prototype.renderingLayer, camera, 0, matBlock, castMode, prototype.receiveShadows, null);
        }
Beispiel #15
0
        public static void CreateGPUMesh(FoliagePrototype prototype, Mesh mesh, int density)
        {
            int currentValues = 0;

            List <UNCombineInstance> combineInstances = new List <UNCombineInstance>();
            UNCombineInstance        instance;

            int maxPerMeshInstances = CalculatePerMeshInstances(prototype, density);

            float rndX;
            float rndZ;

            Vector3 position;

            for (int x = 0; x < maxPerMeshInstances; x++)
            {
                for (int z = 0; z < maxPerMeshInstances; z++)
                {
                    currentValues++;

                    position.x = x;
                    position.y = prototype.FoliageInstancedMeshData.offset.y;
                    position.z = z;

                    for (int densityIndex = 1; densityIndex <= density; densityIndex++)
                    {
                        rndX = Random.Range(-1f, 1f);
                        rndZ = Random.Range(-1f, 1f);

                        for (int i = 0; i < prototype.FoliageInstancedMeshData.meshes.Length; i++)
                        {
                            instance = new UNCombineInstance()
                            {
                                mesh      = prototype.FoliageInstancedMeshData.meshes[i],
                                transform = Matrix4x4.TRS(position, Quaternion.identity, Vector3.one),

                                densityOfffset = new Vector2(rndX, rndZ),

                                density = densityIndex
                            };

                            combineInstances.Add(instance);
                        }

                        //physicsObjects.Add(new UNPhysicsTemplate(position, rndX, rndZ, densityIndex, prototype));
                    }

                    if (currentValues >= prototype.maxFoliageCapability)
                    {
                        break;
                    }
                }

                if (currentValues >= prototype.maxFoliageCapability)
                {
                    break;
                }
            }

            Utility.UNBatchUtility.CombineMeshes(combineInstances, prototype.FoliageInstancedMeshData.mat, mesh, prototype, false, 0, true, null);

            mesh.name = string.Format("uNature Mesh ({0}) ({1})", density, mesh.vertexCount);

            mesh.bounds = FoliageCore_MainManager.FOLIAGE_MAIN_AREA_BOUNDS;
        }
Beispiel #16
0
 public static int GENERATION_RANGE_OFFSET(FoliagePrototype prototype)
 {
     return(Mathf.Abs(1 - Mathf.CeilToInt(((float)prototype.FoliageGenerationRadius / 2)))); // from 3 -> 1
 }