/// <summary>
        /// Fix or repair holes in GeoTIFF data. Typically used when GeoTIFF data
        /// has values > 65000 (which in metres is very unlikely)
        /// Also used with Include Below Sea Level with OpenTopo GMRT data.
        /// See notes in ImportHeightmapTIFF() under 32bit SampleFormat.IEEEFP.
        /// </summary>
        /// <param name="landscape"></param>
        /// <param name="lbLayer"></param>
        /// <param name="showErrors"></param>
        public static void FixGeoTIFFHeightmap(LBLandscape landscape, LBLayer lbLayer, bool showErrors)
        {
            string methodName = "LBImportTIFF.FixGeoTIFFHeightmap";

            if (landscape == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - landscape is null. Please report");
                }
            }
            else if (landscape.topographyLayersList == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - topographyLayers is not defined. Please report");
                }
            }
            else if (lbLayer == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - lbLayer is not defined. Please report");
                }
            }
            else if (lbLayer.type != LBLayer.LayerType.UnityTerrains)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - lbLayer is not of type: UnityTerrains. Please report");
                }
            }
            else if (lbLayer.lbTerrainDataList == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - lbLayer.lbTerrainDataList is not defined. Please report");
                }
            }
            else if (lbLayer.lbTerrainDataList.Count < 1)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - lbLayer.lbTerrainDataList does not contain any data. Please report");
                }
            }
            {
                int           numTerrainData = (lbLayer.lbTerrainDataList == null ? 0 : lbLayer.lbTerrainDataList.Count);
                LBTerrainData lbTerrainData  = null;

                ushort upperClip = 65000;

                // GRMT data adjustment variables. New sea-level to be 10,000
                ushort landCeiling = 65335 - 9999; // The maximum assumed height land values can be

                // We may need to use LBTerrainData.GetLandscapeScopedHeightmap() to fix holes
                // across terrain boundaries

                for (int lbTDataIdx = 0; lbTDataIdx < numTerrainData; lbTDataIdx++)
                {
                    lbTerrainData = lbLayer.lbTerrainDataList[lbTDataIdx];

                    if (lbTerrainData != null && lbTerrainData.HasRAWHeightData())
                    {
                        // Raw data is stored as a 1-dimensional USHORT byte array
                        // To fix holes we
                        int    heightmapResolution = lbTerrainData.RawHeightResolution;
                        int    byteIndex, byteIndexNearby;
                        ushort heightUShort, heightUShortNearby;

                        ushort sampleMinValue = ushort.MaxValue;
                        ushort sampleMaxValue = ushort.MinValue;

                        for (int z = 0; z < heightmapResolution; z++)
                        {
                            for (int x = 0; x < heightmapResolution; x++)
                            {
                                byteIndex = z * (heightmapResolution * 2) + (x * 2);

                                // LB stores RAW data in little endian (Windows) format, which is more suited to Intel processors.
                                heightUShort = (ushort)((lbTerrainData.rawHeightData[byteIndex + 1] << 8) | lbTerrainData.rawHeightData[byteIndex]);

                                // Global Multi-Resolution Topography (GMRT) data include +ve and -ve data.
                                // As we only import into ushort, the -ve values become values close to 64K
                                if (lbLayer.isBelowSeaLevelDataIncluded)
                                {
                                    // WORKAROUD - z==0 and z = max have incorrect values.
                                    // Attempt to fix bottom and top edges with some GMRT datasets (not sure why this happens yet...)
                                    //if ((z == 0 || z == (heightmapResolution - 1)) && heightUShort == 0u)
                                    if ((z == 0) && heightUShort == 0)
                                    {
                                        ulong  total    = 0;
                                        int    pixels   = 0;
                                        ushort pixelAvg = 0;
                                        // Get matrix of nearby pixels
                                        for (int pz = -3; pz < 4; pz++)
                                        {
                                            // Ignore pixels we're trying to fix
                                            if (pz == 0)
                                            {
                                                continue;
                                            }

                                            // Ensure the pixel is within the data area
                                            if (z + pz < 0 || z + pz > heightmapResolution - 1)
                                            {
                                                continue;
                                            }

                                            for (int px = -3; px < 4; px++)
                                            {
                                                // Ignore original value and ensure the pixel is within the data area
                                                if ((pz == 0 && px == 0) || (x + px < 0 || x + px > heightmapResolution - 1))
                                                {
                                                    continue;
                                                }

                                                byteIndexNearby    = (z + pz) * (heightmapResolution * 2) + ((x + px) * 2);
                                                heightUShortNearby = (ushort)((lbTerrainData.rawHeightData[byteIndexNearby + 1] << 8) | lbTerrainData.rawHeightData[byteIndexNearby]);

                                                // Only include pixels that are not being adjusted
                                                if (heightUShortNearby > 0)
                                                {
                                                    pixels++;
                                                    total += heightUShortNearby;
                                                }
                                            }
                                        }

                                        if (pixels > 0)
                                        {
                                            pixelAvg = Convert.ToUInt16((total / (ulong)pixels));
                                            if (pixelAvg > 0)
                                            {
                                                heightUShort = pixelAvg;
                                            }
                                        }
                                    }

                                    // Raise land values by 10,000
                                    if (heightUShort < landCeiling)
                                    {
                                        heightUShort += 10000;
                                    }
                                    else
                                    {
                                        // The -ve (below sea level) values have become height +ve numbers during the import
                                        // process. Move these original -ve number back under the new artifical sea level.
                                        heightUShort = (ushort)(10000u - (65535u - (uint)heightUShort));
                                    }

                                    // Convert ushort 0-65535 back to 2-bytes
                                    // LB stores RAW data in little endian (Windows) format, which is more suited to Intel processors.
                                    lbTerrainData.rawHeightData[byteIndex]     = System.Convert.ToByte(heightUShort & 255);
                                    lbTerrainData.rawHeightData[byteIndex + 1] = System.Convert.ToByte(heightUShort >> 8);

                                    // keep track of the min/max values in the input TIFF data
                                    if (heightUShort > sampleMaxValue)
                                    {
                                        sampleMaxValue = heightUShort;
                                    }
                                    if (heightUShort < sampleMinValue)
                                    {
                                        sampleMinValue = heightUShort;
                                    }
                                }
                                else
                                {
                                    // Is this an extreme value?
                                    if (heightUShort >= upperClip)
                                    {
                                        ulong  total    = 0;
                                        int    pixels   = 0;
                                        ushort pixelAvg = 0;
                                        // Get matrix of nearby pixels
                                        for (int pz = -3; pz < 4; pz++)
                                        {
                                            // Ensure the pixel is within the data area
                                            if (z + pz < 0 || z + pz > heightmapResolution - 1)
                                            {
                                                continue;
                                            }

                                            for (int px = -3; px < 4; px++)
                                            {
                                                // Ignore original value and ensure the pixel is within the data area
                                                if ((pz == 0 && px == 0) || (x + px < 0 || x + px > heightmapResolution - 1))
                                                {
                                                    continue;
                                                }

                                                // Ensure the pixel is within the data area
                                                //if (x + px < 0 || x + px > heightmapResolution - 1) { continue; }
                                                byteIndexNearby    = (z + pz) * (heightmapResolution * 2) + ((x + px) * 2);
                                                heightUShortNearby = (ushort)((lbTerrainData.rawHeightData[byteIndexNearby + 1] << 8) | lbTerrainData.rawHeightData[byteIndexNearby]);

                                                // Only include pixels that are not being clipped. Adjacent pixels may also need to be clipped, so we need
                                                // to not include them for averaging purposes, else the new pixel updated below will be much higher than the surrounding terrain.
                                                if (heightUShortNearby < upperClip)
                                                {
                                                    pixels++;
                                                    total += heightUShortNearby;
                                                }
                                            }
                                        }

                                        if (pixels > 0)
                                        {
                                            pixelAvg = Convert.ToUInt16((total / (ulong)pixels));
                                            if (pixelAvg > 0)
                                            {
                                                // Convert ushort 0-65535 back to 2-bytes
                                                // LB stores RAW data in little endian (Windows) format, which is more suited to Intel processors.
                                                lbTerrainData.rawHeightData[byteIndex]     = System.Convert.ToByte(pixelAvg & 255);
                                                lbTerrainData.rawHeightData[byteIndex + 1] = System.Convert.ToByte(pixelAvg >> 8);
                                                //Debug.Log("x,z " + x + "," + z + " avg: " + pixelAvg);
                                            }
                                        }
                                        else
                                        {
                                            // keep track of the min/max values in the input TIFF data
                                            if (heightUShort > sampleMaxValue)
                                            {
                                                sampleMaxValue = heightUShort;
                                            }
                                            if (heightUShort < sampleMinValue)
                                            {
                                                sampleMinValue = heightUShort;
                                            }
                                        }
                                    }
                                    else // Value is not extreme so update min/max values
                                    {
                                        // keep track of the min/max values in the input TIFF data
                                        if (heightUShort > sampleMaxValue)
                                        {
                                            sampleMaxValue = heightUShort;
                                        }
                                        if (heightUShort < sampleMinValue)
                                        {
                                            sampleMinValue = heightUShort;
                                        }
                                    }
                                }
                            }
                        }

                        // Need to update max height
                        lbTerrainData.rawMinHeight = sampleMinValue;
                        lbTerrainData.rawMaxHeight = sampleMaxValue;
                    }
                }
            }
        }
        /// <summary>
        /// Import a GeoTIFF file from disk into a Topography Layer
        /// </summary>
        /// <param name="landscape"></param>
        /// <param name="rawFileList"></param>
        /// <param name="isMacRAWFormat"></param>
        /// <param name="showErrors"></param>
        /// <returns></returns>
        public static bool ImportGeoTIFFHeightmap(LBLandscape landscape, string filePath, bool showErrors)
        {
            bool   isSuccessful = false;
            string methodName   = "LBImportTIFF.ImportGeoTIFFHeightmap";

            if (landscape == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - landscape is null. Please report");
                }
            }
            else if (landscape.topographyLayersList == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - topographyLayers is not defined. Please report");
                }
            }
            else if (string.IsNullOrEmpty(filePath))
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - filePath is not defined. Please report.");
                }
            }
            else if (landscape.landscapeTerrains == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - landscapeTerrains is not defined. Please report");
                }
            }
            else if (landscape.landscapeTerrains.Length < 1)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - No terrains in landscape");
                }
            }
            else if (landscape.topographyLayersList.Exists(lyr => lyr.type == LBLayer.LayerType.UnityTerrains))
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " - Multiple Unity Terrain Layers are not supported in the same landscape");
                }
            }
            else
            {
                float generationStartTime = Time.realtimeSinceStartup;
                int   numTerrains         = landscape.landscapeTerrains.Length;

                List <LBTerrainData> lbTerrainDataList = new List <LBTerrainData>();

                // Track the min/max heights for all the terrains
                ushort sampleMinHeight = ushort.MaxValue;
                ushort sampleMaxHeight = ushort.MinValue;

                for (int index = 0; index < numTerrains; index++)
                {
                    //Debug.Log("INFO: " + methodName + " importing TIFF for terrain: " + landscape.landscapeTerrains[index].name + " using file: " + filePath);

                    // Import TIFF region for the current terrain
                    LBTerrainData lbTerrainData = ImportHeightmapTIFF(landscape, landscape.landscapeTerrains[index], filePath, ref sampleMinHeight, ref sampleMaxHeight, showErrors);

                    // Don't continue if at least one terrain cannot be imported
                    if (lbTerrainData == null)
                    {
                        break;
                    }
                    else
                    {
                        lbTerrainDataList.Add(lbTerrainData);
                    }

                    // Only create a new layer if all terrains were imported
                    if (lbTerrainDataList.Count == numTerrains)
                    {
                        LBLayer lbLayer = new LBLayer();
                        if (lbLayer != null)
                        {
                            lbLayer.type = LBLayer.LayerType.UnityTerrains;
                            lbLayer.lbTerrainDataList      = lbTerrainDataList;
                            lbLayer.isCheckHeightRangeDiff = true;
                            lbLayer.heightScale            = 1.0f;
                            lbLayer.normaliseImage         = false;

                            // Insert at the top of the list
                            landscape.topographyLayersList.Insert(0, lbLayer);
                        }

                        if (landscape.showTiming)
                        {
                            Debug.Log("Time taken to import TIFF heightmaps: " + (Time.realtimeSinceStartup - generationStartTime).ToString("00.00") + " seconds.");
                        }

                        isSuccessful = true;
                    }
                }
            }

            return(isSuccessful);
        }
    // Use this for initialization
    void Awake()
    {
        #region Initialise
        // This line just gets the starting time of the generation so that the total generation time
        // can be recorded and displayed
        float generationStartTime = Time.realtimeSinceStartup;

        RuntimeSampleHelper.RemoveDefaultCamera();
        RuntimeSampleHelper.RemoveDefaultLight();

        // Get a link to the LBLandscape script
        landscape = this.GetComponent <LBLandscape>();

        if (landscape == null)
        {
            Debug.Log("Cannot find LBLandscape script attached to Runtime gameobject");
            return;
        }

        // Check to see if Universal Render Pipeline is installed in the project
        bool isURP = LBLandscape.IsURP(false);

        // Check to see if Light Weight Render Pipeline is installed in this project
        bool isLWRP = !isURP && LBLandscape.IsLWRP(false);

        // Check to see if High Definition Render Pipeline is installed in this project
        bool isHDRP = !isURP && !isLWRP && LBLandscape.IsHDRP(false);

        #if UNITY_2019_2_OR_NEWER
        bool is201920Plus = true;
        #else
        bool is201920Plus = false;
        #endif

        #endregion

        #region Create the terrains and store references to them
        terrainsList = new List <Terrain>();
        int terrainNumber = 0;

        for (float tx = 0f; tx < landscapeSize.x - 1f; tx += 2000f)
        {
            for (float ty = 0f; ty < landscapeSize.y - 1f; ty += 2000f)
            {
                // Create a new gameobject
                GameObject terrainObj = new GameObject("Runtime Terrain " + (terrainNumber++).ToString("000"));

                // Correctly parent and position the terrain
                terrainObj.transform.parent        = this.transform;
                terrainObj.transform.localPosition = new Vector3(tx, 0f, ty);

                // Add a terrain component
                Terrain newTerrain = terrainObj.AddComponent <Terrain>();

                // Set terrain settings (depending on your situtation, you may need to set more or less than I have in this example)
                newTerrain.heightmapPixelError   = 1;
                newTerrain.basemapDistance       = 5000f;
                newTerrain.treeDistance          = 5000f;
                newTerrain.treeBillboardDistance = 100f;
                newTerrain.detailObjectDistance  = 150f;
                newTerrain.treeCrossFadeLength   = 25f;

                // Set terrain data settings (same as above comment)
                TerrainData newTerrainData = new TerrainData();

                // One thing to note here is that modfiying the heightmap resolution not only clears all terrai height data,
                // it also scales up or down the size of the terrain. So you should always set the heightmap resolution
                // BEFORE you set the terrain size
                newTerrainData.heightmapResolution = 513;
                newTerrainData.size = Vector3.one * 2000f;
                newTerrainData.SetDetailResolution(1024, 16);
                newTerrain.terrainData = newTerrainData;

                // Set up the terrain collider
                TerrainCollider newTerrainCol = terrainObj.AddComponent <TerrainCollider>();
                newTerrainCol.terrainData = newTerrainData;

                // Add the terrain to the list of terrains
                terrainsList.Add(newTerrain);
            }
        }

        #endregion

        landscape.SetLandscapeTerrains(true);
        landscape.SetTerrainNeighbours(false);

        #region Set the terrain material
        int numTerrains = landscape.landscapeTerrains == null ? 0 : landscape.landscapeTerrains.Length;

        // Check for URP/LWRP/HDRP or do we need to create a default material for U2019.2.0 or newer
        if (isURP || isLWRP || isHDRP || is201920Plus)
        {
            float   pixelError = 0f;
            Terrain terrain    = null;
            LBLandscape.TerrainMaterialType terrainMaterialType = isURP ? LBLandscape.TerrainMaterialType.URP : (isLWRP ? LBLandscape.TerrainMaterialType.LWRP : (terrainMaterialType = isHDRP ? LBLandscape.TerrainMaterialType.HDRP : LBLandscape.TerrainMaterialType.BuiltInStandard));

            for (int tIdx = 0; tIdx < numTerrains; tIdx++)
            {
                terrain = landscape.landscapeTerrains[tIdx];
                landscape.SetTerrainMaterial(terrain, tIdx, (tIdx == numTerrains - 1), terrain.terrainData.size.x, ref pixelError, terrainMaterialType);
            }
        }
        #endregion

        // Set the topography noise variables
        float maskWarpAmount    = 0f;
        float maskNoiseTileSize = 10000f;
        float maskNoiseOffsetX  = 0f;
        float maskNoiseOffsetY  = 0f;

        AnimationCurve distanceToCentreMask = new AnimationCurve();
        int            keyInt = distanceToCentreMask.AddKey(0f, 1f);
        keyInt = distanceToCentreMask.AddKey(0.529f, 0.959f);
        keyInt = distanceToCentreMask.AddKey(1f, 0f);
        Keyframe[] curveKeys = distanceToCentreMask.keys;
        curveKeys[0].inTangent  = 0f;
        curveKeys[0].outTangent = 0f;
        curveKeys[1].inTangent  = -0.25f;
        curveKeys[1].outTangent = -0.25f;
        curveKeys[2].inTangent  = 0f;
        curveKeys[2].outTangent = 0f;
        distanceToCentreMask    = new AnimationCurve(curveKeys);

        AnimationCurve maskNoiseCurveModifier = AnimationCurve.Linear(0f, 0.5f, 1f, 1f);

        // Avoid warning of keyInt not being used.
        if (keyInt == 0)
        {
        }

        // Create the Topography Layers
        // You can mix and match Perlin and Image layers
        landscape.topographyLayersList = new List <LBLayer>();
        if (landscape.topographyLayersList != null)
        {
            // Add one or more Base layers
            LBLayer lbBaseLayer1 = new LBLayer();
            if (lbBaseLayer1 != null)
            {
                lbBaseLayer1 = LBLayer.SetLayerFromPreset(LBLayer.LayerPreset.DesertFloorBase);
                landscape.topographyLayersList.Add(lbBaseLayer1);
            }

            // Add one or more Additive layers
            LBLayer lbAdditiveLayer1 = new LBLayer();
            if (lbAdditiveLayer1 != null)
            {
                // You can manually configure a layer, or use a preset then modify it.
                lbAdditiveLayer1 = LBLayer.SetLayerFromPreset(LBLayer.LayerPreset.MountainRangeComplexBase);
                // If using using a different type of preset, must set the type after applying preset
                lbAdditiveLayer1.type = LBLayer.LayerType.PerlinAdditive;
                // Optionally override the preset settings
                lbAdditiveLayer1.noiseTileSize   = 5000f;
                lbAdditiveLayer1.octaves         = 8;
                lbAdditiveLayer1.lacunarity      = 1.92f;
                lbAdditiveLayer1.gain            = 0.45f;
                lbAdditiveLayer1.warpAmount      = 0;
                lbAdditiveLayer1.removeBaseNoise = true;
                lbAdditiveLayer1.heightScale     = 1f;
                lbAdditiveLayer1.additiveAmount  = 0.75f;
                lbAdditiveLayer1.additiveCurve   = LBLayer.CreateAdditiveCurve(lbAdditiveLayer1.additiveAmount);
                lbAdditiveLayer1.perOctaveCurveModifierPresets = new List <LBCurve.CurvePreset>();
                lbAdditiveLayer1.perOctaveCurveModifierPresets.Add(LBCurve.CurvePreset.DoubleRidged);
                landscape.topographyLayersList.Add(lbAdditiveLayer1);
            }

            // Add a detail layer
            LBLayer lbDetailLayer1 = new LBLayer();
            if (lbDetailLayer1 != null)
            {
                lbDetailLayer1 = LBLayer.SetLayerFromPreset(LBLayer.LayerPreset.HillsDetail);
                landscape.topographyLayersList.Add(lbDetailLayer1);
            }
        }

        // Create the terrain topographies
        for (int t = 0; t < terrainsList.Count && landscape.topographyLayersList != null; t++)
        {
            // Add the topography layers
            terrainsList[t].terrainData = LBLandscapeTerrain.HeightmapFromLayers(landscape, terrainsList[t].terrainData,
                                                                                 terrainsList[t].transform.position, landscapeSize, landscape.transform.position, landscape.topographyLayersList);


            if (IsMaskingOn)
            {
                // Example of applying a mask to the terrain topography
                terrainsList[t].terrainData = LBLandscapeTerrain.MaskedHeightmap(terrainsList[t].terrainData,
                                                                                 terrainsList[t].transform.position, landscapeSize, transform.position,
                                                                                 1, distanceToCentreMask, maskWarpAmount, maskNoiseTileSize,
                                                                                 new Vector2(maskNoiseOffsetX, maskNoiseOffsetY), maskNoiseCurveModifier);
            }
        }

        // Create a list of LBTerrainTexture objects
        // These contain the textures and normal maps but also the rules for applying them to the terrain

        landscape.terrainTexturesList = new List <LBTerrainTexture>();

        // Populate the list by creating temporary LBTerrainTexture objects and adjusting their settings,
        // then adding each one into the list

        // Grass Hill texture
        LBTerrainTexture tempTerrainTexture = new LBTerrainTexture();
        tempTerrainTexture.texture   = grassHillTexture;
        tempTerrainTexture.normalMap = grassHillNormalMap;

        tempTerrainTexture.tileSize       = Vector2.one * 25f;
        tempTerrainTexture.minInclination = 0f;
        tempTerrainTexture.maxInclination = 45f;
        tempTerrainTexture.useNoise       = true;
        tempTerrainTexture.noiseTileSize  = 100f;
        tempTerrainTexture.texturingMode  = LBTerrainTexture.TexturingMode.Inclination;
        landscape.terrainTexturesList.Add(tempTerrainTexture);

        // Rock Layered texture
        tempTerrainTexture                = new LBTerrainTexture();
        tempTerrainTexture.texture        = rockLayeredTexture;
        tempTerrainTexture.normalMap      = rockLayeredNormalMap;
        tempTerrainTexture.tileSize       = Vector2.one * 100f;
        tempTerrainTexture.minInclination = 30f;
        tempTerrainTexture.maxInclination = 90f;
        tempTerrainTexture.useNoise       = true;
        tempTerrainTexture.noiseTileSize  = 100f;
        tempTerrainTexture.texturingMode  = LBTerrainTexture.TexturingMode.Inclination;
        landscape.terrainTexturesList.Add(tempTerrainTexture);

        // Texture the terrains
        for (int t = 0; t < terrainsList.Count; t++)
        {
            // Use the LBLandscapeTerrain.TextureTerrain function for texturing the terrain
            terrainsList[t].terrainData = LBLandscapeTerrain.TextureTerrain(terrainsList[t].terrainData, landscape.terrainTexturesList,
                                                                            terrainsList[t].transform.position, landscapeSize, this.transform.position, false, landscape);
        }

        // Display the total time taken to generate the landscape (usually for debugging purposes)
        Debug.Log("Time taken to generate landscape: " + (Time.realtimeSinceStartup - generationStartTime).ToString("00.00") + " seconds.");
    }
    // Use this for initialization
    void Awake()
    {
        #region Initialise
        // This line just gets the starting time of the generation so that the total generation time
        // can be recorded and displayed
        float generationStartTime = Time.realtimeSinceStartup;

        RuntimeSampleHelper.RemoveDefaultCamera();
        RuntimeSampleHelper.RemoveDefaultLight();

        // We're using some old trees in this demo, which don't like anti-aliasing
        QualitySettings.antiAliasing = 0;

        // Get a link to the LBLandscape script
        landscape = this.GetComponent <LBLandscape>();

        if (landscape == null)
        {
            Debug.Log("Cannot find LBLandscape script attached to Runtime gameobject");
            return;
        }

        // Update the size
        landscape.size = landscapeSize;
        // Create the terrains
        int terrainNumber = 0;
        #endregion

        #region Create Terrains
        for (float tx = 0f; tx < landscapeSize.x - 1f; tx += terrainWidth)
        {
            for (float ty = 0f; ty < landscapeSize.y - 1f; ty += terrainWidth)
            {
                // Create a new gameobject
                GameObject terrainObj = new GameObject("RuntimeTerrain" + (terrainNumber++).ToString("000"));
                // Create a new gameobject
                // Correctly parent and position the terrain
                terrainObj.transform.parent        = this.transform;
                terrainObj.transform.localPosition = new Vector3(tx, 0f, ty);
                // Add a terrain component
                Terrain newTerrain = terrainObj.AddComponent <Terrain>();
                // Set terrain settings (depending on your situtation, you may need to set more or less than I have in this example)
                newTerrain.heightmapPixelError   = 5f;
                newTerrain.basemapDistance       = 1000f;
                newTerrain.treeDistance          = 750f;
                newTerrain.treeBillboardDistance = 100f;
                newTerrain.detailObjectDistance  = 200f;
                newTerrain.treeCrossFadeLength   = 5f;
                // Set terrain data settings (same as above comment)
                TerrainData newTerrainData = new TerrainData();
                newTerrainData.heightmapResolution = 513;
                newTerrainData.size = new Vector3(terrainWidth, terrainHeight, terrainWidth);
                newTerrainData.SetDetailResolution(1024, 16);
                newTerrain.terrainData = newTerrainData;

                // Set up the terrain collider
                TerrainCollider newTerrainCol = terrainObj.AddComponent <TerrainCollider>();
                newTerrainCol.terrainData = newTerrainData;
            }
        }

        landscape.SetLandscapeTerrains(true);
        landscape.SetDefaultTerrainMaterial();
        #endregion

        #region Create a Stencil
        // Add a new Stencil to the (empty) landscape
        LBStencil lbStencil = LBStencil.CreateStencilInScene(landscape, landscape.gameObject);
        if (lbStencil != null)
        {
            lbStencil.name += "01";

            /// Import PNG files into stencil layers (at runtime) and add as filters.
            lbStencil.layerImportMethod = LBStencil.LayerImportMethod.Grayscale;
            if (lbStencil.ImportTexture("Hills Layer 1", stencilLayerTex1, true))
            {
                // Remove the default first layer
                if (lbStencil.stencilLayerList.Count > 1)
                {
                    lbStencil.stencilLayerList.RemoveAt(0);
                }
            }
        }
        #endregion

        #region Define the Topography
        // NOTE: This sample uses a topography mask. This is not a requirement

        // Create the distance to centre mask using an animation curve
        AnimationCurve distanceToCentreMask = new AnimationCurve();
        distanceToCentreMask.AddKey(0.00f, 0.04f);
        distanceToCentreMask.AddKey(0.30f, 0.03f);
        distanceToCentreMask.AddKey(0.78f, 1.00f);
        distanceToCentreMask.AddKey(1.00f, 1.00f);
        Keyframe[] distanceToCentreMaskKeys = distanceToCentreMask.keys;
        distanceToCentreMaskKeys[0].inTangent  = 0.00f;
        distanceToCentreMaskKeys[0].outTangent = 0.00f;
        distanceToCentreMaskKeys[1].inTangent  = -0.02f;
        distanceToCentreMaskKeys[1].outTangent = -0.02f;
        distanceToCentreMaskKeys[2].inTangent  = 0.01f;
        distanceToCentreMaskKeys[2].outTangent = 0.01f;
        distanceToCentreMaskKeys[3].inTangent  = 0.00f;
        distanceToCentreMaskKeys[3].outTangent = 0.00f;
        distanceToCentreMask = new AnimationCurve(distanceToCentreMaskKeys);

        // Assign the topography mask to the LBLandscape instance
        landscape.distanceToCentreMask = distanceToCentreMask;
        landscape.topographyMaskMode   = LBLandscape.MaskMode.DistanceToCentre;

        // Create the Topography Layers
        // You can mix and match Perlin and Image layers
        landscape.topographyLayersList = new List <LBLayer>();
        if (landscape.topographyLayersList != null)
        {
            // NOTE
            // If you have used the LB Editor to first build a test landscape, the Topography layer
            // can be scripted out and pasted into your runtime script here.

            // Layer Code generated from Landscape Builder at 7:59 AM on ....
            AnimationCurve additiveCurve = new AnimationCurve();

            AnimationCurve subtractiveCurve = new AnimationCurve();

            List <LBLayerFilter> filters = new List <LBLayerFilter>();
            // Add LayerFilter code here
            List <AnimationCurve> imageCurveModifiers = new List <AnimationCurve>();

            List <AnimationCurve> outputCurveModifiers = new List <AnimationCurve>();
            AnimationCurve        OutputCurve1         = new AnimationCurve();
            OutputCurve1.AddKey(0.00f, 0.00f);
            OutputCurve1.AddKey(0.50f, 0.06f);
            OutputCurve1.AddKey(1.00f, 1.00f);
            Keyframe[] OutputCurve1Keys = OutputCurve1.keys;
            OutputCurve1Keys[0].inTangent  = 0.00f;
            OutputCurve1Keys[0].outTangent = 0.00f;
            OutputCurve1Keys[1].inTangent  = 0.50f;
            OutputCurve1Keys[1].outTangent = 0.50f;
            OutputCurve1Keys[2].inTangent  = 4.00f;
            OutputCurve1Keys[2].outTangent = 4.00f;
            OutputCurve1 = new AnimationCurve(OutputCurve1Keys);

            outputCurveModifiers.Add(OutputCurve1);

            List <AnimationCurve> perOctaveCurveModifiers = new List <AnimationCurve>();
            AnimationCurve        PerOctaveCurve1         = new AnimationCurve();
            PerOctaveCurve1.AddKey(0.00f, 0.00f);
            PerOctaveCurve1.AddKey(0.05f, 0.10f);
            PerOctaveCurve1.AddKey(0.45f, 0.90f);
            PerOctaveCurve1.AddKey(0.50f, 1.00f);
            PerOctaveCurve1.AddKey(0.55f, 0.90f);
            PerOctaveCurve1.AddKey(0.95f, 0.10f);
            PerOctaveCurve1.AddKey(1.00f, 0.00f);
            Keyframe[] PerOctaveCurve1Keys = PerOctaveCurve1.keys;
            PerOctaveCurve1Keys[0].inTangent  = 0.00f;
            PerOctaveCurve1Keys[0].outTangent = 0.00f;
            PerOctaveCurve1Keys[1].inTangent  = 2.00f;
            PerOctaveCurve1Keys[1].outTangent = 2.00f;
            PerOctaveCurve1Keys[2].inTangent  = 2.00f;
            PerOctaveCurve1Keys[2].outTangent = 2.00f;
            PerOctaveCurve1Keys[3].inTangent  = 0.00f;
            PerOctaveCurve1Keys[3].outTangent = 0.00f;
            PerOctaveCurve1Keys[4].inTangent  = -2.00f;
            PerOctaveCurve1Keys[4].outTangent = -2.00f;
            PerOctaveCurve1Keys[5].inTangent  = -2.00f;
            PerOctaveCurve1Keys[5].outTangent = -2.00f;
            PerOctaveCurve1Keys[6].inTangent  = 0.00f;
            PerOctaveCurve1Keys[6].outTangent = 0.00f;
            PerOctaveCurve1 = new AnimationCurve(PerOctaveCurve1Keys);

            perOctaveCurveModifiers.Add(PerOctaveCurve1);

            AnimationCurve mapPathBlendCurve = new AnimationCurve();
            mapPathBlendCurve.AddKey(0.00f, 0.00f);
            mapPathBlendCurve.AddKey(1.00f, 1.00f);
            Keyframe[] mapPathBlendCurveKeys = mapPathBlendCurve.keys;
            mapPathBlendCurveKeys[0].inTangent  = 0.00f;
            mapPathBlendCurveKeys[0].outTangent = 0.00f;
            mapPathBlendCurveKeys[1].inTangent  = 0.00f;
            mapPathBlendCurveKeys[1].outTangent = 0.00f;
            mapPathBlendCurve = new AnimationCurve(mapPathBlendCurveKeys);

            AnimationCurve mapPathHeightCurve = new AnimationCurve();
            mapPathHeightCurve.AddKey(0.00f, 1.00f);
            mapPathHeightCurve.AddKey(1.00f, 1.00f);
            Keyframe[] mapPathHeightCurveKeys = mapPathHeightCurve.keys;
            mapPathHeightCurveKeys[0].inTangent  = 0.00f;
            mapPathHeightCurveKeys[0].outTangent = 0.00f;
            mapPathHeightCurveKeys[1].inTangent  = 0.00f;
            mapPathHeightCurveKeys[1].outTangent = 0.00f;
            mapPathHeightCurve = new AnimationCurve(mapPathHeightCurveKeys);

            LBLayer lbBaseLayer01 = new LBLayer();
            if (lbBaseLayer01 != null)
            {
                lbBaseLayer01.type                   = LBLayer.LayerType.PerlinBase;
                lbBaseLayer01.preset                 = LBLayer.LayerPreset.MountainPeaksBase;
                lbBaseLayer01.layerTypeMode          = LBLayer.LayerTypeMode.Add;
                lbBaseLayer01.noiseTileSize          = 1000;
                lbBaseLayer01.noiseOffsetX           = 0;
                lbBaseLayer01.noiseOffsetZ           = 0;
                lbBaseLayer01.octaves                = 7;
                lbBaseLayer01.downscaling            = 1;
                lbBaseLayer01.lacunarity             = 1.75f;
                lbBaseLayer01.gain                   = 0.475f;
                lbBaseLayer01.additiveAmount         = 0.5f;
                lbBaseLayer01.subtractiveAmount      = 0.2f;
                lbBaseLayer01.additiveCurve          = additiveCurve;
                lbBaseLayer01.subtractiveCurve       = subtractiveCurve;
                lbBaseLayer01.removeBaseNoise        = true;
                lbBaseLayer01.addMinHeight           = false;
                lbBaseLayer01.addHeight              = 0f;
                lbBaseLayer01.restrictArea           = false;
                lbBaseLayer01.areaRect               = new Rect(0, 0, 1000, 1000);
                lbBaseLayer01.interpolationSmoothing = 0;
                //lbBaseLayer01.heightmapImage = heightmapImage;
                lbBaseLayer01.imageHeightScale        = 1f;
                lbBaseLayer01.imageCurveModifiers     = imageCurveModifiers;
                lbBaseLayer01.filters                 = filters;
                lbBaseLayer01.isDisabled              = false;
                lbBaseLayer01.showLayer               = false;
                lbBaseLayer01.showAdvancedSettings    = false;
                lbBaseLayer01.showCurvesAndFilters    = true;
                lbBaseLayer01.showAreaHighlighter     = false;
                lbBaseLayer01.detailSmoothRate        = 0f;
                lbBaseLayer01.areaBlendRate           = 0.5f;
                lbBaseLayer01.downscaling             = 1;
                lbBaseLayer01.warpAmount              = 0f;
                lbBaseLayer01.warpOctaves             = 1;
                lbBaseLayer01.outputCurveModifiers    = outputCurveModifiers;
                lbBaseLayer01.perOctaveCurveModifiers = perOctaveCurveModifiers;
                lbBaseLayer01.heightScale             = 0.75f;
                lbBaseLayer01.minHeight               = 0f;
                lbBaseLayer01.imageSource             = LBLayer.LayerImageSource.Default;
                lbBaseLayer01.imageRepairHoles        = false;
                lbBaseLayer01.threshholdRepairHoles   = 0f;
                lbBaseLayer01.mapPathBlendCurve       = mapPathBlendCurve;
                lbBaseLayer01.mapPathHeightCurve      = mapPathHeightCurve;
                lbBaseLayer01.mapPathAddInvert        = false;
                lbBaseLayer01.floorOffsetY            = 0f;
                // Add LBMapPath code here
                // lbBaseLayer01.lbPath = lbPath;
                // lbBaseLayer01.lbMapPath = lbMapPath;

                // NOTE Add the new layer to the landscape meta-data
                landscape.topographyLayersList.Add(lbBaseLayer01);
            }
        }

        #endregion

        // Create the terrain topographies
        landscape.ApplyTopography(false, true);

        // NOTE
        // If you have used the LB Editor to first build a test path in a landscape, the path points can be scripted
        // out and pasted into your runtime script

        #region LBMapPath Map Path
        // LBMapPath generated from Landscape Builder at 3:10 PM on Sunday, October 01, 2017
        LBMapPath lbMapPath = LBMapPath.CreateMapPath(landscape, landscape.gameObject);
        if (lbMapPath != null)
        {
            lbMapPath.name = "Map Path";
            if (lbMapPath.lbPath != null)
            {
                lbMapPath.lbPath.pathName           = "Map Path";
                lbMapPath.mapResolution             = 1;
                lbMapPath.lbPath.blendStart         = true;
                lbMapPath.lbPath.blendEnd           = true;
                lbMapPath.lbPath.pathResolution     = 2f;
                lbMapPath.lbPath.closedCircuit      = false;
                lbMapPath.lbPath.edgeBlendWidth     = 0f;
                lbMapPath.lbPath.removeCentre       = false;
                lbMapPath.lbPath.leftBorderWidth    = 0f;
                lbMapPath.lbPath.rightBorderWidth   = 0f;
                lbMapPath.lbPath.snapToTerrain      = true;
                lbMapPath.lbPath.heightAboveTerrain = 0f;
                lbMapPath.lbPath.zoomOnFind         = true;
                lbMapPath.lbPath.findZoomDistance   = 50f;
                // Mesh options
                lbMapPath.lbPath.isMeshLandscapeUV       = false;
                lbMapPath.lbPath.meshUVTileScale         = new Vector2(1, 1);
                lbMapPath.lbPath.meshYOffset             = 0.08f;
                lbMapPath.lbPath.meshEdgeSnapToTerrain   = true;
                lbMapPath.lbPath.meshSnapType            = LBPath.MeshSnapType.BothEdges;
                lbMapPath.lbPath.meshIsDoubleSided       = false;
                lbMapPath.lbPath.meshIncludeEdges        = false;
                lbMapPath.lbPath.meshIncludeWater        = false;
                lbMapPath.lbPath.meshSaveToProjectFolder = false;
                lbMapPath.meshMaterial = path1meshMaterial;
                // Path Points
                lbMapPath.lbPath.positionList.Add(new Vector3(631.6624f, 23.52699f, 825.2574f));
                lbMapPath.lbPath.positionList.Add(new Vector3(615.8184f, 9.507171f, 763.9471f));
                lbMapPath.lbPath.positionList.Add(new Vector3(592.5421f, 4.510101f, 721.7316f));
                lbMapPath.lbPath.positionList.Add(new Vector3(600.6003f, 2.589149f, 679.3673f));
                lbMapPath.lbPath.positionList.Add(new Vector3(620.8919f, 2.475228f, 658.526f));
                lbMapPath.lbPath.positionList.Add(new Vector3(599.6022f, 2.838308f, 605.2884f));
                lbMapPath.lbPath.positionList.Add(new Vector3(575.0403f, 2.714737f, 555.6046f));
                lbMapPath.lbPath.positionList.Add(new Vector3(560.4745f, 2.838308f, 472.1874f));
                lbMapPath.lbPath.positionList.Add(new Vector3(570.2177f, 3.09073f, 444.6886f));
                lbMapPath.lbPath.positionList.Add(new Vector3(570.2177f, 3.299063f, 387.1046f));
                lbMapPath.lbPath.positionList.Add(new Vector3(600.3734f, 4.613719f, 311.1418f));
                lbMapPath.lbPath.positionList.Add(new Vector3(610.5876f, 6.345493f, 293.1662f));
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(11.32066f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.widthList.Add(14f);
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(638.2852f, 23.52699f, 823.5834f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(622.2536f, 9.507171f, 761.4589f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(599.409f, 4.510101f, 720.4888f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(606.8383f, 2.589149f, 682.5374f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(627.8883f, 2.475228f, 658.7487f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(604.7557f, 2.838308f, 602.9471f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(581.7473f, 2.714737f, 553.6004f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(567.473f, 2.838308f, 472.0406f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(577.1524f, 3.09073f, 445.6413f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(577.0537f, 3.299063f, 388.6086f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(606.7752f, 4.613719f, 313.9633f));
                lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(616.454f, 6.345493f, 296.91f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(625.0396f, 23.52699f, 826.9315f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(609.3831f, 9.507171f, 766.4353f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(585.6751f, 4.510101f, 722.9744f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(594.3624f, 2.589149f, 676.1973f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(613.8955f, 2.475228f, 658.3033f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(594.4488f, 2.838308f, 607.6296f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(568.3334f, 2.714737f, 557.6088f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(553.4761f, 2.838308f, 472.3342f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(563.2829f, 3.09073f, 443.736f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(563.3816f, 3.299063f, 385.6005f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(593.9716f, 4.613719f, 308.3203f));
                lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(604.7213f, 6.345493f, 289.4224f));
                lbMapPath.minPathWidth = lbMapPath.lbPath.GetMinWidth();
                lbMapPath.lbPath.RefreshPathHeights(landscape);
                // Create Mesh for Path
                if (lbMapPath.lbPath.CreateMeshFromPath(landscape))
                {
                    Vector3   meshPosition  = new Vector3(0f, lbMapPath.lbPath.meshYOffset, 0f);
                    Transform meshTransform = LBMeshOperations.AddMeshToScene(lbMapPath.lbPath.lbMesh, meshPosition, lbMapPath.lbPath.pathName + " Mesh", lbMapPath.transform, lbMapPath.meshMaterial, true, true);
                    if (meshTransform != null)
                    {
                    }
                }
            }
        }
        #endregion

        // Create a list of LBTerrainTexture objects
        // These contain the textures and normal maps but also the rules for applying them to the terrain
        landscape.terrainTexturesList = new List <LBTerrainTexture>();

        // Populate the list by creating temporary LBTerrainTexture objects and adjusting their settings,
        // then adding each one into the list

        // Update the textures
        LBTerrainTexture tempTerrainTexture = new LBTerrainTexture();
        if (tempTerrainTexture != null)
        {
            // Forest Floor
            tempTerrainTexture.texture       = texture1;
            tempTerrainTexture.normalMap     = texture1NM;
            tempTerrainTexture.tileSize      = Vector2.one * 15f;
            tempTerrainTexture.useNoise      = false;
            tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.ConstantInfluence;
            tempTerrainTexture.strength      = 0.04f;
            landscape.terrainTexturesList.Add(tempTerrainTexture);

            // Rock Layered
            tempTerrainTexture                = new LBTerrainTexture();
            tempTerrainTexture.texture        = texture2;
            tempTerrainTexture.normalMap      = texture2NM;
            tempTerrainTexture.tileSize       = Vector2.one * 100f;
            tempTerrainTexture.texturingMode  = LBTerrainTexture.TexturingMode.HeightAndInclination;
            tempTerrainTexture.minHeight      = 400f / terrainHeight;
            tempTerrainTexture.maxHeight      = 1000f / terrainHeight;
            tempTerrainTexture.minInclination = 30f;
            tempTerrainTexture.maxInclination = 90f;
            tempTerrainTexture.useNoise       = true;
            tempTerrainTexture.noiseTileSize  = 100f;
            tempTerrainTexture.strength       = 1f;
            landscape.terrainTexturesList.Add(tempTerrainTexture);

            // Rock1
            tempTerrainTexture                = new LBTerrainTexture();
            tempTerrainTexture.texture        = texture3;
            tempTerrainTexture.normalMap      = texture3NM;
            tempTerrainTexture.tileSize       = Vector2.one * 100f;
            tempTerrainTexture.texturingMode  = LBTerrainTexture.TexturingMode.HeightAndInclination;
            tempTerrainTexture.minHeight      = 10f / terrainHeight;
            tempTerrainTexture.maxHeight      = 1000f / terrainHeight;
            tempTerrainTexture.minInclination = 30f;
            tempTerrainTexture.maxInclination = 60f;
            tempTerrainTexture.useNoise       = true;
            tempTerrainTexture.noiseTileSize  = 100f;
            tempTerrainTexture.strength       = 1f;
            landscape.terrainTexturesList.Add(tempTerrainTexture);

            // CliffBlue
            tempTerrainTexture               = new LBTerrainTexture();
            tempTerrainTexture.texture       = texture4;
            tempTerrainTexture.normalMap     = texture4NM;
            tempTerrainTexture.tileSize      = Vector2.one * 100f;
            tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.Height;
            tempTerrainTexture.minHeight     = 100f / terrainHeight;
            tempTerrainTexture.maxHeight     = 1000f / terrainHeight;
            tempTerrainTexture.useNoise      = true;
            tempTerrainTexture.noiseTileSize = 10f;
            tempTerrainTexture.strength      = 0.5f;
            landscape.terrainTexturesList.Add(tempTerrainTexture);

            // Good Dirt - FUTURE generate Map at runtime from slightly wider path and texture edges
            //tempTerrainTexture = new LBTerrainTexture();
            //tempTerrainTexture.texture = texture5;
            //tempTerrainTexture.normalMap = texture5NM;
            //tempTerrainTexture.tileSize = Vector2.one * 10f;
            //tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.Map;
            //tempTerrainTexture.map = ....
            //tempTerrainTexture.mapIsPath = true;
            //tempTerrainTexture.useAdvancedMapTolerance = false;
            //tempTerrainTexture.mapInverse = false;
            //tempTerrainTexture.useNoise = false;
            //tempTerrainTexture.strength = 1f;
            //landscape.terrainTexturesList.Add(tempTerrainTexture);

            // Texture the terrains
            landscape.ApplyTextures(true, true);
        }

        // Add a tree type
        LBTerrainTree terrainTree1 = new LBTerrainTree();
        if (terrainTree1 != null && treePrefab1 != null)
        {
            // Set tree type options as required. See LBTerrainTree class constructor for default settings
            terrainTree1.prefab            = treePrefab1.gameObject;
            terrainTree1.maxTreesPerSqrKm  = 140;
            terrainTree1.minScale          = 2f;
            terrainTree1.maxScale          = 3f;
            terrainTree1.treeScalingMode   = LBTerrainTree.TreeScalingMode.RandomScaling;
            terrainTree1.lockWidthToHeight = true;
            terrainTree1.treePlacingMode   = LBTerrainTree.TreePlacingMode.HeightAndInclination;
            terrainTree1.minInclination    = 0f;
            terrainTree1.maxInclination    = 30f;
            terrainTree1.minHeight         = 0f;
            terrainTree1.maxHeight         = 200f / terrainHeight;
            terrainTree1.useNoise          = false;

            //// Create a new filter, which will be used for the Stencil Layer
            //// This demonstrates how to apply a stencil layer to the placement of trees
            //LBFilter lbFilterTree = LBFilter.CreateFilter(lbStencil, "Hills Layer 1", true);

            //if (lbFilterTree != null)
            //{
            //    // If the list of filters isn't defined, create an empty list
            //    if (terrainTree1.filterList == null) { terrainTree1.filterList = new List<LBFilter>(); }

            //    // Add the Stencil Layer to the list of Tree Filters
            //    terrainTree1.filterList.Add(lbFilterTree);
            //}

            // Add the tree type configuration to the landscape
            landscape.terrainTreesList.Add(terrainTree1);
        }

        LBTerrainTree terrainTree2 = new LBTerrainTree();
        if (terrainTree2 != null && treePrefab1 != null)
        {
            // Set tree type options as required. See LBTerrainTree class constructor for default settings
            terrainTree2.prefab            = treePrefab2.gameObject;
            terrainTree2.maxTreesPerSqrKm  = 140;
            terrainTree2.minScale          = 2f;
            terrainTree2.maxScale          = 3f;
            terrainTree2.treeScalingMode   = LBTerrainTree.TreeScalingMode.RandomScaling;
            terrainTree2.lockWidthToHeight = true;
            terrainTree2.treePlacingMode   = LBTerrainTree.TreePlacingMode.HeightAndInclination;
            terrainTree2.minInclination    = 0f;
            terrainTree2.maxInclination    = 30f;
            terrainTree2.minHeight         = 0f;
            terrainTree2.maxHeight         = 200f / terrainHeight;
            terrainTree2.useNoise          = false;

            // Add the tree type configuration to the landscape
            landscape.terrainTreesList.Add(terrainTree2);
        }

        // Populate the landscape with the trees
        landscape.treesHaveColliders = true;
        landscape.treePlacementSpeed = LBTerrainTree.TreePlacementSpeed.FastPlacement;
        landscape.ApplyTrees(true, true);

        // Add some rock prefabs to the landscape
        LBLandscapeMesh lbLandscapeMesh = new LBLandscapeMesh();
        if (lbLandscapeMesh != null && rockPrefab != null)
        {
            lbLandscapeMesh.usePrefab = true;
            lbLandscapeMesh.prefab    = rockPrefab;
            // Set mesh options as required. See LBLandscapeMesh class constructor for default settings
            lbLandscapeMesh.maxMeshes       = 50;
            lbLandscapeMesh.meshPlacingMode = LBLandscapeMesh.MeshPlacingMode.ConstantInfluence;
            // Sink the rocks into the ground by 0.5m
            lbLandscapeMesh.offset = new Vector3(0f, -0.5f, 0f);
            // Group the rocks together
            //lbLandscapeMesh.isClustered = true;
            //lbLandscapeMesh.clusterDensity = 0.1f;
            //lbLandscapeMesh.clusterDistance = 10f;

            landscape.landscapeMeshList.Add(lbLandscapeMesh);

            landscape.meshPlacementSpeed = LBLandscapeMesh.MeshPlacementSpeed.FastPlacement;
            //landscape.ApplyMeshes(true, true);
        }

        // Get the first Camera Animator in the scene, snap the camera path to the new terrain,
        // and start moving the camera along the camera path.
        LBCameraAnimator lbCameraAnimator = LBCameraAnimator.GetFirstCameraAnimatorInLandscape(landscape);
        if (lbCameraAnimator == null)
        {
            Debug.LogWarning("GetFirstCameraAnimatorInLandscape returned null");
        }
        else
        {
            if (lbMapPath != null)
            {
                if (!lbCameraAnimator.cameraPath.ImportMapPathPoints(lbMapPath))
                {
                    Debug.LogWarning("Could not make camera animator travel along new Map Path.");
                }
            }

            // Get the LBPath instance which contains the points along the camera path
            LBPath lbPath = lbCameraAnimator.cameraPath.lbPath;
            if (lbPath == null)
            {
                Debug.LogWarning("Could not find the camera path instance for the animator");
            }
            else
            {
                // Optionally update the path points to match the terrain
                lbPath.heightAboveTerrain = 5f;
                lbPath.snapToTerrain      = true;
                lbPath.RefreshPathHeights(landscape);

                // Start the camera moving from the start of the path.
                lbCameraAnimator.BeginAnimation(true, 0f);
            }
        }

        // Display the total time taken to generate the landscape (usually for debugging purposes)
        Debug.Log("Time taken to generate landscape: " + (Time.realtimeSinceStartup - generationStartTime).ToString("00.00") + " seconds.");
    }
        /// <summary>
        /// Create an LBMesh object to hold the water mesh for a Topography Image Modifier Layer.
        /// </summary>
        /// <param name="landscape"></param>
        /// <param name="lbLayer"></param>
        /// <param name="layerIdx"></param>
        /// <param name="meshTitle"></param>
        /// <param name="showErrors"></param>
        /// <returns></returns>
        public static bool CreateMeshForWaterFromLayer(LBLandscape landscape, LBLayer lbLayer, int layerIdx, string meshTitle, bool showErrors)
        {
            bool isSuccessful = false;

            string methodName = "LBMeshOperations.CreateMeshForWaterFromLayer";

            if (landscape == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " landscape is null. Please Report");
                }
            }
            else if (lbLayer == null)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " lbLayer is null. Please Report");
                }
            }
            else if (lbLayer.type != LBLayer.LayerType.ImageModifier)
            {
                if (showErrors)
                {
                    Debug.LogWarning("ERROR: " + methodName + " LayerType must be ImageModifier. Please Report");
                }
            }
            {
                // TODO get the minium area below zero for the RAW modifier file to use for meshWidth/Length

                // Get the absolute width and length
                Vector2 meshSize = Vector2.zero;
                meshSize.x = lbLayer.areaRect.width < 0 ? -lbLayer.areaRect.width : lbLayer.areaRect.width;
                meshSize.y = lbLayer.areaRect.height < 0 ? -lbLayer.areaRect.height : lbLayer.areaRect.height;

                // Get the bottom-left point of mesh with landscape (it might be outside the landscape)
                Vector2 meshBottomLeft = Vector2.zero;
                meshBottomLeft.x = lbLayer.areaRect.x - (meshSize.x / 2f);
                meshBottomLeft.y = lbLayer.areaRect.y - (meshSize.y / 2f);
                if (meshBottomLeft.x < 0)
                {
                    meshBottomLeft.x += meshSize.x;
                }
                else if (meshBottomLeft.x == meshSize.x)
                {
                    meshBottomLeft.x = 0f;
                }
                if (meshBottomLeft.y < 0)
                {
                    meshBottomLeft.y += meshSize.y;
                }
                else if (meshBottomLeft.y == meshSize.y)
                {
                    meshBottomLeft.y = 0f;
                }

                //Debug.Log("INFO: " + methodName + " areaRect xy: " + lbLayer.areaRect.x + "," + lbLayer.areaRect.y + " b-l:" + meshBottomLeft);

                // If there is an existing LBMesh instance, remove all the mesh data
                if (lbLayer.modifierWaterLBMesh != null)
                {
                    LBMesh.DeleteMesh(lbLayer.modifierWaterLBMesh);
                }
                else
                {
                    lbLayer.modifierWaterLBMesh = new LBMesh();
                }

                if (lbLayer.modifierWaterLBMesh == null)
                {
                    if (showErrors)
                    {
                        Debug.LogWarning("ERROR: " + methodName + " Could not create LBMesh for the water in Layer " + (layerIdx + 1) + ". Please Report");
                    }
                }
                else if (meshSize.x < 0.1f || meshSize.y < 0.1f)
                {
                    { if (showErrors)
                      {
                          Debug.LogWarning("ERROR: " + methodName + " LayerType " + (layerIdx + 1) + " has an invalid water mesh size " + meshSize.x + "," + meshSize.y);
                      }
                    }
                }
                {
                    lbLayer.modifierWaterLBMesh.title = meshTitle;

                    // Initialise mesh lists
                    List <Vector3> verts     = new List <Vector3>();
                    List <Vector2> uvs       = new List <Vector2>();
                    List <int>     triangles = new List <int>();
                    List <Vector3> normals   = new List <Vector3>();
                    List <Vector4> tangents  = new List <Vector4>();
                    List <Vector4> colours   = new List <Vector4>(); // Store as Vector4s rather than Color so they are serializable

                    // Declare outside loops for less garbage collection
                    // We are creating a flat plane, so can use Vector2.
                    Vector2 vertPositionN     = Vector2.zero; // Normalised position within mesh
                    Vector2 vertLandscapePosN = Vector2.zero; // Normalised postion within the landscape
                    int     vertCount         = 0;

                    // Default colour of each vert (stored in LB as a Vector4)
                    Vector4 defaultVertColour = new Vector4(1f, 1f, 1f, 1f);

                    // The number of cells wide and long in the mesh
                    int meshWidth  = 10;
                    int meshLength = 10;

                    for (int x = 0; x < meshWidth; x++)
                    {
                        for (int z = 0; z < meshLength; z++)
                        {
                            // Create the vert as a 0-1 position
                            // Normalise the RAW Pixel - converting it to a range of 0 to 1
                            vertPositionN.x = (float)x / (float)(meshWidth - 1);
                            vertPositionN.y = (float)z / (float)(meshLength - 1);
                            verts.Add(new Vector3(vertPositionN.x * meshSize.x, 0f, vertPositionN.y * meshSize.y));
                            normals.Add(Vector3.up);

                            if (lbLayer.modifierWaterIsMeshLandscapeUV)
                            {
                                // UVs normalised to the landscape
                                vertLandscapePosN.x = ((vertPositionN.x * meshSize.x) + meshBottomLeft.x) / landscape.size.x;
                                vertLandscapePosN.y = ((vertPositionN.y * meshSize.y) + meshBottomLeft.y) / landscape.size.y;

                                uvs.Add(new Vector2(vertLandscapePosN.x / lbLayer.modifierWaterMeshUVTileScale.x, vertLandscapePosN.y / lbLayer.modifierWaterMeshUVTileScale.y));
                            }
                            else
                            {
                                // Generic uvs (simply 0-1 coordinates of vert position)
                                uvs.Add(new Vector2(vertPositionN.x / lbLayer.modifierWaterMeshUVTileScale.x, vertPositionN.y / lbLayer.modifierWaterMeshUVTileScale.y));
                            }

                            // Create tangent
                            tangents.Add(new Vector4(1f, 0f, 0f, 1f));

                            // Add the two triangles for the quad
                            // Not required if on left or bottom edges of the mesh
                            if (x < meshWidth - 1 && z < meshLength - 1)
                            {
                                // Bottom (left) triangle
                                // Bottom left of quad
                                triangles.Add(vertCount);
                                // Bottom right of quad
                                triangles.Add(vertCount + 1);
                                // Top right of quad
                                triangles.Add(vertCount + meshWidth + 1);

                                // Top (right) triangle
                                // Top left of quad
                                triangles.Add(vertCount + meshWidth);
                                // Bottom left of quad
                                triangles.Add(vertCount);
                                // Top right of quad
                                triangles.Add(vertCount + meshWidth + 1);
                            }

                            // Set default vert colour
                            colours.Add(defaultVertColour);

                            // Increment the vert count
                            vertCount++;
                        }
                    }

                    lbLayer.modifierWaterLBMesh.verts     = verts;
                    lbLayer.modifierWaterLBMesh.triangles = triangles;
                    lbLayer.modifierWaterLBMesh.normals   = normals;
                    lbLayer.modifierWaterLBMesh.uvs       = uvs;
                    lbLayer.modifierWaterLBMesh.tangents  = tangents;

                    //Debug.Log("INFO " + methodName + " - created Mesh (verts " + verts.Count + " tris " + (triangles.Count / 3) + ")");

                    isSuccessful = true;
                }
            }

            return(isSuccessful);
        }
    // Use this for initialization
    void Awake()
    {
        #region Initialise
        // This line just gets the starting time of the generation so that the total generation time
        // can be recorded and displayed
        float generationStartTime = Time.realtimeSinceStartup;

        RuntimeSampleHelper.RemoveDefaultCamera();
        RuntimeSampleHelper.RemoveDefaultLight();

        // Get a link to the LBLandscape script
        landscape = this.GetComponent <LBLandscape>();

        if (landscape == null)
        {
            Debug.Log("Cannot find LBLandscape script attached to Runtime gameobject");
            return;
        }

        // Update the size
        landscape.size = landscapeSize;

        #endregion

        #region Create the terrains
        int terrainNumber = 0;

        for (float tx = 0f; tx < landscapeSize.x - 1f; tx += 2000f)
        {
            for (float ty = 0f; ty < landscapeSize.y - 1f; ty += 2000f)
            {
                // Create a new gameobject
                GameObject terrainObj = new GameObject("Runtime Terrain " + (terrainNumber++).ToString("000"));

                // Correctly parent and position the terrain
                terrainObj.transform.parent        = this.transform;
                terrainObj.transform.localPosition = new Vector3(tx, 0f, ty);

                // Add a terrain component
                Terrain newTerrain = terrainObj.AddComponent <Terrain>();

                // Set terrain settings (depending on your situtation, you may need to set more or less than I have in this example)
                newTerrain.heightmapPixelError   = 1;
                newTerrain.basemapDistance       = 5000f;
                newTerrain.treeDistance          = 5000f;
                newTerrain.treeBillboardDistance = 100f;
                newTerrain.detailObjectDistance  = 150f;
                newTerrain.treeCrossFadeLength   = 25f;

                newTerrain.groupingID       = 100; // default is 0
                newTerrain.allowAutoConnect = true;

                // Set terrain data settings (same as above comment)
                TerrainData newTerrainData = new TerrainData();

                // One thing to note here is that modfiying the heightmap resolution not only clears all terrain height data,
                // it also scales up or down the size of the terrain. So you should always set the heightmap resolution
                // BEFORE you set the terrain size
                newTerrainData.heightmapResolution = 513;
                newTerrainData.size = Vector3.one * 2000f;
                newTerrainData.SetDetailResolution(1024, 16);
                newTerrain.terrainData = newTerrainData;

                // Set up the terrain collider
                TerrainCollider newTerrainCol = terrainObj.AddComponent <TerrainCollider>();
                newTerrainCol.terrainData = newTerrainData;
            }
        }
        #endregion

        landscape.SetLandscapeTerrains(true);
        terrainHeight = landscape.GetLandscapeTerrainHeight();

        landscape.SetDefaultTerrainMaterial();

        #region Add a new Stencil to the (empty) landscape
        LBStencil lbStencil = LBStencil.CreateStencilInScene(landscape, landscape.gameObject);
        if (lbStencil != null)
        {
            lbStencil.name += "01";

            /// Import PNG files into stencil layers (at runtime) and add as filters.
            lbStencil.layerImportMethod = LBStencil.LayerImportMethod.Grayscale;
            if (lbStencil.ImportTexture("Hills Layer 1", stencilLayerTex1, true))
            {
                // Remove the default first layer
                if (lbStencil.stencilLayerList.Count > 1)
                {
                    lbStencil.stencilLayerList.RemoveAt(0);
                }
            }
        }
        #endregion

        // NOTE: This sample uses a topography mask. This is not a requirement

        // Create the distance to centre mask using an animation curve
        AnimationCurve distanceToCentreMask = new AnimationCurve();
        int            keyInt = distanceToCentreMask.AddKey(0f, 1f);
        keyInt = distanceToCentreMask.AddKey(0.529f, 0.959f);
        keyInt = distanceToCentreMask.AddKey(1f, 0f);
        Keyframe[] curveKeys = distanceToCentreMask.keys;
        curveKeys[0].inTangent  = 0f;
        curveKeys[0].outTangent = 0f;
        curveKeys[1].inTangent  = -0.25f;
        curveKeys[1].outTangent = -0.25f;
        curveKeys[2].inTangent  = 0f;
        curveKeys[2].outTangent = 0f;
        distanceToCentreMask    = new AnimationCurve(curveKeys);

        // Assign the topography mask to the LBLandscape instance
        landscape.distanceToCentreMask = distanceToCentreMask;
        if (IsMaskingOn)
        {
            landscape.topographyMaskMode = LBLandscape.MaskMode.DistanceToCentre;
        }
        else
        {
            landscape.topographyMaskMode = LBLandscape.MaskMode.None;
        }
        landscape.maskWarpAmount         = 0f;
        landscape.maskNoiseTileSize      = 10000f;
        landscape.maskNoiseCurveModifier = AnimationCurve.Linear(0f, 0.5f, 1f, 1f);
        landscape.maskNoiseOffsetX       = 0f;
        landscape.maskNoiseOffsetY       = 0f;

        // Avoid warning of keyInt not being used.
        if (keyInt == 0)
        {
        }

        // Create the Topography Layers
        // You can mix and match Perlin and Image layers
        landscape.topographyLayersList = new List <LBLayer>();
        if (landscape.topographyLayersList != null)
        {
            // Add one or more Base layers
            LBLayer lbBaseLayer1 = new LBLayer();
            if (lbBaseLayer1 != null)
            {
                lbBaseLayer1 = LBLayer.SetLayerFromPreset(LBLayer.LayerPreset.DesertFloorBase);
                landscape.topographyLayersList.Add(lbBaseLayer1);
            }

            // Add one or more Additive layers
            LBLayer lbAdditiveLayer1 = new LBLayer();
            if (lbAdditiveLayer1 != null)
            {
                // You can manually configure a layer, or use a preset then modify it.
                lbAdditiveLayer1 = LBLayer.SetLayerFromPreset(LBLayer.LayerPreset.RollingHillsBase);
                // If using using a different type of preset, must set the type after applying preset
                lbAdditiveLayer1.type = LBLayer.LayerType.PerlinAdditive;
                // Optionally override the preset settings
                //lbAdditiveLayer1.noiseTileSize = 5000f;
                //lbAdditiveLayer1.octaves = 8;
                //lbAdditiveLayer1.lacunarity = 1.92f;
                //lbAdditiveLayer1.gain = 0.45f;
                //lbAdditiveLayer1.warpAmount = 0;
                lbAdditiveLayer1.removeBaseNoise = true;
                lbAdditiveLayer1.heightScale     = 0.35f;
                lbAdditiveLayer1.additiveAmount  = 0.95f;
                lbAdditiveLayer1.additiveCurve   = LBLayer.CreateAdditiveCurve(lbAdditiveLayer1.additiveAmount);
                //lbAdditiveLayer1.perOctaveCurveModifierPresets = new List<LBCurve.CurvePreset>();
                //lbAdditiveLayer1.perOctaveCurveModifierPresets.Add(LBCurve.CurvePreset.DoubleRidged);

                // Create a new topography layer filter, which will be used for the Stencil Layer
                LBLayerFilter lbLayerFilter = LBLayerFilter.CreateLayerFilter(lbStencil, "Hills Layer 1", true);

                if (lbLayerFilter != null)
                {
                    // If the list of filters isn't defined, create an empty list
                    if (lbAdditiveLayer1.filters == null)
                    {
                        lbAdditiveLayer1.filters = new List <LBLayerFilter>();
                    }

                    // Add the Stencil Layer to the list of Topography LayerFilters
                    lbAdditiveLayer1.filters.Add(lbLayerFilter);
                }

                landscape.topographyLayersList.Add(lbAdditiveLayer1);
            }

            // Add a detail layer
            LBLayer lbDetailLayer1 = new LBLayer();
            if (lbDetailLayer1 != null)
            {
                lbDetailLayer1 = LBLayer.SetLayerFromPreset(LBLayer.LayerPreset.HillsDetail);
                landscape.topographyLayersList.Add(lbDetailLayer1);
            }
        }

        // Create the terrain topographies
        landscape.ApplyTopography(false, true);

        // Get the first Camera Animator in the scene, snap the camera path to the new terrain,
        // and start moving the camera along the camera path.
        LBCameraAnimator lbCameraAnimator = LBCameraAnimator.GetFirstCameraAnimatorInLandscape(landscape);
        if (lbCameraAnimator == null)
        {
            Debug.LogWarning("GetFirstCameraAnimatorInLandscape returned null");
        }
        else
        {
            // Get the LBPath instance which contains the points along the camera path
            LBPath lbPath = lbCameraAnimator.cameraPath.lbPath;
            if (lbPath == null)
            {
                Debug.LogWarning("Could not find the camera path instance for the animator");
            }
            else
            {
                // Optionally update the path points to match the terrain
                lbPath.heightAboveTerrain = 15f;
                lbPath.snapToTerrain      = true;
                lbPath.RefreshPathHeights(landscape);

                // Start the camera moving from the start of the path.
                lbCameraAnimator.BeginAnimation(true, 0f);
            }
        }

        // Add some water the scene
        int     numberOfMeshes = 0;
        Vector2 waterSize      = new Vector2(landscape.size.x * 2f, landscape.size.y * 2f);
        // The primary water body is placed in the centre of the landscape
        Vector3 waterPosition = landscape.start + (0.5f * new Vector3(landscape.size.x, 0f, landscape.size.y));

        // Populate the paramaters to pass to AddWaterToScene()
        LBWaterParameters lbWaterParms = new LBWaterParameters();
        lbWaterParms.landscape               = landscape;
        lbWaterParms.landscapeGameObject     = landscape.gameObject;
        lbWaterParms.waterPosition           = waterPosition;
        lbWaterParms.waterSize               = waterSize;
        lbWaterParms.waterIsPrimary          = true;
        lbWaterParms.waterHeight             = waterHeight;
        lbWaterParms.waterPrefab             = waterPrefab;
        lbWaterParms.keepPrefabAspectRatio   = true;
        lbWaterParms.waterResizingMode       = LBWater.WaterResizingMode.StandardAssets;
        lbWaterParms.waterMaxMeshThreshold   = 5000;
        lbWaterParms.waterMainCamera         = Camera.main;
        lbWaterParms.waterCausticsPrefabList = null;
        lbWaterParms.isRiver    = false;
        lbWaterParms.lbLighting = GameObject.FindObjectOfType <LBLighting>();

        LBWater addedWater = LBWaterOperations.AddWaterToScene(lbWaterParms, ref numberOfMeshes);

        if (addedWater == null)
        {
            Debug.LogWarning("Could not add water to scene");
        }

        // Create a list of LBTerrainTexture objects
        // These contain the textures and normal maps but also the rules for applying them to the terrain
        landscape.terrainTexturesList = new List <LBTerrainTexture>();

        // Populate the list by creating temporary LBTerrainTexture objects and adjusting their settings,
        // then adding each one into the list

        // Grass Hill texture
        LBTerrainTexture tempTerrainTexture = new LBTerrainTexture();
        if (tempTerrainTexture != null)
        {
            tempTerrainTexture.texture   = grassHillTexture;
            tempTerrainTexture.normalMap = grassHillNormalMap;

            tempTerrainTexture.tileSize       = Vector2.one * 25f;
            tempTerrainTexture.minInclination = 0f;
            tempTerrainTexture.maxInclination = 45f;
            tempTerrainTexture.useNoise       = true;
            tempTerrainTexture.noiseTileSize  = 100f;
            tempTerrainTexture.texturingMode  = LBTerrainTexture.TexturingMode.Inclination;
            landscape.terrainTexturesList.Add(tempTerrainTexture);

            // Rock Layered texture
            tempTerrainTexture                = new LBTerrainTexture();
            tempTerrainTexture.texture        = rockLayeredTexture;
            tempTerrainTexture.normalMap      = rockLayeredNormalMap;
            tempTerrainTexture.tileSize       = Vector2.one * 100f;
            tempTerrainTexture.minInclination = 30f;
            tempTerrainTexture.maxInclination = 90f;
            tempTerrainTexture.useNoise       = true;
            tempTerrainTexture.noiseTileSize  = 100f;
            tempTerrainTexture.texturingMode  = LBTerrainTexture.TexturingMode.Inclination;
            landscape.terrainTexturesList.Add(tempTerrainTexture);

            // Texture the terrains
            landscape.ApplyTextures(true, true);
        }

        // Add a tree type
        LBTerrainTree tempTerrainTree = new LBTerrainTree();
        if (tempTerrainTree != null && treePrefab != null)
        {
            // Set tree type options as required. See LBTerrainTree class constructor for default settings
            tempTerrainTree.prefab           = treePrefab.gameObject;
            tempTerrainTree.maxTreesPerSqrKm = 100;
            tempTerrainTree.treePlacingMode  = LBTerrainTree.TreePlacingMode.HeightAndInclination;
            tempTerrainTree.minInclination   = 0f;
            tempTerrainTree.maxInclination   = 30f;
            tempTerrainTree.minHeight        = (waterHeight + 2f) / terrainHeight;

            // Create a new filter, which will be used for the Stencil Layer
            // This demonstrates how to apply a stencil layer to the placement of trees
            LBFilter lbFilterTree = LBFilter.CreateFilter(lbStencil, "Hills Layer 1", true);

            if (lbFilterTree != null)
            {
                // If the list of filters isn't defined, create an empty list
                if (tempTerrainTree.filterList == null)
                {
                    tempTerrainTree.filterList = new List <LBFilter>();
                }

                // Add the Stencil Layer to the list of Tree Filters
                tempTerrainTree.filterList.Add(lbFilterTree);
            }

            // Add the tree type configuration to the landscape
            landscape.terrainTreesList.Add(tempTerrainTree);

            // Populate the landscape with the trees
            landscape.ApplyTrees(true, true);
        }

        // Add some rock prefabs to the landscape
        LBLandscapeMesh lbLandscapeMesh = new LBLandscapeMesh();
        if (lbLandscapeMesh != null && rockPrefab != null)
        {
            lbLandscapeMesh.usePrefab = true;
            lbLandscapeMesh.prefab    = rockPrefab;
            // Set mesh options as required. See LBLandscapeMesh class constructor for default settings
            lbLandscapeMesh.maxMeshes = 100;
            // Sink the rocks into the ground by 0.5m
            lbLandscapeMesh.offset = new Vector3(0f, -0.5f, 0f);
            // Place the rocks near the water's edge
            lbLandscapeMesh.meshPlacingMode = LBLandscapeMesh.MeshPlacingMode.HeightAndInclination;
            lbLandscapeMesh.minHeight       = (waterHeight + 1f) / terrainHeight;
            lbLandscapeMesh.maxHeight       = lbLandscapeMesh.minHeight + (10f / terrainHeight);
            lbLandscapeMesh.maxInclination  = 12.5f;
            lbLandscapeMesh.useNoise        = true;
            // Group the rocks together
            lbLandscapeMesh.isClustered     = true;
            lbLandscapeMesh.clusterDensity  = 0.1f;
            lbLandscapeMesh.clusterDistance = 10f;
            //lbLandscapeMesh.minProximity = 10f;

            landscape.landscapeMeshList.Add(lbLandscapeMesh);

            landscape.ApplyMeshes(true, true);
        }

        // Display the total time taken to generate the landscape (usually for debugging purposes)
        Debug.Log("Time taken to generate landscape: " + (Time.realtimeSinceStartup - generationStartTime).ToString("00.00") + " seconds.");
    }