Exemplo n.º 1
0
        public override void Apply(ProceduralLayer layer, TerrainWrapper wrapper)
        {
            var trees    = wrapper.CompoundTerrainData.Trees;
            var tSize    = wrapper.Terrain.terrainData.size;
            var terrainY = wrapper.transform.position.y;

            HashSet <string> removed = new HashSet <string>();

            foreach (var treePair in trees)
            {
                var wPos   = wrapper.Terrain.TreeToWorldPos(treePair.Value.Position);
                var height = wrapper.GetCompoundHeight(null, wPos) * tSize.y;
                wPos.y = terrainY + treePair.Value.Position.y + height;

                RaycastHit hit;
                if (Physics.Raycast(wPos + Vector3.up * 500, Vector3.down, out hit, 500, Mask) && ((hit.point - wPos).magnitude > Distance))
                {
                    removed.Add(treePair.Key);
                }
            }
            layer.TreeRemovals = removed.ToList();
            foreach (var treeRemoval in layer.TreeRemovals)
            {
                trees.Remove(treeRemoval);
            }

            Debug.Log(string.Format("TreeRaycast deleted {0} trees", layer.TreeRemovals.Count));
            wrapper.FinaliseTrees();
            MiscUtilities.ClearProgressBar();
        }
Exemplo n.º 2
0
 private void OnFrameAfterPostFinalise(TerrainWrapper wrapper)
 {
     if (!Enabled)
     {
         return;
     }
     for (int i = 0; i < Components.Count; i++)
     {
         var proceduralLayerComponent = Components[i];
         if (!proceduralLayerComponent.Enabled)
         {
             continue;
         }
         if (proceduralLayerComponent.Timing == ProceduralLayerComponent.ApplyTiming.OnFrameAfterPostFinalise)
         {
             MiscUtilities.ProgressBar(
                 string.Format("Procedural Layer {0}: Processing {1}", name, proceduralLayerComponent.GetType()),
                 string.Format("{0}/{1}", i + 1, Components.Count), i / (float)Components.Count);
             proceduralLayerComponent.Apply(this, wrapper);
         }
     }
     MiscUtilities.ClearProgressBar();
 }
        /// <summary>
        /// TODO: This is a very complicated method. Is there a way to move towards componentisation?
        /// TODO: Layer filter method should be able to include/exclude arbitrary numbers of layers (currently it is all or one)
        /// Generally it doesn't make sense to apply only one component for a given layer. While partial recalculation
        /// might be possible, it doesn't currently exist. So when we recalcualte one component on a layer, we also
        /// recalculate all other Components on that layer.
        /// </summary>
        /// <param name="wrapper">The wrapper to recalculate the Components for</param>
        /// <param name="layerFilter">A name filter for the layers (for recalculating a single layer)</param>
        public static void ApplyAllLayerComponents(TerrainWrapper wrapper, string layerFilter = null)
        {
            Profiler.BeginSample("ApplyallLayerComponents");

            var mappings = SortComponents(wrapper, layerFilter);

            for (int i = 0; i < mappings.Count; i++)
            {
                var layerStampMapping = mappings[i];
                for (int j = 0; j < layerStampMapping.Components.Count; j++)
                {
                    MiscUtilities.ProgressBar(String.Format("PreBake for Component {0}", layerStampMapping.Components[j].name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count);
                    layerStampMapping.Components[j].OnPreBake();
                }
            }

            mappings = SortComponents(wrapper, layerFilter);
            if (wrapper.Locked)
            {
                Debug.LogWarning(string.Format("Attempted to write to Terrain Wrapper {0} but it was locked.", wrapper.name), wrapper);
            }
            else
            {
                bool anyLayerWrittenTo = false;
                // Okay, we've organised our Components in such a way so we can iterate through and execute them.
                // Iterating the mappings here is equivalent to iterating through the TerrainWrapper layers and executing all the relevant Components for each layer.
                for (int i = 0; i < mappings.Count; i++)
                {
                    var layerStampMapping = mappings[i];
                    var layer             = wrapper.GetLayer <MMTerrainLayer>(layerStampMapping.LayerName, false, true); // Is this redundant or just cautious? See line 100

                    // Here, we copy the flattened information of all layers below this layer to the current layer, to easily blend new data with old data.
                    // A somewhat naive solution, but the best I have found after trying several out.
                    wrapper.CopyCompoundToLayer(layer);

                    anyLayerWrittenTo = true;

                    if (wrapper.WriteHeights)
                    {
                        // Heights are a special type of layer, as layerComponents have the ability to compete with each other and determine who gets control of a point
                        // on the map through their height values. For this reason heights needed to be evaluated first, so winners can be determined.
                        for (int j = 0; j < layerStampMapping.Components.Count; j++)
                        {
                            MiscUtilities.ProgressBar(String.Format("Applying Heights for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count);
                            layerStampMapping.Components[j].ProcessHeights(wrapper, layer, j + 1);
                        }
                    }

                    // The Stencil is a critical component of componenting. Fundament It holds a dual purpose - blending
                    for (int j = 0; j < layerStampMapping.Components.Count; j++)
                    {
                        var stamp = layerStampMapping.Components[j];
                        MiscUtilities.ProgressBar(String.Format("Applying Stencil for Component {0} : Layer {1}", stamp.name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count);
                        stamp.ProcessStencil(wrapper, layer, j + 1);
                    }

                    MiscUtilities.ClampStencil(layer.Stencil);

                    for (int j = 0; j < layerStampMapping.Components.Count; j++)
                    {
                        var layerComponent = layerStampMapping.Components[j];
                        var stencilKey     = j + 1;

                        if (wrapper.WriteSplats)
                        {
                            MiscUtilities.ProgressBar(String.Format("Applying Splats for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count);
                            layerComponent.ProcessSplats(wrapper, layer, stencilKey);
                        }

                        if (wrapper.WriteObjects)
                        {
                            MiscUtilities.ProgressBar(String.Format("Applying Objects for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count);
                            layerComponent.ProcessObjects(wrapper, layer, stencilKey);
                        }

                        if (wrapper.WriteTrees)
                        {
                            MiscUtilities.ProgressBar(String.Format("Applying Trees for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count);
                            layerComponent.ProcessTrees(wrapper, layer, stencilKey);
                        }

                        if (wrapper.WriteDetails)
                        {
                            MiscUtilities.ProgressBar(String.Format("Applying Details for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count);
                            layerComponent.ProcessDetails(wrapper, layer, stencilKey);
                        }

                        #if VEGETATION_STUDIO
                        if (wrapper.WriteVegetationStudio)
                        {
                            MiscUtilities.ProgressBar(String.Format("Applying Details for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count);
                            layerComponent.ProcessVegetationStudio(wrapper, layer, stencilKey);
                        }
                        #endif

                        layer.Dirty = false;
                    }

                    if (anyLayerWrittenTo)
                    {
                        wrapper.SetDirtyAbove(layer);
                        MiscUtilities.ColoriseStencil(layer.Stencil);
                        wrapper.ClearCompoundCache(layer);
        #if UNITY_EDITOR
                        UnityEditor.EditorUtility.SetDirty(layer);
        #endif
                        wrapper.Dirty = true;
                    }
                }
            }
            for (int i = 0; i < mappings.Count; i++)
            {
                var layerStampMapping = mappings[i];
                for (int j = 0; j < layerStampMapping.Components.Count; j++)
                {
                    layerStampMapping.Components[j].OnPostBake();
                }
            }
            MiscUtilities.ClearProgressBar();
            Profiler.EndSample();
        }