/// <summary>
        /// Take whatever action you want to do in this method
        /// </summary>
        private void TakeAction()
        {
            isTakingAction = true;

            // Get the location of the object
            worldPosition = gameObject.transform.position;

            // Check which dominant texture is at this location in the landscape
            terrainTextureName = LBLandscapeTerrain.GetTextureNameAtPosition(landscape, worldPosition, checkTerrainHeight, heightTolerance, true);

#if UNITY_EDITOR
            // Typically, we don't want to be debugging in a build.
            if (debuggingMode)
            {
                Debug.Log("INFO: LBCheckTexture - dominate texture at " + worldPosition.ToString() + " is " + (string.IsNullOrEmpty(terrainTextureName) ? "unknown" : terrainTextureName));
            }
#endif

            if (textureNameList != null && !string.IsNullOrEmpty(terrainTextureName))
            {
                // Convert to all lowercase for non-case sensitive comparison
                terrainTextureName = terrainTextureName.ToLower();

                // Did we find a match?
                int nameIndex = textureNameList.FindIndex(tn => tn.ToLower() == terrainTextureName);
                if (nameIndex >= 0)
                {
                    PerformAction(terrainTextureName, nameIndex);
                }
            }

            isTakingAction = false;
        }
        /// <summary>
        /// Alternative method of checking the terrain. In this example it must match the first texture in the list
        /// Change the Update() statement to call TakeAction2() rather than TakeAction()
        /// </summary>
        private void TakeAction2()
        {
            isTakingAction = true;

            // Get the location of the object
            worldPosition = gameObject.transform.position;

            // Get the first texture name from the editor
            // You could use any name you like or pass it in as a parameter
            if (textureNameList != null && textureNameList.Count > 0)
            {
                terrainTextureName = textureNameList[0];
                if (!string.IsNullOrEmpty(terrainTextureName))
                {
                    // Check to see if the first texture has a weight of at least 40% at the location
                    if (LBLandscapeTerrain.IsTextureNameAtPosition(landscape, worldPosition, terrainTextureName, checkTerrainHeight, heightTolerance, 0.4f, true))
                    {
                        PerformAction(terrainTextureName, 0);
                    }
                }
            }

            isTakingAction = false;
        }
예제 #3
0
        /// <summary>
        /// Creates a preview mesh from the RAW height map data, with each vert offset by vertOffset
        /// NOTE: RecalculateTangents is only available in U5.6+
        /// </summary>
        /// <param name="vertOffset"></param>
        /// <param name="maxMeshResolution"></param>
        /// <returns></returns>
        public Mesh CreatePreviewMesh(Vector3 vertOffset, int maxMeshResolution = 129)
        {
            if (rawHeightData == null)
            {
                return(null);
            }
            else if (rawHeightData.Length < 2)
            {
                return(null);
            }
            else
            {
                Mesh previewMesh = new Mesh();

                //string methodName = "LBRaw.CreatePreviewMesh";

                // Declare outside loops for less garbage collection
                Vector3 vertPosition;
                int     byteIndex = 0;
                int     vertCount = 0;
                ushort  heightUShort;

                int meshWidth  = rawSourceWidth;
                int meshLength = rawSourceLength;
                if (meshWidth > maxMeshResolution)
                {
                    meshWidth = maxMeshResolution;
                }
                if (meshLength > maxMeshResolution)
                {
                    meshLength = maxMeshResolution;
                }

                int pixelScalingX = (int)((rawSourceWidth - 1) / (meshWidth - 1));
                int pixelScalingZ = (int)((rawSourceWidth - 1) / (meshWidth - 1));

                // Initialise mesh lists
                List <Vector3> verts     = new List <Vector3>();
                List <Vector2> uvs       = new List <Vector2>();
                List <int>     triangles = new List <int>();

                // Loop through all the x,z heightmap coordinates in this chunk of the terrain
                // Triangle numbers are zero based (triX,triZ) while the position in the terrain
                // is offset by the starting location of the chunk.
                for (int x = 0; x < rawSourceWidth; x += pixelScalingX)
                {
                    for (int z = 0; z < rawSourceLength; z += pixelScalingZ)
                    {
                        // Create vert for top right of quad

                        // Get the index of the byte for this x,z position
                        byteIndex = z * (rawSourceWidth * 2) + (x * 2);

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

                        // Heights are stored as [height,width] and are 0.0 - 1.0f.

                        // Create the vert as a 0-1 position
                        // Normalise the RAW Pixel - converting it to a range of 0 to 1
                        vertPosition = new Vector3((float)x / (float)(rawSourceWidth - 1), LBLandscapeTerrain.Normalise(heightUShort, rawMinHeight, rawMaxHeight), (float)z / (float)(rawSourceLength - 1));
                        verts.Add(vertPosition + vertOffset);

                        // Generic uvs (simply 0-1 coordinates of vert position)
                        uvs.Add(new Vector2(vertPosition.x, vertPosition.z));

                        // Add the two triangles for the quad
                        // Not required if on left or bottom edges of the mesh
                        if (x < rawSourceWidth - 1 && z < rawSourceLength - 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);
                        }

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

                //string methodName = "LBRaw.CreatePreviewMesh";
                //Debug.Log("INFO: " + methodName + " Mesh verts:" + verts.Count + " tris:" + triangles.Count);

                // Set mesh data
                previewMesh.vertices  = verts.ToArray();
                previewMesh.uv        = uvs.ToArray();
                previewMesh.triangles = triangles.ToArray();
                previewMesh.RecalculateNormals();
#if UNITY_5_6_OR_NEWER
                previewMesh.RecalculateTangents();
#endif
                previewMesh.name = dataSourceName + " preview mesh";

                // Return the generated mesh
                return(previewMesh);
            }
        }
    // 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()
    {
        // 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();

        // Create the terrains and store references to them
        terrainsList = new List <Terrain>();

        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");

                // 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;
                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);
            }
        }

        // 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 terrain topographies
        for (int t = 0; t < terrainsList.Count; t++)
        {
            // Use the LBLandscapeTerrain.PerlinNoiseHeightmap function for value based perlin noise
            // This example is using the values from the Rolling Hills preset
            terrainsList[t].terrainData = LBLandscapeTerrain.PerlinNoiseHeightmap(terrainsList[t].terrainData, terrainsList[t].transform.position,
                                                                                  7, 10000f, Vector2.zero, 1f, 2.00f, 0.40f, true, true, 1, 0.5f, 0, LBCurve.SetCurveFromPreset(LBCurve.CurvePreset.None), 1.5f);

            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

        List <LBTerrainTexture> 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;
        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;
        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, terrainTexturesList,
                                                                            terrainsList[t].transform.position, landscapeSize, this.transform.position, false, null);
        }

        // 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.");
    }
예제 #6
0
    // Use this for initialization
    void Awake()
    {
        // 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();

        // Create the terrains and store references to them
        terrainsList = new List <Terrain>();

        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");

                // 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;
                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);
            }
        }

        // Create the terrain topographies
        for (int t = 0; t < terrainsList.Count; t++)
        {
            // Use the LBLandscapeTerrain.PerlinNoiseHeightmap function for value based perlin noise
            // This example is using the values from the Mountain Range preset

            terrainsList[t].terrainData = LBLandscapeTerrain.PerlinNoiseHeightmap(terrainsList[t].terrainData, terrainsList[t].transform.position,
                                                                                  7, 5000f, Vector2.zero, 2f, 1.95f, 0.49f, true, false, 0, 0f, 0, LBCurve.SetCurveFromPreset(LBCurve.CurvePreset.None), 1f);
        }

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

        List <LBTerrainTexture> 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;
        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;
        terrainTexturesList.Add(tempTerrainTexture);

        // Rock1 texture
        tempTerrainTexture                = new LBTerrainTexture();
        tempTerrainTexture.texture        = rock1Texture;
        tempTerrainTexture.normalMap      = rock1NormalMap;
        tempTerrainTexture.tileSize       = Vector2.one * 100f;
        tempTerrainTexture.minInclination = 30f;
        tempTerrainTexture.maxInclination = 60f;
        tempTerrainTexture.useNoise       = true;
        tempTerrainTexture.noiseTileSize  = 100f;
        tempTerrainTexture.texturingMode  = LBTerrainTexture.TexturingMode.Inclination;
        terrainTexturesList.Add(tempTerrainTexture);

        // Bot Cliff texture
        tempTerrainTexture               = new LBTerrainTexture();
        tempTerrainTexture.texture       = botCliffTexture;
        tempTerrainTexture.normalMap     = botCliffNormalMap;
        tempTerrainTexture.tileSize      = Vector2.one * 100f;
        tempTerrainTexture.strength      = 0.01f;
        tempTerrainTexture.useNoise      = false;
        tempTerrainTexture.noiseTileSize = 100f;
        tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.ConstantInfluence;
        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, terrainTexturesList,
                                                                            terrainsList[t].transform.position, landscapeSize, this.transform.position, false, null);
        }

        // 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.");
    }
예제 #7
0
        private void OnSceneGUI()
        {
            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            Event current = Event.current;

            if (current != null)
            {
                if (lbGroupLocationItem == null)
                {
                    return;
                }
                else if (lbGroup == null)
                {
                    lbGroup = lbGroupLocationItem.lbGroup; if (lbGroup == null)
                    {
                        return;
                    }
                }

                bool isLeftButton  = (current.button == 0);
                bool isRightButton = (current.button == 1);

                tryPosition = lbGroupLocationItem.transform.position;

                // Clamp position of clearing
                if (tryPosition.x < landscapeBounds.xMin || tryPosition.x > landscapeBounds.xMax || tryPosition.z < landscapeBounds.yMin || tryPosition.z > landscapeBounds.yMax)
                {
                    lbGroupLocationItem.transform.position = prevPosition;
                }

                // Update prevPostion with the current position
                prevPosition = lbGroupLocationItem.transform.position;

                prevPosition.y = LBLandscapeTerrain.GetHeight(landscape, new Vector2(prevPosition.x, prevPosition.z), false) + landscape.start.y;
                // Snap the clearing location to the terrain height at this point
                lbGroupLocationItem.transform.position = prevPosition;

                if (current.type == EventType.MouseDown && isRightButton)
                {
                    #region Display the Context-sensitive menu
                    // NOTE: The Context Menu that is display when a location is NOT selected, can be found
                    // in LandscapeBuilderWindow.SceneGUI(SceneView sv)

                    GenericMenu menu = new GenericMenu();
                    menu.AddItem(new GUIContent("Delete Postion"), false, DeleteLocation);
                    menu.AddSeparator("");
                    menu.AddItem(new GUIContent("Delete ALL"), false, DeleteAll);
                    menu.AddSeparator("");
                    menu.AddItem(new GUIContent("Unselect"), false, () => { Selection.activeObject = null; });
                    // The Cancel option is not really necessary as use can just click anywhere else. However, it may help some users.
                    menu.AddItem(new GUIContent("Cancel"), false, () => { });
                    menu.ShowAsContext();
                    current.Use();
                    #endregion
                }
                // Record the starting positions
                else if (current.type == EventType.MouseDown && isLeftButton && landscape != null)
                {
                    lbGroupLocationItem.position  = lbGroupLocationItem.transform.position - landscape.start;
                    lbGroupLocationItem.rotationY = lbGroupLocationItem.transform.rotation.eulerAngles.y;
                }
                else if (current.type == EventType.MouseUp && isLeftButton)
                {
                    if (lbGroup.isFixedRotation)
                    {
                        #if UNITY_2017_3_OR_NEWER
                        if (Tools.current == Tool.Rotate || Tools.current == Tool.Transform)
                        #else
                        if (Tools.current == Tool.Rotate)
                        #endif
                        {
                            // Locate the first matching clearing position
                            // Only check x,z axis as the y-axis may be slightly wrong
                            int idx = lbGroup.positionList.FindIndex(pos => pos.x == lbGroupLocationItem.position.x && pos.z == lbGroupLocationItem.position.z);

                            if (idx > -1)
                            {
                                // update with the new rotation
                                lbGroupLocationItem.rotationY          = lbGroupLocationItem.transform.rotation.eulerAngles.y;
                                lbGroup.rotationYList[idx]             = lbGroupLocationItem.rotationY;
                                lbGroupLocationItem.transform.rotation = Quaternion.Euler(0f, lbGroupLocationItem.rotationY, 0f);
                                // Update the LB Editor Windows
                                LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow));
                            }
                        }
                    }


                    #if UNITY_2017_3_OR_NEWER
                    if ((Tools.current == Tool.Move || Tools.current == Tool.Transform) && landscape != null)
                    #else
                    if (Tools.current == Tool.Move && landscape != null)
                    #endif
                    {
                        // Locate the first matching clearing position
                        // Only check x,z axis as the y-axis may be slightly wrong
                        int idx = lbGroup.positionList.FindIndex(pos => pos.x == lbGroupLocationItem.position.x && pos.z == lbGroupLocationItem.position.z);

                        if (idx > -1)
                        {
                            // update it with the new position
                            lbGroup.positionList[idx] = lbGroupLocationItem.transform.position - landscape.start;
                        }
                    }

                    #if UNITY_2017_3_OR_NEWER
                    if (Tools.current == Tool.Scale || Tools.current == Tool.Transform)
                    #else
                    if (Tools.current == Tool.Scale)
                    #endif
                    {
                        lbGroup.minClearingRadius = lbGroupLocationItem.transform.localScale.x / 2f;
                        lbGroup.maxClearingRadius = lbGroup.minClearingRadius;

                        // Update the LB Editor Windows
                        LBEditorHelper.RepaintEditorWindow(typeof(LandscapeBuilderWindow));

                        // Resize all the locations in the scene
                        LBGroupLocationItem.RefreshLocationSizesInScene(landscape, lbGroup, true);
                    }
                }

                #region Changed Rotation

                // Clamp rotation
                if (!lbGroup.isFixedRotation)
                {
                    lbGroupLocationItem.transform.rotation = Quaternion.identity;
                }
                //else
                //{
                //    Vector3 eulerAngles = lbGroupLocationItem.transform.rotation.eulerAngles;
                //    if (eulerAngles.x != 0f || eulerAngles.z != 0f)
                //    {
                //        //lbGroupLocationItem.transform.rotation = Quaternion.Euler(0f, lbGroupLocationItem.rotationY, 0f);
                //    }
                //}
                #endregion

                #region Changed Radius
#if UNITY_2017_3_OR_NEWER
                if (Tools.current == Tool.Scale || Tools.current == Tool.Transform)
#else
                if (Tools.current == Tool.Scale)
                #endif
                {
                    // Equally scale x-z axis
                    float   currentScale = lbGroup.minClearingRadius * 2f;
                    float   maxScale     = -currentScale;
                    Vector3 localScale   = lbGroupLocationItem.transform.localScale;

                    // Delta = Abs(localScale.) - currentScale
                    float deltaX = (localScale.x < 0f ? -localScale.x : localScale.x);
                    float deltaY = (localScale.y < 0f ? -localScale.y : localScale.y);
                    float deltaZ = (localScale.z < 0f ? -localScale.z : localScale.z);

                    // Get the max scale amount of any of the axis
                    if (deltaX != currentScale && deltaX > maxScale)
                    {
                        maxScale = localScale.x;
                    }
                    if (deltaZ != currentScale && deltaZ > maxScale)
                    {
                        maxScale = localScale.z;
                    }

                    // Did the user change the scale?
                    if (maxScale != -currentScale)
                    {
                        // Clamp scaling to 0.2
                        if (maxScale < 0.2f)
                        {
                            maxScale = 0.2f;
                        }

                        localScale.x = maxScale;

                        // Make x-z axis the same
                        localScale.z = localScale.x;

                        // Don't change y-axis
                        localScale.y = 0.1f;

                        lbGroupLocationItem.transform.localScale = localScale;
                    }
                    else if (deltaY > 0f)
                    {
                        // Local Y axis scaling
                        localScale.y = 0.1f;
                        lbGroupLocationItem.transform.localScale = localScale;
                    }
                }
                #endregion
            }
        }