/// /// Dvornik /// using UnityEngine; using UnityEditor; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Collections.Generic; /// /// Split terrain. /// public class SplitTerrain : EditorWindow { string num = "4"; List terrainData = new List(); List terrainGo = new List(); Terrain parentTerrain; const int terrainsCount = 4; // Add submenu [MenuItem("Dvornik/Terrain/Split Terrain")] static void Init() { // Get existing open window or if none, make a new one: SplitTerrain window = (SplitTerrain)EditorWindow.GetWindow(typeof(SplitTerrain)); window.minSize = new Vector2( 100f,100f ); window.maxSize = new Vector2( 200f,200f ); window.autoRepaintOnSceneChange = true; window.title = "Resize terrain"; window.Show(); } /// /// Determines whether this instance is power of two the specified x. /// /// /// true if this instance is power of two the specified x; otherwise, false. /// /// /// If set to true x. /// bool IsPowerOfTwo(int x) { return (x & (x - 1)) == 0; } void SplitIt() { if ( Selection.activeGameObject == null ) { Debug.LogWarning("No terrain was selected"); return; } parentTerrain = Selection.activeGameObject.GetComponent(typeof(Terrain)) as Terrain; if ( parentTerrain == null ) { Debug.LogWarning("Current selection is not a terrain"); return; } //Split terrain for ( int i=0; i< terrainsCount; i++) { EditorUtility.DisplayProgressBar("Split terrain","Process " + i, (float) i / terrainsCount ); TerrainData td = new TerrainData(); GameObject tgo = Terrain.CreateTerrainGameObject( td ); tgo.name = parentTerrain.name + " " + i; terrainData.Add( td ); terrainGo.Add ( tgo ); Terrain genTer = tgo.GetComponent(typeof(Terrain)) as Terrain; genTer.terrainData = td; AssetDatabase.CreateAsset(td, "Assets/" + genTer.name+ ".asset"); // Assign splatmaps genTer.terrainData.splatPrototypes = parentTerrain.terrainData.splatPrototypes; // Assign detail prototypes genTer.terrainData.detailPrototypes = parentTerrain.terrainData.detailPrototypes; // Assign tree information genTer.terrainData.treePrototypes = parentTerrain.terrainData.treePrototypes; // Copy parent terrain propeties #region parent properties genTer.basemapDistance = parentTerrain.basemapDistance; genTer.castShadows = parentTerrain.castShadows; genTer.detailObjectDensity = parentTerrain.detailObjectDensity; genTer.detailObjectDistance = parentTerrain.detailObjectDistance; genTer.heightmapMaximumLOD = parentTerrain.heightmapMaximumLOD; genTer.heightmapPixelError = parentTerrain.heightmapPixelError; genTer.treeBillboardDistance = parentTerrain.treeBillboardDistance; genTer.treeCrossFadeLength = parentTerrain.treeCrossFadeLength; genTer.treeDistance = parentTerrain.treeDistance; genTer.treeMaximumFullLODCount = parentTerrain.treeMaximumFullLODCount; #endregion //Start processing it // Translate peace to position #region translate peace to right position Vector3 parentPosition = parentTerrain.GetPosition(); int terraPeaces = (int) Mathf.Sqrt( terrainsCount ); float spaceShiftX = parentTerrain.terrainData.size.z / terraPeaces; float spaceShiftY = parentTerrain.terrainData.size.x / terraPeaces; float xWShift = (i % terraPeaces ) * spaceShiftX; float zWShift = ( i / terraPeaces ) * spaceShiftY; tgo.transform.position = new Vector3( tgo.transform.position.x + zWShift, tgo.transform.position.y, tgo.transform.position.z + xWShift ); // Shift last position tgo.transform.position = new Vector3( tgo.transform.position.x + parentPosition.x, tgo.transform.position.y + parentPosition.y, tgo.transform.position.z + parentPosition.z ); #endregion // Split height #region split height Debug.Log ( "Split height" ); //Copy heightmap td.heightmapResolution = parentTerrain.terrainData.heightmapResolution / terraPeaces; //Keep y same td.size = new Vector3( parentTerrain.terrainData.size.x / terraPeaces, parentTerrain.terrainData.size.y, parentTerrain.terrainData.size.z / terraPeaces ); float[,] parentHeight = parentTerrain.terrainData.GetHeights(0,0, parentTerrain.terrainData.heightmapResolution, parentTerrain.terrainData.heightmapResolution ); float[,] peaceHeight = new float[ parentTerrain.terrainData.heightmapResolution / terraPeaces + 1, parentTerrain.terrainData.heightmapResolution / terraPeaces + 1 ]; // Shift calc int heightShift = parentTerrain.terrainData.heightmapResolution / terraPeaces; int startX = 0; int startY = 0; int endX = 0; int endY = 0; if ( i==0 ) { startX = startY = 0; endX = endY = parentTerrain.terrainData.heightmapResolution / terraPeaces + 1; } if ( i==1 ) { startX = startY = 0; endX = parentTerrain.terrainData.heightmapResolution / terraPeaces + 1; endY = parentTerrain.terrainData.heightmapResolution / terraPeaces + 1; } if ( i==2 ) { startX = startY = 0; endX = parentTerrain.terrainData.heightmapResolution / terraPeaces + 1; endY = parentTerrain.terrainData.heightmapResolution / terraPeaces + 1; } if ( i==3 ) { startX = startY = 0; endX = parentTerrain.terrainData.heightmapResolution / terraPeaces + 1; endY = parentTerrain.terrainData.heightmapResolution / terraPeaces + 1; } // iterate for ( int x=startX;x< endX;x++) { EditorUtility.DisplayProgressBar("Split terrain","Split height", (float) x / ( endX - startX )); for ( int y=startY;y< endY;y++) { int xShift=0; int yShift=0; // if ( i==0 ) { xShift = 0; yShift = 0; } // if ( i==1 ) { xShift = heightShift; yShift = 0; } // if ( i==2 ) { xShift = 0; yShift = heightShift; } if ( i==3 ) { xShift = heightShift; yShift = heightShift; } float ph = parentHeight[ x + xShift,y + yShift]; peaceHeight[x ,y ] = ph; } } EditorUtility.ClearProgressBar(); // Set heightmap to child genTer.terrainData.SetHeights( 0,0, peaceHeight ); #endregion // Split splat map #region split splat map td.alphamapResolution = parentTerrain.terrainData.alphamapResolution / terraPeaces; float[,,] parentSplat = parentTerrain.terrainData.GetAlphamaps(0,0, parentTerrain.terrainData.alphamapResolution, parentTerrain.terrainData.alphamapResolution ); float[,,] peaceSplat = new float[ parentTerrain.terrainData.alphamapResolution / terraPeaces , parentTerrain.terrainData.alphamapResolution / terraPeaces, parentTerrain.terrainData.alphamapLayers ]; // Shift calc int splatShift = parentTerrain.terrainData.alphamapResolution / terraPeaces; if ( i==0 ) { startX = startY = 0; endX = endY = parentTerrain.terrainData.alphamapResolution / terraPeaces; } if ( i==1 ) { startX = startY = 0; endX = parentTerrain.terrainData.alphamapResolution / terraPeaces; endY = parentTerrain.terrainData.alphamapResolution / terraPeaces; } if ( i==2 ) { startX = startY = 0; endX = parentTerrain.terrainData.alphamapResolution / terraPeaces; endY = parentTerrain.terrainData.alphamapResolution / terraPeaces; } if ( i==3 ) { startX = startY = 0; endX = parentTerrain.terrainData.alphamapResolution / terraPeaces; endY = parentTerrain.terrainData.alphamapResolution / terraPeaces; } // iterate for ( int s=0;s 0f && ti.position.x < 0.5f && ti.position.z > 0f && ti.position.z < 0.5f ) { // Recalculate new tree position ti.position = new Vector3( ti.position.x * 2f, ti.position.y, ti.position.z * 2f ); // Add tree instance genTer.AddTreeInstance( ti ); } // Second section if ( i==1 && ti.position.x > 0.0f &&ti.position.x < 0.5f && ti.position.z >= 0.5f && ti.position.z <= 1.0f ) { // Recalculate new tree position ti.position = new Vector3( (ti.position.x ) * 2f, ti.position.y, ( ti.position.z - 0.5f ) * 2f ); // Add tree instance genTer.AddTreeInstance( ti ); } // Third section if ( i==2 && ti.position.x >= 0.5f && ti.position.x <= 1.0f && ti.position.z > 0.0f && ti.position.z < 0.5f ) { // Recalculate new tree position ti.position = new Vector3( (ti.position.x - 0.5f ) * 2f, ti.position.y, ( ti.position.z ) * 2f ); // Add tree instance genTer.AddTreeInstance( ti ); } // Fourth section if ( i==3 && ti.position.x >= 0.5f && ti.position.x <= 1.0f && ti.position.z >= 0.5f && ti.position.z <= 1.0f ) { // Recalculate new tree position ti.position = new Vector3( (ti.position.x - 0.5f ) * 2f, ti.position.y, ( ti.position.z - 0.5f ) * 2f ); // Add tree instance genTer.AddTreeInstance( ti ); } } #endregion AssetDatabase.SaveAssets(); } EditorUtility.ClearProgressBar(); } void OnGUI() { if(GUILayout.Button("Split terrain")) { SplitIt(); } } }