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