상속: MonoBehaviour
    private static void ApplyTexturesToNewTerrain(TerrainData terrainData, TextureData data)
    {
        if (data.ControlTextureResolution != terrainData.alphamapResolution)
        {
            data.AdjustSplatMapResolution(terrainData.alphamapResolution);
        }

        terrainData.SetAlphamaps(0, 0, data.SplatMaps);
    }
	/// <summary>
	/// Creates terrain data from heights.
	/// </summary>
	/// <param name="heightPercents">Terrain height percentages ranging from 0 to 1.</param>
	/// <param name="maxHeight">The maximum height of the terrain, corresponding to a height percentage of 1.</param>
	/// <param name="heightSampleDistance">The horizontal/vertical distance between height samples.</param>
	/// <param name="splatPrototypes">The textures used by the terrain.</param>
	/// <param name="alphaMap">Texture blending information.</param>
	/// <returns>A TerrainData instance.</returns>
	public static TerrainData CreateTerrainData(float[,] heightPercents, float maxHeight, float heightSampleDistance, SplatPrototype[] splatPrototypes, float[,,] alphaMap)
	{
		Debug.Assert((heightPercents.GetLength(0) == heightPercents.GetLength(1)) && (maxHeight >= 0) && (heightSampleDistance >= 0));

		// Create the TerrainData.
		var terrainData = new TerrainData();
		terrainData.heightmapResolution = heightPercents.GetLength(0);

		var terrainWidth = (terrainData.heightmapResolution - 1) * heightSampleDistance;

		// If maxHeight is 0, leave all the heights in terrainData at 0 and make the vertical size of the terrain 1 to ensure valid AABBs.
		if(!Mathf.Approximately(maxHeight, 0))
		{
			terrainData.size = new Vector3(terrainWidth, maxHeight, terrainWidth);

			terrainData.SetHeights(0, 0, heightPercents);
		}
		else
		{
			terrainData.size = new Vector3(terrainWidth, 1, terrainWidth);
		}

		// Texture the terrain.
		if((splatPrototypes != null) && (alphaMap != null))
		{
			Debug.Assert(alphaMap.GetLength(0) == alphaMap.GetLength(1));

			terrainData.alphamapResolution = alphaMap.GetLength(0);
			terrainData.splatPrototypes = splatPrototypes;
			terrainData.SetAlphamaps(0, 0, alphaMap);
		}

		return terrainData;
	}
예제 #3
0
파일: plane.cs 프로젝트: andywatts/UnityGod
 void Start()
 {
     tData = myTerrain.terrainData;
     xResolution = tData.heightmapWidth;
     zResolution = tData.heightmapHeight;
     heights = tData.GetHeights(0, 0, xResolution, zResolution);
 }
    void OnGUI()
    {
        tWidth = EditorGUILayout.IntField("Terrain Width", tWidth);
        tHeight = EditorGUILayout.IntField("Terrain Height", tHeight);
        tDepth = EditorGUILayout.IntField("Terrain Depth", tDepth);

        EditorGUILayout.Separator();

        cellWidth = EditorGUILayout.IntSlider("Cell Width", cellWidth, 1, 512);
        cellDepth = EditorGUILayout.IntSlider("Cell Depth", cellDepth, 1, 512);
        cliffLevel = EditorGUILayout.FloatField("Cliff Height", cliffLevel);

        EditorGUILayout.Separator();

        if (GUILayout.Button("Create"))
        {
            TerrainData terData = new TerrainData() { size = new Vector3(tWidth, tHeight, tDepth), name = "Map Terrain", heightmapResolution = 512, baseMapResolution = 1024 };
            GameObject ter = Terrain.CreateTerrainGameObject(terData);
            ter.name = "Map";
            Gridmap gmap = ter.AddComponent<Gridmap>();
            gmap.cellWidth = cellWidth;
            gmap.cellDepth = cellDepth;
            gmap.cliffHeight = cliffLevel;
            isVisible = false;
            this.Close();
        }
        else if (GUILayout.Button("Cancel"))
        {
            isVisible = false;
            this.Close();
        }
    }
예제 #5
0
    // Update is called once per frame
    void Update()
    {
        transform.Translate(Vector3.forward * Time.deltaTime * Speed);

        if (transform.position.z >= 2 + float.Epsilon && !go)
        {
            go = true;
            GameObject terrain;
            TerrainData _terraindata = new TerrainData();
            TerrainData t = gameObject.GetComponent<Terrain>().terrainData;
            terrain = Terrain.CreateTerrainGameObject(t);

            GameObject ingameTerrainGameObject = (GameObject)Instantiate(terrain, StartPos, Quaternion.identity);
            //GenerateHeights(gameObject.GetComponent<Terrain>(), 2f);
            ingameTerrainGameObject.AddComponent<MoveTerrain>();

            Destroy(terrain);

            Destroy(gameObject);

        }

        /*if (transform.position.z > 20 + float.Epsilon)
            Destroy(gameObject);*/
    }
예제 #6
0
	private void getTerrain (){
		if(Terrain.activeTerrain != null){
			r_Terrain = Terrain.activeTerrain;
			r_TerrainData = r_Terrain.terrainData;
			r_TerrainPos = r_Terrain.transform.position;
		}
	}
예제 #7
0
	void Update()
	{
		terrain = GetComponent<Terrain>();
		tData = terrain ? terrain.terrainData : null;
		tMaterial = terrain ? terrain.materialTemplate : null;
		if (!terrain || !tData || !tMaterial)
			return;
		
		if(disableBasemap && !Application.isPlaying && GetComponent<Terrain>().basemapDistance != 1000000) // only reset on update in edit mode
			GetComponent<Terrain>().basemapDistance = 1000000;
		if (cutoutMode)
		{
			if (tMaterial.HasProperty("_CutoutModeHideAlpha") && tMaterial.GetFloat("_CutoutModeHideAlpha") != cutoutModeHideAlpha)
				tMaterial.SetFloat("_CutoutModeHideAlpha", cutoutModeHideAlpha);
		}
		else
			if (tMaterial.HasProperty("_CutoutModeHideAlpha") && tMaterial.GetFloat("_CutoutModeHideAlpha") != -1)
				tMaterial.SetFloat("_CutoutModeHideAlpha", -1);

		if (!Application.isPlaying)
			ApplyTransparencyMap();
		else
			if (!transparencyMap && autoUpdateTransparencyMap)
			{
				UpdateTransparencyMap();
				ApplyTransparencyMap();
			}
			else
				ApplyTransparencyMap();
	}
예제 #8
0
    public int FindTree(Vector3 location)
    {
        terra = Terrain.activeTerrain.terrainData;
        trees = terra.treeInstances;
        float maxDistance = float.MaxValue;
        //int closestIndice = 0;
        //Vector3 closestTreePos = new Vector3();
        int treeType = -1;
        //float heightScale = 1;
        //float widthScale = 1;

        for (int i = 0; i < terra.treeInstances.Length; i++) {
            TreeInstance currentTree = trees[i];
            Vector3 currentTreeWorldPos = Vector3.Scale(currentTree.position, terra.size) + Terrain.activeTerrain.transform.position;
            float distance = Vector3.Distance(currentTreeWorldPos, location);
            if (distance < maxDistance) {
                maxDistance = distance;
                //closestIndice = i;
                //closestTreePos = currentTreeWorldPos;
                treeType = currentTree.prototypeIndex;
                //heightScale = currentTree.heightScale;
                //widthScale = currentTree.widthScale;
            }
        }

        return treeType;
    }
   void OnGUI()
   {
		go=EditorGUILayout.ObjectField("Terrain game object", go, typeof(GameObject), true) as GameObject;
		if (!go) return;
		Terrain terrainObject;
		terrainObject=go.GetComponent(typeof(Terrain)) as Terrain;
		if (!terrainObject) return;
		terrain=terrainObject.terrainData;
		terrainPos = terrainObject.transform.position;
		
        saveFormat = (SaveFormatRTPtweaked) EditorGUILayout.EnumPopup("Export Format", saveFormat);
		saveResolution = (SaveResolutionRTPtweaked) EditorGUILayout.EnumPopup("Resolution", saveResolution);
 
		EditorGUILayout.BeginHorizontal ();
		EditorGUILayout.LabelField("Slope range (" + Mathf.RoundToInt(loAngle) + "\u00B0 - " + Mathf.RoundToInt(hiAngle) + "\u00B0)");
		if (saveFormat==SaveFormatRTPtweaked.Triangles) {
	  		EditorGUILayout.MinMaxSlider(ref loAngle, ref hiAngle, 0, 90);
		}
		EditorGUILayout.EndHorizontal ();

		AnchorOffset=EditorGUILayout.Toggle("Anchor Offset", AnchorOffset);

		
 
      if (GUILayout.Button("Export"))
      {
         Export();
      }
   }
예제 #10
0
    void Awake()
    {
        Debug.Log("Awake WorldMap");
        MapTile tempMapTile;
        BitMapDecoder bmd = new BitMapDecoder(heightmap);
        terrainData = terrain.terrainData;
        int heighMapWidth = terrainData.heightmapWidth;
        int heighMapHeight = terrainData.heightmapHeight;
        float[,] tempFloat = terrainData.GetHeights(0, 0, heighMapWidth, heighMapHeight);
        tilesDictionary = new Dictionary<string, MapTile>();

        for (int z = 0; z < mapSizeZ; z++ ) {
            for (int x = 0; x < mapSizeX; x++) {
                tempMapTile = new MapTile(x,z);
                int height = BitMapDecoder.getHeightPos(x, z);
                tempMapTile.setY(height);
                //tempFloat[x*2+1, z*2+1] = height / 5;
                tempFloat[x * 2, z*2 * 2] = (float)height / 10;
                //tempFloat[x*2, z * 2+1] = height / 5;
                //tempFloat[x * 2 + 1, z * 2] = height / 5;

                tilesDictionary.Add(("x" + x.ToString() + "z" + z.ToString()), tempMapTile);
            }
        }
        terrain.terrainData.SetHeights(0, 0, tempFloat);
    }
	void Start () {
		tData = Terrain.activeTerrain.terrainData;
		
		SplatPrototype[] terrainTexture = new SplatPrototype[1]; 
		terrainTexture[0] = new SplatPrototype(); 
		terrainTexture[0].texture = (Texture2D)Resources.Load("MyTextures/Dirt");
		tData.splatPrototypes = terrainTexture;  
	}
    public static void UpdateControlTextureResolution(TerrainData terrainData, int newResolution)
    {
        var existingData = GetTerrainTextures(terrainData);

        terrainData.alphamapResolution = newResolution;

        ApplyTexturesToNewTerrain(terrainData, existingData);
    }
 private static TextureData GetTerrainTextures(TerrainData terrainData)
 {
     return new TextureData
            {
                SplatMaps = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight),
                ControlTextureResolution = terrainData.alphamapResolution
            };
 }
    /// <summary>
    /// </summary>
    /// <param name="terrainData"></param>
    /// <param name="position">Location in the XZ plane (not the XY plane!)</param>
    /// <param name="sphereRadius"></param>
    /// <returns></returns>
    private static Vector3 AdjustSpawnPositionForTerrainShape(TerrainData terrainData, Vector2 position, float sphereRadius)
    {
        var height = terrainData.GetInterpolatedHeight(position.x, position.y);
        var normal = terrainData.GetInterpolatedNormal(position.x, position.y);

        var offsetAlongNormal = normal * sphereRadius;
        var positionOnTerrain = new Vector3(position.x, height, position.y);
        return positionOnTerrain + offsetAlongNormal;
    }
예제 #15
0
파일: Area.cs 프로젝트: bpeake13/GGJ2016
 public Area(TerrainData owner, Block[] blocks)
 {
     m_owner = owner;
     
     foreach (Block point in blocks)
     {
         AddPoint(point);
     }
 }
예제 #16
0
 private TerrainData CreateTerrain()
 {
     TerrainData terrainData = new TerrainData ();
     terrainData.size = terrainPrefab.terrainData.size;
     terrainData.heightmapResolution = terrainPrefab.terrainData.heightmapHeight;
     terrainData.baseMapResolution = terrainPrefab.terrainData.baseMapResolution;
     terrainData.SetDetailResolution (terrainPrefab.terrainData.detailResolution, 1);
     return terrainData;
 }
예제 #17
0
 public void Awake()
 {
     waterScript = (WaterToolScript)target as WaterToolScript;
     terComponent = (Terrain) waterScript.GetComponent(typeof(Terrain));
     if(terComponent == null)
         Debug.LogError("This script must be attached to a terrain object - Null reference will be thrown");
     terData = terComponent.terrainData;
     terrainHeights = terData.GetHeights(0, 0, terData.heightmapResolution, terData.heightmapResolution);
 }
예제 #18
0
 void CopyTerrainDataFromTo(TerrainData tDataFrom, ref TerrainData tDataTo)
 {
     tDataTo.SetDetailResolution(tDataFrom.detailResolution, 8);
     tDataTo.heightmapResolution = tDataFrom.heightmapResolution;
     tDataTo.alphamapResolution = tDataFrom.alphamapResolution;
     tDataTo.baseMapResolution = tDataFrom.baseMapResolution;
     tDataTo.size = tDataFrom.size;
     tDataTo.splatPrototypes = tDataFrom.splatPrototypes;
 }
예제 #19
0
    public static string[] GetTerrainSplatNames(TerrainData d)
    {
        List<string> l = new List<string>();

        for (int i = 0; i < d.splatPrototypes.Length; ++i) {
            l.Add(d.splatPrototypes[i].texture.name);
        }

        return l.ToArray();
    }
예제 #20
0
    public TerrainTile(Terrain terrain, TerrainData tData, Vector3 index)
    {
        Terrain = terrain;
        TData = tData;
        TCollider = terrain.GetComponent<TerrainCollider>();
        Index = index;
        InUse = false;

        Terrain.terrainData = TData;
        TCollider.terrainData = TData;
    }
예제 #21
0
    void checkTerrain(JSONNode mines)
    {
        terrain_data = terrain.terrainData;

        //		var pos = mines[0];
        //		float x = pos[0].AsFloat, y = pos[1].AsFloat, z = pos[2].AsFloat;
        //		Debug.Log ("mine0: x: " + x + ", " + "z: " + z + ", " + "y: " + y);
        //		Debug.Log ("InterpolatedHeight: " + terrain_data.GetInterpolatedHeight((x+150.0f)/300.0f, (z+150.0f)/300.0f));
        //
        //		pos = mines[1];
        //		x = pos [0].AsFloat; y = pos [1].AsFloat; z = pos[2].AsFloat;
        //		Debug.Log ("mine1: x: " + x + ", " + "z: " + z + ", " + "y: " + y);
        //		Debug.Log ("InterpolatedHeight: " + terrain_data.GetInterpolatedHeight((x+150.0f)/300.0f, (z+150.0f)/300.0f));
        //
        //		pos = mines[2];
        //		x = pos [0].AsFloat; y = pos[1].AsFloat; z = pos[2].AsFloat;
        //		Debug.Log ("mine2: x: " + x + ", " + "z: " + z + ", " + "y: " + y);
        //		Debug.Log ("InterpolatedHeight: " + terrain_data.GetInterpolatedHeight((x+150.0f)/300.0f, (z+150.0f)/300.0f));

        float[] x = new float[200];
        float[] y = new float[200];
        int mine_num = 200;
        for (int i = 0; i < mine_num; i++){
            var pos = mines[i];
            float px = pos[0].AsFloat, py = pos[1].AsFloat, pz = pos[2].AsFloat;
            x[i] = terrain_data.GetInterpolatedHeight((px+150.0f)/300.0f, (pz+150.0f)/300.0f);
            y[i] = py;
            Debug.Log(i);
        }

        float mxy = 0;
        float mx = 0;
        float mx2 = 0;
        float my = 0;
        for (int i = 0; i < mine_num; i++){
            mx += x[i];
            mx2 += x[i] * x[i];
            my += y[i];
            mxy += x[i]*y[i];
        }
        mx /= mine_num;
        mx2 /= mine_num;
        my /= mine_num;
        mxy /= mine_num;

        float a_up = mxy - mx * my;
        float a_down = mx2 - mx * mx;
        float a = a_up / a_down;

        float b = my - a * mx;

        Debug.Log("a: "+a);
        Debug.Log("b: "+b);
    }
    public static Mesh createMesh(TerrainData t, Vector3 terrainPosition)
    {
        Mesh m = new Mesh();

        int w = t.heightmapWidth;
        int h = t.heightmapHeight;
        Vector3 meshScale = t.size;
        int tRes = 2;
        meshScale = new Vector3(meshScale.x / (w - 1) * tRes, meshScale.y, meshScale.z / (h - 1) * tRes);

        float[,] tData = t.GetHeights(0, 0, w, h);

        w = (w - 1) / tRes + 1;
        h = (h - 1) / tRes + 1;

        Vector3[] tVertices = new Vector3[w * h];

        int[] tPolys;

        tPolys = new int[(w - 1) * (h - 1) * 6];

        // Build vertices
        for (int y = 0; y < h; y++)
        {
            for (int x = 0; x < w; x++)
            {
                tVertices[y * w + x] = Vector3.Scale(meshScale, new Vector3(-y, tData[x * tRes, y * tRes], x)) + terrainPosition;
            }
        }

        int index = 0;

        // Build triangle indices: 3 indices into vertex array for each triangle
        for (int y = 0; y < h - 1; y++)
        {
            for (int x = 0; x < w - 1; x++)
            {
                // For each grid cell output two triangles
                tPolys[index++] = (y * w) + x;
                tPolys[index++] = ((y + 1) * w) + x;
                tPolys[index++] = (y * w) + x + 1;

                tPolys[index++] = ((y + 1) * w) + x;
                tPolys[index++] = ((y + 1) * w) + x + 1;
                tPolys[index++] = (y * w) + x + 1;
            }
        }

        m.vertices = tVertices;
        m.triangles = tPolys;
        m.subMeshCount = 1;

        return m;
    }
    void Start()
    {
        terrain = transform.GetComponent<Terrain>();
        tData = terrain.terrainData;

        xRes = tData.heightmapWidth;
        yRes = tData.heightmapHeight;

        Debug.Log (xRes + "," + yRes);

        initializePoints();
    }
예제 #24
0
 private void _generateNoise(System.Random rng, TerrainData data)
 {
     int width = data.Width;
     int height = data.Height;
     for (int y = 0; y < height; y++)
     {
         for(int x = 0; x < width; x++)
         {
             data.SetValue(x, y, rng.NextDouble() < m_randomFillChance ? 1 : 0);
         }
     }
 }
	void Start () 
	{		
		if (terrain == null) 
		{
			terrain = Terrain.activeTerrain;
            if (terrain != null)
            {
                terrainData = terrain.terrainData;
                terrainPos = terrain.transform.position;
            }
		}
	}
예제 #26
0
	void Start() 
	{
		 //Only do anything when this is more optimized
		tData = Terrain.activeTerrain.terrainData;
		 //Get the Terrain
		lineMaterial = new Material(Shader.Find("Particles/Additive"));
		
		
		changingG = 0;
		
		//DrawLinesAnim();
	}
	///////////////////////////////////

	/**
	 * Initialise les attributs.
	 */
	void Start () {

		tData = this.GetComponent<Terrain>().terrainData;
		hMapTmp = null;
		inCreation = false;
		canAddTexture = false;

		player = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
		soundController = GameObject.FindGameObjectWithTag("Music").GetComponent<SoundController>();

		InitTerrain();
	}
예제 #28
0
    private void Awake()
    {
        var terrain = GetComponent<Terrain>();

        var map = ReadMap(Filename);
        //var map = ReadMap(string.Format("{0}_{1}", 0, 0));
        //var map = GetRandomizedMap(33, 33, 0.2f);

        var data = new TerrainData { size = new Vector3(100f, 100f, 100f), heightmapResolution = 33 };

        terrain.terrainData = data;
        terrain.terrainData.SetHeights(0, 0, map);
    }
	public void GenerateTerrain(TerrainData terrainData, float tileSize)
	{
		if(disableProceduralTerrain)
			return;

		_heightMap = new float[terrainData.heightmapWidth, terrainData.heightmapHeight];

		float width_2 = terrainData.heightmapWidth*0.5f;
		float height_2 = terrainData.heightmapHeight*0.5f;

		float aW = MathHelpers.RandomFromVec2(aWMinMax);
		float bW = MathHelpers.RandomFromVec2(bWMinMax);
		float cW = MathHelpers.RandomFromVec2(cWMinMax);
		float dW = MathHelpers.RandomFromVec2(dWMinMax);
		
		float bH = MathHelpers.RandomFromVec2(bHMinMax);
		float cH = MathHelpers.RandomFromVec2(cHMinMax);
	

		for (int i = 0; i < terrainData.heightmapWidth; i++)
		{
			for (int k = 0; k < terrainData.heightmapHeight; k++)
			{
				float xW = (float)(i - width_2);
				float xH = (float)(k - height_2);
				float heightAdjustW = aW*Mathf.Exp(- (Mathf.Pow((xW -bW),2)/(2*Mathf.Pow(cW,2)) + Mathf.Pow((xH-bH),2)/(2*Mathf.Pow(cH,2)))) + dW;

				_heightMap[i, k] = heightAdjustW +  MathHelpers.RandomFromVec2( perlinNoiseAmpMinMax )*Mathf.PerlinNoise(((float)i / (float)terrainData.heightmapWidth) * tileSize, ((float)k / (float)terrainData.heightmapHeight) * tileSize);
			}
		}

		terrainData.SetHeights(0, 0, _heightMap);

		SplatPrototype groundProto = new SplatPrototype();
		groundProto.texture = terrainTexture;
		groundProto.tileOffset = new Vector2(0f,0f);
		groundProto.tileSize = new Vector2(10f,10f);

		SplatPrototype snowProto = new SplatPrototype();
		snowProto.texture = snowTexture;
		snowProto.tileOffset = new Vector2(0f,0f);
		snowProto.tileSize = new Vector2(10f,10f);

		SplatPrototype[] prototypes = new SplatPrototype[2];
		prototypes[0] = groundProto;
		prototypes[1] = snowProto;
		terrainData.splatPrototypes = prototypes;

		_terrainTransform.localPosition = new Vector3( -0.5f*terrainData.size.x,0f,-0.5f*terrainData.size.z );

	}
예제 #30
0
    public override void Construct(TerrainData data)
    {
        Vector3 position = transform.position;

        for (int y = 0; y < data.Height; y++)
        {
            for (int x = 0; x < data.Width; x++)
            {
                if (data.GetData(x, y) > 0)
                {
                    float worldX = x * m_blockSize + position.x;
                    float worldZ = y * m_blockSize + position.z;
                    float worldY = position.y;

                    GameObject newBlock = (GameObject) Instantiate(m_blocks[data.GetData(x, y) - 1], new Vector3(worldX, worldY, worldZ),
                        Quaternion.identity);
                }
            }
        }

        List<EmptyTerrainBlock> emptyTerrain = new List<EmptyTerrainBlock>(FindObjectsOfType<EmptyTerrainBlock>());

        int bodyBlock = Random.Range(0, emptyTerrain.Count);
        Instantiate(m_bodyItems[Random.Range(0, m_bodyItems.Length)], emptyTerrain[bodyBlock].transform.position + Vector3.up * m_blockSize * 0.5f + Vector3.up * m_itemOffset, Quaternion.identity);
        emptyTerrain.RemoveAt(bodyBlock);

        int headBlock = Random.Range(0, emptyTerrain.Count);
        Instantiate(m_headItems[Random.Range(0, m_headItems.Length)], emptyTerrain[headBlock].transform.position + Vector3.up * m_blockSize * 0.5f + Vector3.up * m_itemOffset, Quaternion.identity);
        emptyTerrain.RemoveAt(headBlock);

        int leftArm = Random.Range(0, emptyTerrain.Count);
        Instantiate(m_armItems[Random.Range(0, m_armItems.Length)], emptyTerrain[leftArm].transform.position + Vector3.up * m_blockSize * 0.5f + Vector3.up * m_itemOffset, Quaternion.identity);
        emptyTerrain.RemoveAt(leftArm);

        int rightArm = Random.Range(0, emptyTerrain.Count);
        Instantiate(m_armItems[Random.Range(0, m_armItems.Length)], emptyTerrain[rightArm].transform.position + Vector3.up * m_blockSize * 0.5f + Vector3.up * m_itemOffset, Quaternion.identity);
        emptyTerrain.RemoveAt(rightArm);

        int leftLeg = Random.Range(0, emptyTerrain.Count);
        Instantiate(m_legItems[Random.Range(0, m_legItems.Length)], emptyTerrain[leftLeg].transform.position + Vector3.up * m_blockSize * 0.5f + Vector3.up * m_itemOffset, Quaternion.identity);
        emptyTerrain.RemoveAt(leftLeg);

        int rightLeg = Random.Range(0, emptyTerrain.Count);
        Instantiate(m_legItems[Random.Range(0, m_legItems.Length)], emptyTerrain[rightLeg].transform.position + Vector3.up * m_blockSize * 0.5f + Vector3.up * m_itemOffset, Quaternion.identity);
        emptyTerrain.RemoveAt(rightLeg);

        int startBlock = Random.Range(0, emptyTerrain.Count);
        Instantiate(m_startArea, emptyTerrain[bodyBlock].transform.position + Vector3.up * m_blockSize * 0.5f,
            Quaternion.identity);
        emptyTerrain.RemoveAt(startBlock);
    }
예제 #31
0
        public override void Sync(Component c)
        {
            Terrain terrainObject = c as Terrain;

            this.name = "cc.Terrain";

            TerrainData terrain = terrainObject.terrainData;

            var terrainLayers = terrain.terrainLayers;
            var alphaMaps     = terrain.GetAlphamaps(0, 0, terrain.alphamapWidth, terrain.alphamapHeight);

            for (var i = 0; i < terrainLayers.Length; i++)
            {
                SyncTerrainLayer layer = new SyncTerrainLayer();
                layer.name = terrainLayers[i].name;
                this.terrainLayers.Add(layer);
            }

            // weight datas
            int weightmapWidth  = terrain.alphamapWidth;
            int weightmapHeight = terrain.alphamapHeight;

            float[] allWeightDatas = new float[weightmapWidth * weightmapHeight * terrainLayers.Length];
            for (var i = 0; i < weightmapWidth; i++)
            {
                for (var j = 0; j < weightmapHeight; j++)
                {
                    for (var k = 0; k < terrainLayers.Length; k++)
                    {
                        var value = alphaMaps[j, i, k];
                        if (Single.IsNaN(value))
                        {
                            value = 0;
                        }

                        int index = (i + j * weightmapWidth) * terrainLayers.Length + k;
                        allWeightDatas[index] = value;
                    }
                }
            }


            // height datas
            int heightmapWidth  = terrain.heightmapResolution;
            int heightmapHeight = terrain.heightmapResolution;

            var tData  = terrain.GetHeights(0, 0, heightmapWidth, heightmapHeight);
            var height = terrain.size.y;

            float[] allHeightDatas = new float[heightmapWidth * heightmapHeight];
            for (var i = 0; i < heightmapWidth; i++)
            {
                for (var j = 0; j < heightmapHeight; j++)
                {
                    allHeightDatas[i + j * heightmapWidth] = tData[j, i] * height;
                }
            }

            this.weightDatas     = allWeightDatas;
            this.heightmapWidth  = heightmapWidth;
            this.heightmapHeight = heightmapHeight;

            this.heightDatas     = allHeightDatas;
            this.weightmapWidth  = weightmapWidth;
            this.weightmapHeight = weightmapHeight;

            this.terrainWidth  = terrain.size.x;
            this.terrainHeight = terrain.size.y;
        }
예제 #32
0
    public void ExportTerrainData()
    {
        totalPath  = Application.dataPath + "/TerrainData/";
        assetsPath = "Assets/TerrainData/";

        data       = Terrain.activeTerrain.terrainData;
        totalPath  = totalPath + mapName;
        assetsPath = assetsPath + mapName;
        if (!Directory.Exists(totalPath))
        {
            Directory.CreateDirectory(totalPath);
        }

        float[,] tempHeights = data.GetHeights(0, 0, data.heightmapWidth, data.heightmapHeight);
        heightmapWidth       = data.heightmapHeight;
        heightmapHeight      = data.heightmapWidth;
        heights = new float[heightmapWidth, heightmapHeight];
        for (int i = 0; i < heightmapHeight; i++)
        {
            for (int j = 0; j < heightmapWidth; j++)
            {
                heights[i, j] = tempHeights[j, i];
            }
        }

        normals   = new Vector3[data.heightmapWidth, data.heightmapHeight];
        maxHeight = data.size.y;


        SaveHeightNormalMap();

        if (isChunk)
        {
            chunkCountX      = (int)(data.size.x / chunkWidth) + (data.size.x % chunkWidth != 0 ? 1 : 0);
            chunkCountZ      = (int)(data.size.z / chunkLength) + (data.size.z % chunkLength != 0 ? 1 : 0);
            chunkPixelCountX = (int)(heightmapWidth * chunkWidth / data.size.x) + 1;
            chunkPixelCountZ = (int)(heightmapHeight * chunkLength / data.size.z) + 1;

            string chunkPath = totalPath + "/Chunks";
            if (!Directory.Exists(chunkPath))
            {
                Directory.CreateDirectory(chunkPath);
            }
            if (isSaveGPUMesh)
            {
                SaveTerrainMesh(chunkWidth, chunkLength, assetsPath, true);
                if (isDivideMaterial)
                {
                    SaveChunkHeightNormalMap(chunkPath);
                    SaveChunkTerrainMaterial(assetsPath + "/Chunks");
                    SaveChunkPrefab(assetsPath);
                }
                //SaveChunkTotalPrefab(assetsPath);
            }
            if (isSaveCPUMesh)
            {
                SaveChunkHeightMesh(assetsPath + "/Chunks");
            }
        }
        else
        {
            chunkCountX      = 1;
            chunkCountZ      = 1;
            chunkPixelCountX = heightmapWidth;
            chunkPixelCountZ = heightmapHeight;
        }


        if (isSaveCPUMesh)
        {
            SaveHeightMesh();
        }

        if (isSaveGPUMesh)
        {
            SaveTerrainMesh(data.size.x, data.size.z, assetsPath, false);
            if (isDivideMaterial)
            {
                SaveTotalTerrainMaterial();
                SaveTotalPrefab();
            }
        }

        if (isGPUInstance)
        {
            SaveInstancePrefab();
        }
    }
예제 #33
0
        public override bool OnPaint(Terrain terrain, IOnPaint editContext)
        {
            if (m_TargetTerrain == null ||
                selectedDetail == kInvalidDetail ||
                selectedDetail >= m_TargetTerrain.terrainData.detailPrototypes.Length)
            {
                return(false);
            }

            Texture2D brush = editContext.brushTexture as Texture2D;

            if (brush == null)
            {
                Debug.LogError("Brush texture is not a Texture2D.");
                return(false);
            }

            if (m_BrushRep == null)
            {
                m_BrushRep = new BrushRep();
            }

            PaintTreesDetailsContext ctx = PaintTreesDetailsContext.Create(terrain, editContext.uv);

            for (int t = 0; t < ctx.terrains.Length; ++t)
            {
                Terrain ctxTerrain = ctx.terrains[t];
                if (ctxTerrain != null)
                {
                    int detailPrototype = PaintDetailsUtils.FindDetailPrototype(ctxTerrain, m_TargetTerrain, selectedDetail);
                    if (detailPrototype == kInvalidDetail)
                    {
                        detailPrototype = PaintDetailsUtils.CopyDetailPrototype(ctxTerrain, m_TargetTerrain, selectedDetail);
                    }

                    TerrainData terrainData = ctxTerrain.terrainData;

                    TerrainPaintUtilityEditor.UpdateTerrainDataUndo(terrainData, "Terrain - Detail Edit");

                    int size = (int)Mathf.Max(1.0f, editContext.brushSize * ((float)terrainData.detailResolution / terrainData.size.x));

                    m_BrushRep.CreateFromBrush(brush, size);

                    Vector2 ctxUV = ctx.uvs[t];

                    int xCenter = Mathf.FloorToInt(ctxUV.x * terrainData.detailWidth);
                    int yCenter = Mathf.FloorToInt(ctxUV.y * terrainData.detailHeight);

                    int intRadius   = Mathf.RoundToInt(size) / 2;
                    int intFraction = Mathf.RoundToInt(size) % 2;

                    int xmin = xCenter - intRadius;
                    int ymin = yCenter - intRadius;

                    int xmax = xCenter + intRadius + intFraction;
                    int ymax = yCenter + intRadius + intFraction;

                    if (xmin >= terrainData.detailWidth || ymin >= terrainData.detailHeight || xmax <= 0 || ymax <= 0)
                    {
                        continue;
                    }

                    xmin = Mathf.Clamp(xmin, 0, terrainData.detailWidth - 1);
                    ymin = Mathf.Clamp(ymin, 0, terrainData.detailHeight - 1);

                    xmax = Mathf.Clamp(xmax, 0, terrainData.detailWidth);
                    ymax = Mathf.Clamp(ymax, 0, terrainData.detailHeight);

                    int width  = xmax - xmin;
                    int height = ymax - ymin;

                    float targetStrength = detailStrength;
                    if (Event.current.shift || Event.current.control)
                    {
                        targetStrength = -targetStrength;
                    }

                    int[] layers = { detailPrototype };
                    if (targetStrength < 0.0F && !Event.current.control)
                    {
                        layers = terrainData.GetSupportedLayers(xmin, ymin, width, height);
                    }

                    for (int i = 0; i < layers.Length; i++)
                    {
                        int[,] alphamap = terrainData.GetDetailLayer(xmin, ymin, width, height, layers[i]);

                        for (int y = 0; y < height; y++)
                        {
                            for (int x = 0; x < width; x++)
                            {
                                int   xBrushOffset = (xmin + x) - (xCenter - intRadius + intFraction);
                                int   yBrushOffset = (ymin + y) - (yCenter - intRadius + intFraction);
                                float opa          = detailOpacity * m_BrushRep.GetStrengthInt(xBrushOffset, yBrushOffset);

                                float targetValue = Mathf.Lerp(alphamap[y, x], targetStrength, opa);
                                alphamap[y, x] = Mathf.RoundToInt(targetValue - .5f + Random.value);
                            }
                        }

                        terrainData.SetDetailLayer(xmin, ymin, layers[i], alphamap);
                    }
                }
            }

            return(false);
        }
예제 #34
0
    void ConsumeTerrainTriangles(TerrainData terrain, GameObject gameObject)
    {
        Vector3 terrainPos = gameObject.transform.position;
        //GwNavTag navTag = BuildNavTag(gameObject);

        int vertexCount_x = terrain.heightmapWidth;
        int vertexCount_z = terrain.heightmapHeight;

        float sampleWidthInMeter  = terrain.size.x / (terrain.heightmapWidth - 1);
        float sampleHeightInMeter = terrain.size.z / (terrain.heightmapHeight - 1);

        for (int z = 0; z < vertexCount_z - 1; ++z)
        {
            for (int x = 0; x < vertexCount_x - 1; ++x)
            {
                Vector3 A = GetTerrainVertex(terrain, x, z, sampleWidthInMeter, sampleHeightInMeter) + terrainPos;
                Vector3 B = GetTerrainVertex(terrain, x + 1, z, sampleWidthInMeter, sampleHeightInMeter) + terrainPos;
                Vector3 C = GetTerrainVertex(terrain, x + 1, z + 1, sampleWidthInMeter, sampleHeightInMeter) + terrainPos;
                Vector3 D = GetTerrainVertex(terrain, x, z + 1, sampleWidthInMeter, sampleHeightInMeter) + terrainPos;

//                 RecastNavigationDllImports.PushTriangleWithNavTag(A, B, C);
//                 RecastNavigationDllImports.PushTriangleWithNavTag(A, C, D);
                RecastNavigationDllImports.PushTriangleWithNavTag(C, B, A);
                RecastNavigationDllImports.PushTriangleWithNavTag(D, C, A);
                totalTriangleCount += 2;
            }
        }

        float treeRadius = 0.3f;
        float treeHeight = 5.0f;

        //navTag.m_isExclusive = true;
        foreach (TreeInstance tree in terrain.treeInstances)
        {
            Vector3 center = Vector3.Scale(terrain.size, tree.position) + terrainPos;
            Vector3 baseA  = new Vector3(center.x - treeRadius, center.y, center.z - treeRadius);
            Vector3 baseB  = new Vector3(center.x + treeRadius, center.y, center.z - treeRadius);
            Vector3 baseC  = new Vector3(center.x + treeRadius, center.y, center.z + treeRadius);
            Vector3 baseD  = new Vector3(center.x - treeRadius, center.y, center.z + treeRadius);

            Vector3 topA = baseA + Vector3.up * treeHeight;
            Vector3 topB = baseB + Vector3.up * treeHeight;
            Vector3 topC = baseC + Vector3.up * treeHeight;
            Vector3 topD = baseD + Vector3.up * treeHeight;

            /*
             * // Push base has non walkable
             * RecastNavigationDllImports.PushTriangleWithNavTag(baseA, baseB, baseC, navTag);
             * RecastNavigationDllImports.PushTriangleWithNavTag(baseA, baseC, baseD, navTag);
             * totalTriangleCount +=2;
             */

            // Push trunk as a vertical square based tube
            // Front
            RecastNavigationDllImports.PushTriangleWithNavTag(baseA, baseB, topB);
            RecastNavigationDllImports.PushTriangleWithNavTag(baseA, topB, topA);
            // Right
            RecastNavigationDllImports.PushTriangleWithNavTag(baseB, baseC, topC);
            RecastNavigationDllImports.PushTriangleWithNavTag(baseB, topC, topB);
            // Back
            RecastNavigationDllImports.PushTriangleWithNavTag(baseC, baseD, topD);
            RecastNavigationDllImports.PushTriangleWithNavTag(baseC, topD, topC);
            // Left
            RecastNavigationDllImports.PushTriangleWithNavTag(baseD, baseA, topA);
            RecastNavigationDllImports.PushTriangleWithNavTag(baseD, topA, topD);
            totalTriangleCount += 8;
        }
    }
예제 #35
0
    /// <summary>
    /// 创建单块地图
    /// </summary>
    /// <param name="tdData"></param>
    private void CreateTerrain(TDData tdData)
    {
        // 设置TerrainData的基础参数
        TerrainData terrainData = new TerrainData();

        terrainData.heightmapResolution = head.ResolutionSize + 1;
        terrainData.SetDetailResolution(head.ResolutionSize, 8);
        terrainData.alphamapResolution = head.ResolutionSize * 2;
        terrainData.baseMapResolution  = head.ResolutionSize;
        terrainData.size = head.terrainSize;

        terrainData.detailPrototypes = details;
        terrainData.treePrototypes   = trees;
        terrainData.terrainLayers    = splats;
        terrainData.RefreshPrototypes();

        // 高度,贴图,细节设置
        if (tdData.heightMap != null)
        {
            terrainData.SetHeights(0, 0, tdData.heightMap);
        }

        if (tdData.detailMap != null)
        {
            for (int i = 0; i < tdData.detailMap.Length; i++)
            {
                terrainData.SetDetailLayer(0, 0, i, tdData.detailMap[i]);
            }
        }

        if (tdData.alphaMap != null)
        {
            terrainData.SetAlphamaps(0, 0, tdData.alphaMap);
        }

        // 在场景中创建Terrain实体并设置实体的参数
        GameObject newTerrainGameObject = Terrain.CreateTerrainGameObject(terrainData);

        newTerrainGameObject.name               = terrainData.name;
        newTerrainGameObject.isStatic           = false;
        newTerrainGameObject.transform.position = tdData.terrainPos;
        newTerrainGameObject.layer              = LayerMask.NameToLayer("Terrain");

        // 设置Terrain类的参数
        Terrain terrain = newTerrainGameObject.GetComponent <Terrain>();

        terrain.heightmapPixelError = head.heightmapPixelError;
        terrain.basemapDistance     = head.basemapDistance;
        terrain.drawHeightmap       = head.drawHeightmap;
        terrain.name = tdData.name;

        if (tdData.treePoses != null)
        {
            // 为地形添加树木实体
            for (int index = 0; index < tdData.treePoses.Length; index++)
            {
                for (int i = 0; i < tdData.treePoses[index].Length; i++)
                {
                    TreeInstance instance = TerrainUtility.GetTreeInstance(index);
                    instance.position = tdData.treePoses[index][i];
                    terrain.AddTreeInstance(instance);
                }
            }
        }

        newTerrainGameObject.transform.SetParent(terrainParent);
    }
예제 #36
0
 /// <summary>
 /// Calculate the new height after flattening
 /// </summary>
 /// <param name="currentHeight">Current terrain height</param>
 /// <param name="terrainData">The used terrain Data</param>
 /// <returns>The new height</returns>
 private float NewFlattenHeight(float targetHeight, TerrainData terrainData)
 {
     return(Mathf.Clamp(targetHeight, m_MinHeight / terrainData.size.y, m_MaxHeight / terrainData.size.y));
 }
예제 #37
0
    IEnumerator loadTerrainTile(TerrainTile tile)
    {
        // Create and position GameObject
        var terrainData = new TerrainData();

        terrainData.heightmapResolution = terrainResolution;
        terrainData.alphamapResolution  = tileSize;

        // Download the tile heightmap
        tile.url = baseUrl + tile.z + "/" + tile.x + "/" + tile.y + ".png";
        WWW www = new WWW(tile.url);

        while (!www.isDone)
        {
        }
        tile.heightmap = new Texture2D(terrainResolution, terrainResolution); //2049
        www.LoadImageIntoTexture(tile.heightmap);

        // Multidimensional array of this tiles heights in x/y
        float[,] terrainHeights = terrainData.GetHeights(0, 0, terrainResolution + 1, terrainResolution + 1);

        // Load colors into byte array
        Color[] pixelByteArray = tile.heightmap.GetPixels();

        if (flatTerrain)
        {
            for (int y = 0; y <= tileSize; y++)
            {
                for (int x = 0; x <= tileSize; x++)
                {
                    terrainHeights[y, x] = 0f;
                }
            }
        }
        else
        {
            for (int y = 0; y <= terrainResolution; y++)
            {
                for (int x = 0; x <= terrainResolution; x++)
                {
                    if (x == terrainResolution && y == terrainResolution)
                    {
                        terrainHeights[y, x] = pixelByteArray[(y - 1) * tileSize + (x - 1)].grayscale;
                    }
                    else if (x == terrainResolution)
                    {
                        terrainHeights[y, x] = pixelByteArray[(y) * tileSize + (x - 1)].grayscale;
                    }
                    else if (y == terrainResolution)
                    {
                        terrainHeights[y, x] = pixelByteArray[((y - 1) * tileSize) + x].grayscale;
                    }
                    else
                    {
                        terrainHeights[y, x] = pixelByteArray[y * tileSize + x].grayscale;
                    }
                }
            }
        }

        // Use the newly populated height data to apply the heightmap
        terrainData.SetHeights(0, 0, terrainHeights);

        // Set terrain size
        terrainData.size = new Vector3(terrainSize, terrainHeight, terrainSize);

        tile.terrain = Terrain.CreateTerrainGameObject(terrainData);
        tile.terrain.transform.position = new Vector3(tile.worldX * terrainSize, 0, tile.worldZ * terrainSize);

        tile.terrain.name = "tile_" + tile.x.ToString() + "_" + tile.y.ToString();

        yield return(null);
    }
예제 #38
0
    public static GameObject Spawn(GreebleDefinition greebleDefinition, Ray ray, float distance, Quaternion rotation, float maxSlope = 0.5f)
    {
        if (distance <= 0f)
        {
            return(null);
        }
        Vector3    vector = ray.origin;
        RaycastHit raycastHit;

        if (!Physics.Raycast(ray, out raycastHit, distance, greebleDefinition.SurfaceMask | greebleDefinition.KillMask))
        {
            return(null);
        }
        if ((greebleDefinition.KillMask.value & 1 << raycastHit.collider.gameObject.layer) > 0)
        {
            return(null);
        }
        if (Vector3.Dot(ray.direction, raycastHit.normal) > -maxSlope)
        {
            return(null);
        }
        bool flag = greebleDefinition.TerrainTextureMask != null && greebleDefinition.TerrainTextureMask.Length > 0;

        if (flag)
        {
            Terrain component = raycastHit.collider.GetComponent <Terrain>();
            if (component)
            {
                Vector3     position           = component.GetPosition();
                TerrainData terrainData        = component.terrainData;
                int         alphamapResolution = terrainData.alphamapResolution;
                int         num   = (int)((raycastHit.point.x - position.x) / terrainData.size.x * (float)alphamapResolution);
                int         num2  = (int)((raycastHit.point.z - position.z) / terrainData.size.z * (float)alphamapResolution);
                bool        flag2 = false;
                if (num >= 0 && num2 >= 0 && num < alphamapResolution && num2 < alphamapResolution)
                {
                    float[,,] alphamaps = component.terrainData.GetAlphamaps(num, num2, 1, 1);
                    float num3 = 0f;
                    int   num4 = -1;
                    for (int i = terrainData.alphamapLayers - 1; i >= 0; i--)
                    {
                        if (alphamaps[0, 0, i] > num3)
                        {
                            num3 = alphamaps[0, 0, i];
                            num4 = i;
                        }
                    }
                    if (num4 >= 0)
                    {
                        for (int j = 0; j < greebleDefinition.TerrainTextureMask.Length; j++)
                        {
                            if (greebleDefinition.TerrainTextureMask[j] == num4)
                            {
                                flag2 = true;
                                break;
                            }
                        }
                    }
                }
                if (!flag2)
                {
                    return(null);
                }
            }
        }
        vector = raycastHit.point;
        if (greebleDefinition.MatchSurfaceNormal)
        {
            Vector3    lhs        = Vector3.Cross(Vector3.forward, raycastHit.normal);
            Vector3    forward    = Vector3.Cross(lhs, raycastHit.normal);
            Quaternion quaternion = Quaternion.LookRotation(forward, raycastHit.normal);
            if (greebleDefinition.RandomizeRotation)
            {
                rotation = quaternion * rotation;
            }
            else
            {
                rotation = quaternion;
            }
        }
        vector   += rotation * greebleDefinition.Prefab.transform.position;
        rotation *= greebleDefinition.Prefab.transform.rotation;
        GameObject result;

        if (Application.isPlaying)
        {
            result = GreeblePlugin.Instantiate(greebleDefinition.Prefab, vector, rotation);
        }
        else
        {
            result = (GameObject)UnityEngine.Object.Instantiate(greebleDefinition.Prefab, vector, rotation);
        }
        return(result);
    }
		void Create()
		{
			// check lighting auto bake
			if (m_Settings.EnableLightingAutoBake)
			{
				UnityEditor.Lightmapping.giWorkflowMode = UnityEditor.Lightmapping.GIWorkflowMode.Iterative;
			}
			else
			{
				UnityEditor.Lightmapping.giWorkflowMode = UnityEditor.Lightmapping.GIWorkflowMode.OnDemand;
			}

			if (m_Settings.EnableClearExistingData)
			{
				ClearExistingTerrainGroup(m_Settings.GroupID);
			}

			// create tiles
			int tileCount = m_Settings.TilesX * m_Settings.TilesZ;
			Vector2Int tileOffset = Vector2Int.zero;
			Vector2Int tileOffsetSource = Vector2Int.zero;
			Vector2Int tileResolution = new Vector2Int(m_Settings.TerrainWidth / m_Settings.TilesX, m_Settings.TerrainLength / m_Settings.TilesZ);
			Vector3 tileSize = new Vector3(tileResolution.x, m_Settings.TerrainHeight, tileResolution.y);
			Vector3 tilePosition = m_Settings.StartPosition;
			Terrain[] terrains = new Terrain[tileCount];

			string assetFolderPath = GetAssetPathFromFullPath(m_Settings.TerrainAssetDirectory);
			int tileIndex = 0;			

			try
			{
				// create terrain grouping object
				string groupName = "TerrainGroup_" + m_Settings.GroupID;				
				GameObject terrainGroup = new GameObject(groupName);
				TerrainGroup groupComp = terrainGroup.AddComponent<TerrainGroup>();				
				terrainGroup.transform.position = m_Settings.StartPosition;
				Heightmap globalHeightmap = null;
				Vector2Int numHeightsPerTile = Vector2Int.zero;

				Undo.RegisterCreatedObjectUndo(terrainGroup, "Create terrain");

				if (m_Settings.UseGlobalHeightmap)
				{
					byte[] rawData = File.ReadAllBytes(m_Settings.GlobalHeightmapPath);
					globalHeightmap = new Heightmap(rawData, m_Settings.FlipMode);
					tileOffsetSource = new Vector2Int(globalHeightmap.Width / m_Settings.TilesX, globalHeightmap.Height / m_Settings.TilesZ);
				}
				else
				{
					tileOffsetSource = tileResolution;
				}

				for (int x = 0; x < m_Settings.TilesX; x++, tileOffset.x += tileOffsetSource.x, tilePosition.x += tileResolution.x)
				{
					tileOffset.y = 0;
					tilePosition.z = m_Settings.StartPosition.z;

					for (int y = 0; y < m_Settings.TilesZ; y++, tileOffset.y += tileOffsetSource.y, tilePosition.z += tileResolution.y)
					{
						EditorUtility.DisplayProgressBar("Creating terrains", string.Format("Updating terrain tile ({0}, {1})", x, y), ((float)tileIndex / tileCount));

						TerrainData terrainData = new TerrainData();
						terrainData.alphamapResolution = m_Settings.ControlTextureResolution;
						terrainData.baseMapResolution = m_Settings.BaseTextureResolution;
						terrainData.SetDetailResolution(m_Settings.DetailResolution, m_Settings.DetailResolutionPerPatch);						
						
						GameObject newGO = Terrain.CreateTerrainGameObject(terrainData);
						Terrain newTerrain = newGO.GetComponent<Terrain>();
						newTerrain.groupingID = m_Settings.GroupID;
						newTerrain.allowAutoConnect = m_Settings.AutoConnect;
						newTerrain.drawInstanced = m_Settings.DrawInstanced;
						newTerrain.heightmapPixelError = m_Settings.PixelError;
						newTerrain.basemapDistance = m_Settings.BaseMapDistance;
						if (m_Settings.MaterialOverride != null)
						{
							newTerrain.materialTemplate = m_Settings.MaterialOverride;
#if UNITY_2019_2_OR_NEWER
#else
							newTerrain.materialType = Terrain.MaterialType.Custom;
#endif
						}

						string terrainName = $"Terrain_{x}_{y}"; ;
						if (m_Settings.EnableGuid)
						{
							Guid newGuid = Guid.NewGuid();
							terrainName = $"Terrain_{x}_{y}_{newGuid}";
						}
						newGO.name = terrainName;
						newTerrain.transform.position = tilePosition;
						newTerrain.transform.SetParent(terrainGroup.transform);
						
						// import height
						if (m_Settings.HeightmapMode == Heightmap.Mode.Global && globalHeightmap != null)
						{
							Heightmap tileHeightmap = GetTileHeightmapFromGlobalHeightmap(globalHeightmap, tileOffset);
							tileHeightmap.ApplyTo(newTerrain);
						}

						if (m_Settings.HeightmapMode == Heightmap.Mode.Tiles || m_Settings.HeightmapMode == Heightmap.Mode.Batch)
						{
							if (File.Exists(m_Settings.TileHeightmapPaths[tileIndex]))
							{
								var remap = (m_Settings.HeightmapRemapMax - m_Settings.HeightmapRemapMin) / m_Settings.TerrainHeight;
								var baseLevel = m_Settings.HeightmapRemapMin / m_Settings.TerrainHeight;
								byte[] rawTileData = File.ReadAllBytes(m_Settings.TileHeightmapPaths[tileIndex]);
								Heightmap tileHeight = new Heightmap(rawTileData, m_Settings.FlipMode);
								Heightmap tileMap = new Heightmap(tileHeight, Vector2Int.zero, new Vector2Int(tileHeight.Width, tileHeight.Height), remap, baseLevel);
								tileMap.ApplyTo(newTerrain);
							}
						}

						terrains[tileIndex] = newTerrain;
						tileIndex++;

						// save terrain data asset
						terrainData.size = tileSize; // set terrain size after heightmap process
						string assetPath = $"{assetFolderPath}/{terrainName}.asset";
						if (!Directory.Exists(assetFolderPath))
						{
							Directory.CreateDirectory(assetFolderPath);
						}
						AssetDatabase.CreateAsset(terrainData, assetPath);

						// finally, resize height resolution if needed
						if (terrainData.heightmapResolution != (m_Settings.HeightmapResolution + 1))
						{
							ToolboxHelper.ResizeHeightmap(terrainData, (m_Settings.HeightmapResolution + 1));
						}						

						Undo.RegisterCreatedObjectUndo(newGO, "Create terrain");
					}
				}

				m_Terrains = terrains;
				m_CurrentGroup = terrainGroup;

				UpdateGroupSettings(groupComp);
				ToolboxHelper.CalculateAdjacencies(m_Terrains, m_Settings.TilesX, m_Settings.TilesZ);
			}
			finally
			{
				AssetDatabase.SaveAssets();
				AssetDatabase.Refresh();
				EditorUtility.ClearProgressBar();
			}
		}
예제 #40
0
    void Export()
    {
        string  fileName  = EditorUtility.SaveFilePanel("Export .obj file", "", "Terrain", "obj");
        int     w         = terrain.heightmapWidth;
        int     h         = terrain.heightmapHeight;
        Vector3 meshScale = terrain.size;
        int     tRes      = (int)Mathf.Pow(2, (int)saveResolution);

        meshScale = new Vector3(meshScale.x / (w - 1) * tRes, meshScale.y, meshScale.z / (h - 1) * tRes);
        Vector2 uvScale = new Vector2(1.0f / (w - 1), 1.0f / (h - 1));

        float[,] tData = terrain.GetHeights(0, 0, w, h);

        w = (w - 1) / tRes + 1;
        h = (h - 1) / tRes + 1;
        Vector3[] tVertices = new Vector3[w * h];
        Vector2[] tUV       = new Vector2[w * h];

        int[] tPolys;

        if (saveFormat == SaveFormat.Triangles)
        {
            tPolys = new int[(w - 1) * (h - 1) * 6];
        }
        else
        {
            tPolys = new int[(w - 1) * (h - 1) * 4];
        }

        // Build vertices and UVs
        for (int y = 0; y < h; y++)
        {
            for (int x = 0; x < w; x++)
            {
                tVertices[y * w + x] = Vector3.Scale(meshScale, new Vector3(-y, tData[x * tRes, y * tRes], x)) + terrainPos;
                tUV[y * w + x]       = Vector2.Scale(new Vector2(x * tRes, y * tRes), uvScale);
            }
        }

        int index = 0;

        if (saveFormat == SaveFormat.Triangles)
        {
            // Build triangle indices: 3 indices into vertex array for each triangle
            for (int y = 0; y < h - 1; y++)
            {
                for (int x = 0; x < w - 1; x++)
                {
                    // For each grid cell output two triangles
                    tPolys[index++] = (y * w) + x;
                    tPolys[index++] = ((y + 1) * w) + x;
                    tPolys[index++] = (y * w) + x + 1;

                    tPolys[index++] = ((y + 1) * w) + x;
                    tPolys[index++] = ((y + 1) * w) + x + 1;
                    tPolys[index++] = (y * w) + x + 1;
                }
            }
        }
        else
        {
            // Build quad indices: 4 indices into vertex array for each quad
            for (int y = 0; y < h - 1; y++)
            {
                for (int x = 0; x < w - 1; x++)
                {
                    // For each grid cell output one quad
                    tPolys[index++] = (y * w) + x;
                    tPolys[index++] = ((y + 1) * w) + x;
                    tPolys[index++] = ((y + 1) * w) + x + 1;
                    tPolys[index++] = (y * w) + x + 1;
                }
            }
        }

        // Export to .obj
        StreamWriter sw = new StreamWriter(fileName);

        try
        {
            sw.WriteLine("# Unity terrain OBJ File");

            // Write vertices
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
            counter    = tCount = 0;
            totalCount = (tVertices.Length * 2 + (saveFormat == SaveFormat.Triangles ? tPolys.Length / 3 : tPolys.Length / 4)) / progressUpdateInterval;
            for (int i = 0; i < tVertices.Length; i++)
            {
                UpdateProgress();
                StringBuilder sb = new StringBuilder("v ", 20);
                // StringBuilder stuff is done this way because it's faster than using the "{0} {1} {2}"etc. format
                // Which is important when you're exporting huge terrains.
                sb.Append(tVertices[i].x.ToString()).Append(" ").
                Append(tVertices[i].y.ToString()).Append(" ").
                Append(tVertices[i].z.ToString());
                sw.WriteLine(sb);
            }
            // Write UVs
            for (int i = 0; i < tUV.Length; i++)
            {
                UpdateProgress();
                StringBuilder sb = new StringBuilder("vt ", 22);
                sb.Append(tUV[i].x.ToString()).Append(" ").
                Append(tUV[i].y.ToString());
                sw.WriteLine(sb);
            }
            if (saveFormat == SaveFormat.Triangles)
            {
                // Write triangles
                for (int i = 0; i < tPolys.Length; i += 3)
                {
                    UpdateProgress();
                    StringBuilder sb = new StringBuilder("f ", 43);
                    sb.Append(tPolys[i] + 1).Append("/").Append(tPolys[i] + 1).Append(" ").
                    Append(tPolys[i + 1] + 1).Append("/").Append(tPolys[i + 1] + 1).Append(" ").
                    Append(tPolys[i + 2] + 1).Append("/").Append(tPolys[i + 2] + 1);
                    sw.WriteLine(sb);
                }
            }
            else
            {
                // Write quads
                for (int i = 0; i < tPolys.Length; i += 4)
                {
                    UpdateProgress();
                    StringBuilder sb = new StringBuilder("f ", 57);
                    sb.Append(tPolys[i] + 1).Append("/").Append(tPolys[i] + 1).Append(" ").
                    Append(tPolys[i + 1] + 1).Append("/").Append(tPolys[i + 1] + 1).Append(" ").
                    Append(tPolys[i + 2] + 1).Append("/").Append(tPolys[i + 2] + 1).Append(" ").
                    Append(tPolys[i + 3] + 1).Append("/").Append(tPolys[i + 3] + 1);
                    sw.WriteLine(sb);
                }
            }
        }
        catch (Exception err)
        {
            Debug.Log("Error saving file: " + err.Message);
        }
        sw.Close();

        terrain = null;
        EditorUtility.DisplayProgressBar("Saving file to disc.", "This might take a while...", 1f);
        EditorWindow.GetWindow <ExportTerrain>().Close();
        EditorUtility.ClearProgressBar();
    }
        public override void OnInspectorGUI()
        {
            if (tg == null)
            {
                return;
            }

            if (tg.splatSettings == null || tg.splatSettings.Length == 0)
            {
                tg.Initialize();
            }

            serializedObject.Update();

            if (titleLabelStyle == null)
            {
                titleLabelStyle = new GUIStyle(EditorStyles.label);
            }
            titleLabelStyle.normal.textColor = titleColor;
            titleLabelStyle.fontStyle        = FontStyle.Bold;
            if (boxStyle == null)
            {
                boxStyle = new GUIStyle(GUI.skin.box);
            }
            if (sectionHeaderStyle == null)
            {
                sectionHeaderStyle = new GUIStyle(EditorStyles.foldout);
            }
            sectionHeaderStyle.SetFoldoutColor();

            EditorGUILayout.BeginHorizontal();
            TerrainData prevTD = (TerrainData)terrainData.objectReferenceValue;

            EditorGUILayout.PropertyField(terrainData);
            TerrainData td = (TerrainData)terrainData.objectReferenceValue;

            if (td != prevTD)
            {
                tg.ExamineTerrainData();
            }
            if (GUILayout.Button("Refresh", GUILayout.Width(60)))
            {
                tg.ExamineTerrainData();
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.PropertyField(seaLevel);
            EditorGUILayout.PropertyField(waterVoxel);
            bool needCreate = false;
            bool needAssign = false;
            bool allIgnored = true;

            if (tg.terrainData != null)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Thumbnail Size", GUILayout.Width(EditorGUIUtility.labelWidth));
                thumbnailSize = EditorGUILayout.IntSlider(thumbnailSize, 16, 256);
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.Separator();
                expandTerrainTextures = EditorGUILayout.Foldout(expandTerrainTextures, new GUIContent("Terrain Textures"), true, sectionHeaderStyle);
                if (expandTerrainTextures)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Texture Size", GUILayout.Width(EditorGUIUtility.labelWidth));
                    terrainTextureSize = EditorGUILayout.IntField(terrainTextureSize);
                    EditorGUILayout.EndHorizontal();
#if UNITY_2018_3_OR_NEWER
                    for (int k = 0; k < tg.terrainData.terrainLayers.Length; k++)
                    {
#else
                    for (int k = 0; k < tg.terrainData.splatPrototypes.Length; k++)
                    {
#endif
                        EditorGUILayout.LabelField("Texture " + (k + 1), GUILayout.Width(80));
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField(new GUIContent(tg.splatSettings [k].preview), boxStyle, GUILayout.Width(thumbnailSize), GUILayout.Height(thumbnailSize));
                        EditorGUILayout.BeginVertical();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Voxel Top", GUILayout.Width(80));
                        tg.splatSettings [k].top = (VoxelDefinition)EditorGUILayout.ObjectField(tg.splatSettings [k].top, typeof(VoxelDefinition), false);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Smooth", GUILayout.Width(80));
                        tg.splatSettings [k].smoothPower = EditorGUILayout.Slider(tg.splatSettings [k].smoothPower, 0, 1f);
                        EditorGUILayout.EndHorizontal();

#if UNITY_2018_3_OR_NEWER
                        int textureCount = tg.terrainData.terrainLayers.Length;
#else
                        int textureCount = tg.terrainData.splatPrototypes.Length;
#endif
                        if (textureIndices == null || textureIndices.Length != textureCount)
                        {
                            textureIndices       = new string[textureCount];
                            textureIndicesValues = new int[textureCount];
                            for (int t = 0; t < textureCount; t++)
                            {
                                textureIndices [t]       = "Texture " + (t + 1);
                                textureIndicesValues [t] = (t + 1);
                            }
                        }

                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Dirt With", GUILayout.Width(80));
                        tg.splatSettings [k].dirtWith = EditorGUILayout.IntPopup(tg.splatSettings [k].dirtWith, textureIndices, textureIndicesValues);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Blend Power", GUILayout.Width(80));
                        tg.splatSettings [k].blendPower = EditorGUILayout.Slider(tg.splatSettings [k].blendPower, 0, 1f);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Voxel Dirt", GUILayout.Width(80));
                        tg.splatSettings [k].dirt = (VoxelDefinition)EditorGUILayout.ObjectField(tg.splatSettings [k].dirt, typeof(VoxelDefinition), false);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Action", GUILayout.Width(80));
                        tg.splatSettings [k].action = (UnityTerrainGenerator.TerrainResourceAction)EditorGUILayout.EnumPopup(tg.splatSettings [k].action);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.EndVertical();
                        EditorGUILayout.EndHorizontal();
                        if (tg.splatSettings [k].action != UnityTerrainGenerator.TerrainResourceAction.Ignore)
                        {
                            allIgnored = false;
                        }
                        if (tg.splatSettings [k].action == UnityTerrainGenerator.TerrainResourceAction.Create)
                        {
                            needCreate = true;
                        }
                        else if ((tg.splatSettings [k].top == null || tg.splatSettings [k].dirt == null) && tg.splatSettings [k].action == UnityTerrainGenerator.TerrainResourceAction.Assigned)
                        {
                            needAssign = true;
                        }
                        EditorGUILayout.Separator();
                    }
                }

                EditorGUILayout.Separator();
                expandTrees = EditorGUILayout.Foldout(expandTrees, new GUIContent("Trees"), true, sectionHeaderStyle);
                if (expandTrees)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Texture Size", GUILayout.Width(EditorGUIUtility.labelWidth));
                    treeTextureSize = EditorGUILayout.IntField(treeTextureSize);
                    EditorGUILayout.EndHorizontal();
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Frond Density", GUILayout.Width(EditorGUIUtility.labelWidth));
                    frondDensity = EditorGUILayout.Slider(frondDensity, 0f, 1f);
                    EditorGUILayout.EndHorizontal();
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Tree Scale", GUILayout.Width(EditorGUIUtility.labelWidth));
                    treeScale = EditorGUILayout.Slider(treeScale, 0.1f, 2f);
                    EditorGUILayout.EndHorizontal();
                    for (int k = 0; k < tg.terrainData.treePrototypes.Length; k++)
                    {
                        EditorGUILayout.LabelField("Tree " + (k + 1), GUILayout.Width(80));
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField(new GUIContent(tg.treeSettings [k].preview), boxStyle, GUILayout.Width(thumbnailSize), GUILayout.Height(thumbnailSize));
                        EditorGUILayout.BeginVertical();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Model Def.", GUILayout.Width(80));
                        tg.treeSettings [k].md = (ModelDefinition)EditorGUILayout.ObjectField(tg.treeSettings [k].md, typeof(ModelDefinition), false);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Smooth", GUILayout.Width(80));
                        tg.treeSettings [k].smoothPower = EditorGUILayout.Slider(tg.treeSettings [k].smoothPower, 0, 1f);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Action", GUILayout.Width(80));
                        tg.treeSettings [k].action = (UnityTerrainGenerator.TerrainResourceAction)EditorGUILayout.EnumPopup(tg.treeSettings [k].action);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.EndVertical();
                        EditorGUILayout.EndHorizontal();
                        if (tg.treeSettings [k].action != UnityTerrainGenerator.TerrainResourceAction.Ignore)
                        {
                            allIgnored = false;
                        }
                        if (tg.treeSettings [k].action == UnityTerrainGenerator.TerrainResourceAction.Create)
                        {
                            needCreate = true;
                        }
                        else if (tg.treeSettings[k].md == null && tg.treeSettings[k].action == UnityTerrainGenerator.TerrainResourceAction.Assigned)
                        {
                            needAssign = true;
                        }
                        EditorGUILayout.Separator();
                    }
                }

                EditorGUILayout.Separator();
                expandVegetation = EditorGUILayout.Foldout(expandVegetation, new GUIContent("Vegetation"), true, sectionHeaderStyle);
                if (expandVegetation)
                {
                    EditorGUILayout.PropertyField(vegetationDensity);
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Texture Size", GUILayout.Width(EditorGUIUtility.labelWidth));
                    vegetationTextureSize = EditorGUILayout.IntField(vegetationTextureSize);
                    EditorGUILayout.EndHorizontal();
                    for (int k = 0; k < tg.terrainData.detailPrototypes.Length; k++)
                    {
                        EditorGUILayout.LabelField("Detail " + (k + 1), GUILayout.Width(EditorGUIUtility.labelWidth));
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField(new GUIContent(tg.detailSettings [k].preview), boxStyle, GUILayout.Width(thumbnailSize), GUILayout.Height(thumbnailSize));
                        EditorGUILayout.BeginVertical();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Voxel Def.", GUILayout.Width(80));
                        tg.detailSettings [k].vd = (VoxelDefinition)EditorGUILayout.ObjectField(tg.detailSettings [k].vd, typeof(VoxelDefinition), false);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Action", GUILayout.Width(80));
                        tg.detailSettings [k].action = (UnityTerrainGenerator.TerrainResourceAction)EditorGUILayout.EnumPopup(tg.detailSettings [k].action);
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.EndVertical();
                        EditorGUILayout.EndHorizontal();
                        if (tg.detailSettings [k].action != UnityTerrainGenerator.TerrainResourceAction.Ignore)
                        {
                            allIgnored = false;
                        }
                        if (tg.detailSettings [k].action == UnityTerrainGenerator.TerrainResourceAction.Create)
                        {
                            needCreate = true;
                        }
                        else if (tg.detailSettings [k].vd == null && tg.detailSettings [k].action == UnityTerrainGenerator.TerrainResourceAction.Assigned)
                        {
                            needAssign = true;
                        }
                        EditorGUILayout.Separator();
                    }
                }
            }
            EditorGUILayout.Separator();
            if (!allIgnored)
            {
                if (needAssign)
                {
                    EditorGUILayout.HelpBox("Please check all 'Assigned' resources are correctly set in the list above or press 'Refresh' to reload TerrainData info.", MessageType.Warning);
                }
                else
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Clean Folders", GUILayout.Width(EditorGUIUtility.labelWidth));
                    cleanFolders = EditorGUILayout.Toggle(cleanFolders);
                    EditorGUILayout.EndHorizontal();
                    if (needCreate)
                    {
                        EditorGUILayout.HelpBox("Press 'Generate' to create voxel definitions for the terrain resources.", MessageType.Info);
                        if (GUILayout.Button("Generate"))
                        {
                            Generate(cleanFolders);
                        }
                    }
                    else
                    {
                        if (GUILayout.Button("Generate Again"))
                        {
                            Generate(true);
                        }
                    }
                }
            }

            EditorGUILayout.Separator();

            serializedObject.ApplyModifiedProperties();
        }

        void Generate(bool forceGeneration = false)
        {
            GenerateTerrainVoxels(forceGeneration);
            GenerateTreeModels(forceGeneration);
            GenerateVegetationVoxels(forceGeneration);

            EditorUtility.SetDirty(tg);
            AssetDatabase.SaveAssets();
        }

        string GetPath()
        {
            WorldDefinition wd = VoxelPlayEnvironment.instance.world;

            return(System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(wd)) + "/Resources/" + wd.name);
        }

        Texture2D CreateTextureFile(Texture2D tex, string path, string filename, float smoothPower)
        {
            if (smoothPower > 0)
            {
                TextureTools.Smooth(tex, smoothPower);
            }
            byte[] texBytes = tex.EncodeToPNG();
            string fullPath = path + "/" + filename + ".png";

            System.IO.File.WriteAllBytes(fullPath, texBytes);
            AssetDatabase.ImportAsset(fullPath);
            TextureImporter importerSettings = AssetImporter.GetAtPath(fullPath) as TextureImporter;

            if (importerSettings != null)
            {
                importerSettings.isReadable    = true;
                importerSettings.filterMode    = FilterMode.Point;
                importerSettings.mipmapEnabled = false;
                importerSettings.SaveAndReimport();
            }
            tex = AssetDatabase.LoadAssetAtPath <Texture2D> (fullPath);
            return(tex);
        }

        VoxelDefinition GenerateVoxelFromTexture(Texture2D textureTop, Texture2D textureSide, Texture2D textureDirt, int textureSize, string path, string voxelDefinitionName, RenderType renderType, float smoothPower)
        {
            // Prepare top texture
            Texture2D texTop = null;

            if (textureTop != null)
            {
                texTop      = Instantiate <Texture2D> (textureTop);
                texTop.name = textureTop.name;
                if (texTop.width != textureSize || texTop.height != textureSize)
                {
                    TextureTools.Scale(texTop, textureSize, textureSize, FilterMode.Bilinear);
                }
                string texName = Sanitize(texTop.name);
                texTop = CreateTextureFile(texTop, path, texName, smoothPower);
            }

            // Side texture
            Texture2D texSide = null;

            if (textureSide != null)
            {
                if (textureSide == textureTop)
                {
                    texSide = texTop;
                }
                else
                {
                    texSide      = Instantiate <Texture2D> (textureSide);
                    texSide.name = textureSide.name;
                    if (texSide.width != textureSize || texSide.height != textureSize)
                    {
                        TextureTools.Scale(texSide, textureSize, textureSize, FilterMode.Bilinear);
                    }
                    // Save texture
                    string texSideName = Sanitize(texSide.name);
                    texSide = CreateTextureFile(texSide, path, texSideName, smoothPower);
                }
            }

            // Dirt texture
            Texture2D texDirt = null;

            if (textureDirt != null)
            {
                if (textureDirt == textureTop)
                {
                    texDirt = texTop;
                }
                else
                {
                    texDirt      = Instantiate <Texture2D> (textureDirt);
                    texDirt.name = textureDirt.name;
                    if (texDirt.width != textureSize || texDirt.height != textureSize)
                    {
                        TextureTools.Scale(texDirt, textureSize, textureSize, FilterMode.Bilinear);
                    }
                    // Save texture
                    string texDirtName = Sanitize(texDirt.name);
                    texDirt = CreateTextureFile(texDirt, path, texDirtName, smoothPower);
                }
            }

            // Setup and save voxel definition
            VoxelDefinition vd = ScriptableObject.CreateInstance <VoxelDefinition> ();

            vd.renderType    = renderType;
            vd.textureTop    = texTop;
            vd.textureSide   = texSide;
            vd.textureBottom = texDirt;
            switch (renderType)
            {
            case RenderType.CutoutCross:
                vd.navigatable   = false;
                vd.windAnimation = true;
                break;

            case RenderType.Cutout:
                vd.navigatable   = false;
                vd.windAnimation = true;
                break;

            default:
                vd.navigatable   = true;
                vd.windAnimation = false;
                break;
            }
            vd.name = Sanitize(voxelDefinitionName);
            string fullPath = path + "/" + vd.name + ".asset";

            AssetDatabase.CreateAsset(vd, fullPath);
            return(vd);
        }

        void GenerateTerrainVoxels(bool forceGeneration)
        {
            string path = GetPath() + "/TerrainVoxels";

            CheckDirectory(path);
#if UNITY_2018_3_OR_NEWER
            for (int k = 0; k < tg.terrainData.terrainLayers.Length; k++)
            {
#else
            for (int k = 0; k < tg.terrainData.splatPrototypes.Length; k++)
            {
#endif
                if (forceGeneration || tg.splatSettings [k].action == UnityTerrainGenerator.TerrainResourceAction.Create)
                {
                    if (tg.splatSettings [k].preview == null)
                    {
                        continue;
                    }
                    int       dirtWith    = tg.splatSettings [k].dirtWith - 1;
                    string    texBaseName = tg.splatSettings [k].preview.name;
                    Texture2D texTop      = Instantiate(tg.splatSettings [k].preview) as Texture2D;
                    texTop.name = texBaseName + " Top";
                    Texture2D texOther = Instantiate(tg.splatSettings [dirtWith].preview) as Texture2D;
                    Texture2D texDirt  = CreateDirtTexture(texTop, texOther, tg.splatSettings [dirtWith].blendPower, 0);
                    texDirt.name = texBaseName + " Dirt";
                    Texture2D texSide = CreateSideTexture(texTop, texDirt);
                    texSide.name                = texBaseName + " Side";
                    tg.splatSettings [k].top    = GenerateVoxelFromTexture(texTop, texSide, texDirt, terrainTextureSize, path, "VoxelTerrainTop " + texBaseName, RenderType.Opaque, tg.splatSettings[k].smoothPower);
                    tg.splatSettings [k].dirt   = GenerateVoxelFromTexture(texDirt, texDirt, texDirt, terrainTextureSize, path, "VoxelTerrainDirt " + texBaseName, RenderType.Opaque, tg.splatSettings[k].smoothPower);
                    tg.splatSettings [k].action = UnityTerrainGenerator.TerrainResourceAction.Assigned;
                }
            }
        }

        Texture2D CreateDirtTexture(Texture2D texTop, Texture2D texOther, float smoothPower, float blendAmount)
        {
            if (texTop.width != terrainTextureSize || texTop.height != terrainTextureSize)
            {
                TextureTools.Scale(texTop, terrainTextureSize, terrainTextureSize);
            }
            if (texOther.width != terrainTextureSize || texOther.height != terrainTextureSize)
            {
                TextureTools.Scale(texOther, terrainTextureSize, terrainTextureSize);
            }
            Color32[] colorsTop   = texTop.GetPixels32();
            Color32[] colorsOther = texOther.GetPixels32();
            for (int k = 0; k < colorsTop.Length; k++)
            {
                colorsTop [k].r = (byte)Mathf.Lerp(colorsTop [k].r, colorsOther [k].r, blendAmount);
                colorsTop [k].g = (byte)Mathf.Lerp(colorsTop [k].g, colorsOther [k].g, blendAmount);
                colorsTop [k].b = (byte)Mathf.Lerp(colorsTop [k].b, colorsOther [k].b, blendAmount);
                colorsTop [k].a = (byte)Mathf.Lerp(colorsTop [k].a, colorsOther [k].a, blendAmount);
            }
            Texture2D tex = new Texture2D(texTop.width, texTop.height, TextureFormat.ARGB32, false);

            tex.SetPixels32(colorsTop);
            tex.Apply(true);
            return(tex);
        }

        Texture2D CreateSideTexture(Texture2D texTop, Texture2D texDirt)
        {
            // Make side texture
            Color32[] colors     = texTop.GetPixels32();
            Color32[] colorsDirt = texDirt.GetPixels32();
            int       h          = texTop.height;
            int       w          = texTop.width;
            int       y0         = (int)(h * 0.6f);
            int       i          = y0 * w;

            for (int y = y0; y < h; y++)
            {
                float threshold = Mathf.Clamp01(2f * ((float)(y - y0)) / (h - y0));
                for (int x = 0; x < w; x++, i++)
                {
                    if (UnityEngine.Random.value < threshold)
                    {
                        colorsDirt [i].r = (byte)Mathf.Lerp(colorsDirt [i].r, colors [i].r, threshold);
                        colorsDirt [i].g = (byte)Mathf.Lerp(colorsDirt [i].g, colors [i].g, threshold);
                        colorsDirt [i].b = (byte)Mathf.Lerp(colorsDirt [i].b, colors [i].b, threshold);
                        colorsDirt [i].a = (byte)Mathf.Lerp(colorsDirt [i].a, colors [i].a, threshold);
                    }
                }
            }
            Texture2D sideTexture = new Texture2D(w, h, TextureFormat.ARGB32, false);

            sideTexture.SetPixels32(colorsDirt);
            sideTexture.Apply(true);
            return(sideTexture);
        }

        void GenerateVegetationVoxels(bool forceGeneration)
        {
            string path = GetPath() + "/Vegetation";

            CheckDirectory(path);
            for (int k = 0; k < tg.terrainData.detailPrototypes.Length; k++)
            {
                if (forceGeneration || tg.detailSettings [k].action == UnityTerrainGenerator.TerrainResourceAction.Create)
                {
                    if (tg.detailSettings [k].preview == null)
                    {
                        continue;
                    }
                    TextureTools.EnsureTextureReadable(tg.detailSettings [k].preview);
                    tg.detailSettings [k].vd     = GenerateVoxelFromTexture(null, tg.detailSettings [k].preview, null, vegetationTextureSize, path, "VoxelVegetation " + tg.detailSettings [k].preview.name, RenderType.CutoutCross, 0);
                    tg.detailSettings [k].action = UnityTerrainGenerator.TerrainResourceAction.Assigned;
                }
            }
        }

        void GenerateTreeModels(bool forceGeneration)
        {
            string path = GetPath() + "/Trees";

            CheckDirectory(path);
            List <ModelBit> bits = new List <ModelBit> ();

            for (int k = 0; k < tg.terrainData.treePrototypes.Length; k++)
            {
                if (forceGeneration || tg.treeSettings [k].action == UnityTerrainGenerator.TerrainResourceAction.Create)
                {
                    // Get tree size
                    GameObject o = tg.terrainData.treePrototypes [k].prefab;
                    // Look for LOD0
                    MeshRenderer[] rr = o.GetComponentsInChildren <MeshRenderer> ();
                    if (rr.Length == 0)
                    {
                        continue;
                    }
                    MeshRenderer r = rr [0];
                    for (int b = 0; b < rr.Length; b++)
                    {
                        if (rr [b].name.Contains("LOD0"))
                        {
                            r = rr [b];
                            break;
                        }
                    }
                    // Get bounds of renderer
                    Bounds bounds = r.bounds;
                    int    sizeX  = (int)(bounds.size.x * treeScale);
                    int    sizeY  = (int)(bounds.size.y * treeScale);
                    int    sizeZ  = (int)(bounds.size.z * treeScale);
                    if (sizeX == 0 || sizeY == 0 || sizeZ == 0)
                    {
                        continue;
                    }

                    // Build model definition
                    ModelDefinition md = ScriptableObject.CreateInstance <ModelDefinition> ();
                    md.sizeX = sizeX;
                    md.sizeY = sizeY;
                    md.sizeZ = sizeZ;
                    bits.Clear();
                    MeshFilter mf       = r.GetComponent <MeshFilter> ();
                    Mesh       mesh     = mf.sharedMesh;
                    Vector3[]  vertices = mesh.vertices;
                    Vector2[]  uvs      = mesh.uv;
                    for (int m = 0; m < mesh.subMeshCount; m++)
                    {
                        int[] triangles = mesh.GetTriangles(m);
                        for (int i = 0; i < triangles.Length; i += 3)
                        {
                            int     i1  = triangles [i];
                            int     i2  = triangles [i + 1];
                            int     i3  = triangles [i + 2];
                            Vector3 v1  = vertices [i1];
                            Vector3 v2  = vertices [i2];
                            Vector3 v3  = vertices [i3];
                            Vector2 uv1 = uvs [i1];
                            Vector2 uv2 = uvs [i2];
                            Vector2 uv3 = uvs [i3];
                            AddModelBit(bits, md, (v1 + v2 + v3) * treeScale / 3f, (uv1 + uv2 + uv3) / 3f, r.sharedMaterials [m], path, tg.treeSettings [k].smoothPower);
                        }
                    }
                    md.bits = bits.ToArray();

                    string treeName = Sanitize(tg.terrainData.treePrototypes [k].prefab.name);
                    md.name = "Tree " + treeName;
                    string fullPath = path + "/" + md.name + ".asset";
                    AssetDatabase.CreateAsset(md, fullPath);
                    tg.treeSettings [k].md     = md;
                    tg.treeSettings [k].action = UnityTerrainGenerator.TerrainResourceAction.Assigned;
                }
            }
        }

        void AddModelBit(List <ModelBit> bits, ModelDefinition md, Vector3 pos, Vector2 uv, Material mat, string path, float smoothPower)
        {
            Texture2D tex = (Texture2D)mat.mainTexture;

            if (tex == null)
            {
                return;
            }
            int y          = Mathf.Clamp(Mathf.FloorToInt(pos.y), 0, md.sizeY - 1);
            int z          = Mathf.Clamp(Mathf.FloorToInt(pos.z) + md.sizeZ / 2, 0, md.sizeZ - 1);
            int x          = Mathf.Clamp(Mathf.FloorToInt(pos.x) + md.sizeX / 2, 0, md.sizeX - 1);
            int voxelIndex = y * md.sizeZ * md.sizeX + z * md.sizeX + x;
            int bitCount   = bits.Count;

            if (bitCount > 0)
            {
                for (int k = bitCount - 1; k >= 0; k--)
                {
                    if (bits [k].voxelIndex == voxelIndex)
                    {
                        return;
                    }
                }
            }
            TextureTools.EnsureTextureReadable(tex);
            ModelBit bit = new ModelBit();

            bit.voxelIndex = voxelIndex;
            VoxelDefinition vd;

            if (textureVoxels == null)
            {
                textureVoxels = new Dictionary <Texture2D, VoxelDefinition> ();
            }
            if (!textureVoxels.TryGetValue(tex, out vd))
            {
                RenderType rt      = RenderType.Cutout;
                string     matName = mat.name.ToUpper();
                string     texName = tex.name.ToUpper();
                if (matName.Contains("BRANCH") || matName.Contains("BARK") || texName.Contains("BARK"))
                {
                    rt = RenderType.Opaque;
                    vd = GenerateVoxelFromTexture(tex, tex, tex, treeTextureSize, path, "VoxelTree " + tex.name, rt, smoothPower);
                }
                else
                {
                    Texture2D frondTex = GenerateFrondTexture(tex, uv, treeTextureSize, path);
                    vd = GenerateVoxelFromTexture(frondTex, frondTex, frondTex, treeTextureSize, path, "VoxelTree " + frondTex.name, rt, smoothPower);
                }
                textureVoxels [tex] = vd;
            }
            bit.voxelDefinition = vd;
            bits.Add(bit);
        }

        Texture2D GenerateFrondTexture(Texture2D tex, Vector2 uv, int textureSize, string path)
        {
            Color32[] sourceColors = tex.GetPixels32();
            // Extract representative colors around uv position
            int            w         = textureSize;
            int            h         = textureSize;
            int            x         = Mathf.Clamp((int)(w * uv.x), 0, w - 1);
            int            y         = Mathf.Clamp((int)(h * uv.y), 0, h - 1);
            List <Color32> repColors = new List <Color32> ();
            int            gap       = textureSize / 2;

            for (int y0 = y - gap; y0 < y + gap; y0++)
            {
                int ty = Mathf.Clamp(y0, 0, h - 1);
                for (int x0 = x - gap; x0 < x + gap; x0++)
                {
                    int tx = Mathf.Clamp(x0, 0, w - 1);
                    repColors.Add(sourceColors [ty * w + tx]);
                }
            }
            Color32[] colors    = repColors.ToArray();
            Color32[] newColors = new Color32[w * h];
            int       i         = 0;

            for (int k = 0; k < newColors.Length; k++)
            {
                if (UnityEngine.Random.value > frondDensity)
                {
                    continue;
                }
                for (int c = 0; c < colors.Length; c++)
                {
                    if (colors [i].a > 128)
                    {
                        break;
                    }
                    i++;
                    if (i >= colors.Length)
                    {
                        i = 0;
                    }
                }
                newColors [k]   = colors [i];
                newColors [k].a = 255;
                i++;
                if (i >= colors.Length)
                {
                    i = 0;
                }
            }
            Texture2D subTex = new Texture2D(w, h, TextureFormat.ARGB32, false);

            subTex.filterMode = FilterMode.Point;
            subTex.name       = tex.name + " Frond";
            subTex.SetPixels32(newColors);
            subTex.Apply(true);
            return(subTex);
        }

        void CheckDirectory(string path)
        {
            if (cleanFolders)
            {
                if (Directory.Exists(path))
                {
                    System.IO.DirectoryInfo di = new DirectoryInfo(path);
                    foreach (FileInfo file in di.GetFiles())
                    {
                        file.Delete();
                    }
                    foreach (DirectoryInfo dir in di.GetDirectories())
                    {
                        dir.Delete(true);
                    }
                }
                AssetDatabase.Refresh();
            }
            System.IO.Directory.CreateDirectory(path);
        }

        string Sanitize(string s)
        {
            if (string.IsNullOrEmpty(s))
            {
                return("");
            }
            int k = s.IndexOf("(Clone)");

            if (k >= 0)
            {
                s = s.Substring(0, k);
            }
            char[] invalidChars = System.IO.Path.GetInvalidFileNameChars();
            for (int i = 0; i < invalidChars.Length; i++)
            {
                if (s.IndexOf(invalidChars [i]) >= 0)
                {
                    s = s.Replace(invalidChars [i], '_');
                }
            }
            return(s);
        }
    }
}
    static XmlElement streamWorld(XmlDocument xmlDoc, XmlElement root)
    {
        XmlElement WorldNode = xmlDoc.CreateElement("gameObject");

        WorldNode.SetAttribute("name", "world");
        root.AppendChild(WorldNode);
        WorldNode.SetAttribute("wname", System.IO.Path.GetFileNameWithoutExtension(EditorApplication.currentScene));

        root = WorldNode;
        GameObject obj = GameObject.Find("Terrain");

        if (obj == null)
        {
            return(null);
        }

        XmlElement TerrainNode = xmlDoc.CreateElement("gameObject");

        TerrainNode.SetAttribute("name", "Terrain");

        root.AppendChild(TerrainNode);
        root = TerrainNode;

        TerrainData terrainData = obj.GetComponent <TerrainCollider>().terrainData;

        Debug.Log("StreamWorld:" + terrainData.name);

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

        XmlElement tmpNode     = xmlDoc.CreateElement("size");
        XmlElement prefabsNode = xmlDoc.CreateElement("prefabs");

        root.AppendChild(prefabsNode);

        tmpNode.InnerText = (terrainData.size.x + " " + terrainData.size.y + " " + terrainData.size.z);
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("name");
        tmpNode.InnerText = terrainData.name;
        root.AppendChild(tmpNode);

        int splitsize = 0;

        foreach (Transform child in obj.transform)
        {
            string name = child.gameObject.name;
            if (name == "2")
            {
                splitsize = 2;
            }
            else if (name == "4")
            {
                splitsize = 4;
            }
            else if (name == "8")
            {
                splitsize = 8;
            }
            else if (name == "16")
            {
                splitsize = 16;
            }
            else if (name == "64")
            {
                splitsize = 64;
            }
        }
        ;

        if (splitsize == 0)
        {
            Debug.LogError("splitsize: is 0");
            splitsize = 8;
        }

        tmpNode           = xmlDoc.CreateElement("splitSize");
        tmpNode.InnerText = (splitsize + "");
        root.AppendChild(tmpNode);

        tmpNode = xmlDoc.CreateElement("alphamapWH");
        tmpNode.SetAttribute("w", terrainData.alphamapWidth + "");
        tmpNode.SetAttribute("h", terrainData.alphamapHeight + "");
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("baseMapResolution");
        tmpNode.InnerText = (terrainData.baseMapResolution + "");
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("detailResolution");
        tmpNode.InnerText = (terrainData.detailResolution + "");
        root.AppendChild(tmpNode);

        tmpNode = xmlDoc.CreateElement("detailWH");
        tmpNode.SetAttribute("w", terrainData.detailWidth + "");
        tmpNode.SetAttribute("h", terrainData.detailHeight + "");
        root.AppendChild(tmpNode);

        tmpNode = xmlDoc.CreateElement("heightmapWH");
        tmpNode.SetAttribute("w", terrainData.heightmapWidth + "");
        tmpNode.SetAttribute("h", terrainData.heightmapHeight + "");
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("heightmapResolution");
        tmpNode.InnerText = (terrainData.heightmapResolution + "");
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("heightmapScale");
        tmpNode.InnerText = (terrainData.heightmapScale.x + " " + terrainData.heightmapScale.y + " " + terrainData.heightmapScale.z);
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("hideFlags");
        tmpNode.InnerText = (terrainData.hideFlags + "");
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("wavingGrassAmount");
        tmpNode.InnerText = (terrainData.wavingGrassAmount + "");
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("wavingGrassSpeed");
        tmpNode.InnerText = (terrainData.wavingGrassSpeed + "");
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("wavingGrassStrength");
        tmpNode.InnerText = (terrainData.wavingGrassStrength + "");
        root.AppendChild(tmpNode);

        tmpNode           = xmlDoc.CreateElement("wavingGrassTint");
        tmpNode.InnerText = (terrainData.wavingGrassTint.r + " " + terrainData.wavingGrassTint.g + " " + terrainData.wavingGrassTint.b + " " + terrainData.wavingGrassTint.a);
        root.AppendChild(tmpNode);

        tmpNode = xmlDoc.CreateElement("treePrototypes");
        for (int i = 0; i < terrainData.treePrototypes.Length; i++)
        {
            TreePrototype tp       = terrainData.treePrototypes[i];
            XmlElement    itemNode = xmlDoc.CreateElement("item");

            itemNode.SetAttribute("prefab", tp.prefab.name);
            refPrefabs.Add(tp.prefab.name);

            XmlElement prefabsItemNode = xmlDoc.CreateElement("item");
            prefabsItemNode.InnerText = tp.prefab.name;
            //prefabsNode.AppendChild(prefabsItemNode);

            itemNode.SetAttribute("bendFactor", tp.bendFactor + "");

            tmpNode.AppendChild(itemNode);

            string path = "Assets/StreamingAssets/" + tp.prefab.name.Replace(" ", "_") + ".unity3d";
            BuildPipeline.BuildAssetBundle(tp.prefab, null, path);
        }
        root.AppendChild(tmpNode);

        /*
         * tmpNode = xmlDoc.CreateElement("treeInstances");
         * for(int i=0; i<terrainData.treeInstances.Length; i++)
         * {
         *      TreeInstance ti = terrainData.treeInstances[i];
         *      XmlElement itemNode = xmlDoc.CreateElement("item");
         *      ti.
         *      itemNode.SetAttribute("prefab", tp.prefab.name);
         *      itemNode.SetAttribute("bendFactor", tp.bendFactor + "");
         *
         *      tmpNode.AppendChild(itemNode);
         * }
         * root.AppendChild(tmpNode);
         */

        tmpNode = xmlDoc.CreateElement("detailPrototypes");
        for (int i = 0; i < terrainData.detailPrototypes.Length; i++)
        {
            DetailPrototype dp       = terrainData.detailPrototypes[i];
            XmlElement      itemNode = xmlDoc.CreateElement("item");

            itemNode.SetAttribute("prefab", dp.prototypeTexture.name);
            refPrefabs.Add(dp.prototypeTexture.name);
            itemNode.SetAttribute("bendFactor", dp.bendFactor + "");
            itemNode.SetAttribute("usePrototypeMesh", dp.usePrototypeMesh + "");

            XmlElement prefabsItemNode = xmlDoc.CreateElement("item");
            prefabsItemNode.InnerText = dp.prototypeTexture.name;
            //prefabsNode.AppendChild(prefabsItemNode);

            tmpNode.AppendChild(itemNode);

            string path = "Assets/StreamingAssets/" + dp.prototypeTexture.name.Replace(" ", "_") + ".unity3d";
            BuildPipeline.BuildAssetBundle(dp.prototypeTexture, null, path);
        }
        root.AppendChild(tmpNode);

        XmlElement splatprotosNode = xmlDoc.CreateElement("splatprotos");

        for (int i = 0; i < terrainData.splatPrototypes.Length; i++)
        {
            SplatPrototype sp       = terrainData.splatPrototypes[i];
            XmlElement     itemNode = xmlDoc.CreateElement("item");

            string texture = sp.texture != null ? sp.texture.name : "";
            if (texture != "")
            {
                XmlElement prefabsItemNode = xmlDoc.CreateElement("item");
                prefabsItemNode.InnerText = texture;
                //prefabsNode.AppendChild(prefabsItemNode);
                refPrefabs.Add(texture);

                string path = "Assets/StreamingAssets/" + texture.Replace(" ", "_") + ".unity3d";
                BuildPipeline.BuildAssetBundle(sp.texture, null, path);
            }

            itemNode.SetAttribute("texture", texture);

            texture = sp.normalMap != null ? sp.normalMap.name : "";
            if (texture != "")
            {
                XmlElement prefabsItemNode = xmlDoc.CreateElement("item");
                prefabsItemNode.InnerText = texture;
                //prefabsNode.AppendChild(prefabsItemNode);
                refPrefabs.Add(texture);

                string path = "Assets/StreamingAssets/" + texture.Replace(" ", "_") + ".unity3d";
                BuildPipeline.BuildAssetBundle(sp.normalMap, null, path);
            }

            itemNode.SetAttribute("normalMap", sp.normalMap != null ? sp.normalMap.name : "");
            itemNode.SetAttribute("tileOffsetX", sp.tileOffset.x + "");
            itemNode.SetAttribute("tileOffsetY", sp.tileOffset.y + "");
            itemNode.SetAttribute("tileSizeX", sp.tileSize.x + "");
            itemNode.SetAttribute("tileSizeY", sp.tileSize.y + "");

            splatprotosNode.AppendChild(itemNode);
        }

        root.AppendChild(splatprotosNode);
        return(WorldNode);
    }
예제 #43
0
    void GetSurfaceSound()
    {
        if (onTerrain)
        {
            TerrainData terrainData = terrain.terrainData;

            #region Texture Mix
            // calculate which splat map cell the worldPos falls within (ignoring y)
            int mapX = (int)(((transform.position.x - terrain.GetPosition().x) / terrainData.size.x) * terrainData.alphamapWidth);
            int mapZ = (int)(((transform.position.z - terrain.GetPosition().z) / terrainData.size.z) * terrainData.alphamapHeight);

            // get the splat data for this cell as a 1x1xN 3d array (where N = number of textures)
            float[,,] splatmapData = terrainData.GetAlphamaps(mapX, mapZ, 1, 1);

            // extract the 3D array data to a 1D array:
            float[] textureMix = new float[splatmapData.GetUpperBound(2) + 1];

            for (int n = 0; n < textureMix.Length; n++)
            {
                textureMix[n] = splatmapData[0, 0, n];
            }
            #endregion

            #region Texture Index
            float maxMix   = 0;
            int   maxIndex = 0;

            // loop through each mix value and find the maximum
            for (int n = 0; n < textureMix.Length; n++)
            {
                if (textureMix[n] > maxMix)
                {
                    maxIndex = n;
                    maxMix   = textureMix[n];
                }
            }

            int textureIndex = maxIndex;
            #endregion

            #region Set Footstep Sound
            string textureName = terrainData.splatPrototypes[textureIndex].texture.name;

            foreach (var texture in textureAttributes)
            {
                if (texture.texture.name == textureName)
                {
                    footstepSound = textureAttributes[texture.index].footstepSounds;
                    canRun        = textureAttributes[texture.index].canRun;
                    GetComponent <PlayerController>().canRun    = textureAttributes[texture.index].canRun;
                    GetComponent <PlayerController>().walkSpeed = textureAttributes[texture.index].walkSpeed;
                    GetComponent <PlayerController>().runSpeed  = textureAttributes[texture.index].runSpeed;
                }
            }
            #endregion
        }

        else if (onMesh)
        {
            //Physics Material
            if (detectionType == _type.TerrainTextureAndPhysicsMaterial)
            {
                foreach (var physicsMaterial in physicsMaterials)
                {
                    if (currentPhysicsMaterial == physicsMaterial.material)
                    {
                        footstepSound = physicsMaterial.footstepSounds;
                        canRun        = physicsMaterial.canRun;
                        GetComponent <PlayerController>().canRun = physicsMaterial.canRun;

                        /* if(!physicsMaterial.canRun)
                         *   if (GetComponent<PlayerController>().isRunning)
                         *       GetComponent<PlayerController>().isRunning = false;  */
                        GetComponent <PlayerController>().walkSpeed = physicsMaterial.walkSpeed;
                        GetComponent <PlayerController>().runSpeed  = physicsMaterial.runSpeed;
                    }
                }
            }

            //Tag
            else if (detectionType == _type.TerrainTextureAndTag)
            {
                foreach (var tag in tags)
                {
                    if (currentMeshTag == tag.tagName)
                    {
                        footstepSound = tag.footstepSounds;
                        canRun        = tag.canRun;
                        GetComponent <PlayerController>().canRun = tag.canRun;

                        /* if (!tag.canRun)
                         *    if (GetComponent<PlayerController>().isRunning)
                         *        GetComponent<PlayerController>().isRunning = false; */
                        GetComponent <PlayerController>().walkSpeed = tag.walkSpeed;
                        GetComponent <PlayerController>().runSpeed  = tag.runSpeed;
                    }
                }
            }
        }
    }
예제 #44
0
        /// <summary>
        /// Apply the Circle Brush
        /// </summary>
        /// <param name="modType">The modification type to apply</param>
        /// <param name="heightData">Terrain height data</param>
        /// <param name="terrainData">Terrain Data used</param>
        private void CircleBrush(TerrainModificationType modType, float[,] heightData, TerrainData terrainData)
        {
            int offsetX = m_BrushWidth / 2;
            int offsetY = m_BrushHeight / 2;

            for (int i = 0; i < m_BrushHeight; i++)
            {
                for (int j = 0; j < m_BrushWidth; j++)
                {
                    float currentRadiusSqr = new Vector2(offsetX - j, offsetY - i).sqrMagnitude;
                    if (currentRadiusSqr < offsetX * offsetY)
                    {
                        switch (modType)
                        {
                        case TerrainModificationType.Raise:
                            heightData[i, j] = NewRaiseHeight(heightData[i, j], terrainData);
                            break;

                        case TerrainModificationType.Lower:
                            heightData[i, j] = NewLowerHeight(heightData[i, j], terrainData);
                            break;

                        case TerrainModificationType.Flatten:
                            heightData[i, j] = NewFlattenHeight(heightData[offsetX, offsetY], terrainData);
                            break;

                        case TerrainModificationType.Smooth:
                            SmoothTerrainOperation(1, heightData, j, i);
                            break;
                        }
                    }
                }
            }
        }
예제 #45
0
        public static Dictionary <Vector2Int, Terrain> SplitTerrainIntoChunks(
            Terrain split, float chunkSize, int heightsRes, int alphasRes, int detailsRes
            )
        {
            if (split == null)
            {
                Debug.LogWarning("splitTerrain == null");
                return(null);
            }

            TerrainData splitData = split.terrainData;

            float parentSize = splitData.size.x;

            if (parentSize <= chunkSize)
            {
                Debug.Log("splitTerrain fits in one grid already...");
                return(null);
            }

            int splits = CalculateChunksInTerrain(split, chunkSize);


            Dictionary <Vector2Int, Terrain> grid2Terrain = new Dictionary <Vector2Int, Terrain>();

            float[,] heights      = splitData.GetHeights(0, 0, splitData.heightmapResolution, splitData.heightmapResolution);
            float[,] chunkHeights = new float[heightsRes, heightsRes];

            TerrainLayer[] terrainLayers = splitData.terrainLayers;
            float[,,] alphas      = splitData.GetAlphamaps(0, 0, splitData.alphamapResolution, splitData.alphamapResolution);
            float[,,] chunkAlphas = new float[alphasRes, alphasRes, splitData.alphamapLayers];

            detailsRes = Mathf.Max(0, detailsRes);
            DetailPrototype[] detailPrototypes = splitData.detailPrototypes;
            int[][,] details    = new int[detailPrototypes.Length][, ];
            int[,] chunkDetails = new int[detailsRes, detailsRes];
            if (detailsRes > 0)
            {
                for (int i = 0; i < detailPrototypes.Length; i++)
                {
                    details[i] = splitData.GetDetailLayer(0, 0, splitData.detailResolution, splitData.detailResolution, i);
                }
            }

            TreePrototype[] treePrototypes = splitData.treePrototypes;
            TreeInstance[]  treeInstances  = splitData.treeInstances;

            Vector3 chunkSize3 = new Vector3(chunkSize, splitData.size.y, chunkSize);

            for (int y = 0; y < splits; y++)
            {
                for (int x = 0; x < splits; x++)
                {
                    Vector2Int grid = new Vector2Int(x, y);

                    TerrainData data     = new TerrainData();
                    GameObject  terrainG = Terrain.CreateTerrainGameObject(data);
                    terrainG.name = split.name + "_" + grid;
                    Terrain terrain = terrainG.GetComponent <Terrain>();
                    terrain.terrainData = data;

                    grid2Terrain[grid] = terrain;

                    // Copy parent terrain propeties
                    #region parent properties
                    terrain.basemapDistance         = split.basemapDistance;
                    terrain.castShadows             = split.castShadows;
                    terrain.detailObjectDensity     = split.detailObjectDensity;
                    terrain.detailObjectDistance    = split.detailObjectDistance;
                    terrain.heightmapPixelError     = split.heightmapPixelError;
                    terrain.treeBillboardDistance   = split.treeBillboardDistance;
                    terrain.treeCrossFadeLength     = split.treeCrossFadeLength;
                    terrain.treeDistance            = split.treeDistance;
                    terrain.treeMaximumFullLODCount = split.treeMaximumFullLODCount;
                    #endregion

                    Vector3 gridWorld = new Vector3(grid.x * chunkSize, 0, grid.y * chunkSize);
                    terrain.transform.position = split.transform.position + gridWorld;

                    SplitHeights(data, splitData, gridWorld, chunkSize, parentSize, chunkHeights, heights, heightsRes);
                    SplitAlphas(data, splitData, gridWorld, chunkSize, parentSize, chunkAlphas, alphas, alphasRes, terrainLayers);

                    if (detailsRes > 0)
                    {
                        SplitDetails(data, splitData, gridWorld, chunkSize, parentSize, chunkDetails, details, detailsRes, detailPrototypes);
                    }

                    SplitTrees(terrain, splitData, gridWorld, chunkSize, treeInstances, treePrototypes);

                    data.size = chunkSize3;
                }
            }
            return(grid2Terrain);
        }
예제 #46
0
        /// <summary>
        /// Apply the Rectangle Brush
        /// </summary>
        /// <param name="modType">The modification type to apply</param>
        /// <param name="heightData">Terrain height data</param>
        /// <param name="terrainData">Terrain Data used</param>
        private void RectangleBrush(TerrainModificationType modType, float[,] heightData, TerrainData terrainData)
        {
            int offsetX = m_BrushWidth / 2;
            int offsetY = m_BrushHeight / 2;

            for (int i = 0; i < m_BrushHeight; i++)
            {
                for (int j = 0; j < m_BrushWidth; j++)
                {
                    switch (modType)
                    {
                    case TerrainModificationType.Raise:
                        heightData[i, j] = NewRaiseHeight(heightData[i, j], terrainData);
                        break;

                    case TerrainModificationType.Lower:
                        heightData[i, j] = NewLowerHeight(heightData[i, j], terrainData);
                        break;

                    case TerrainModificationType.Flatten:
                        heightData[i, j] = NewFlattenHeight(heightData[offsetX, offsetY], terrainData);
                        break;

                    case TerrainModificationType.Smooth:
                        SmoothTerrainOperation(1, heightData, i, j);
                        break;
                    }
                }
            }
        }
예제 #47
0
        public IEnumerator CreateImpl()
        {
            try
            {
                using (m_queue = new JobQueue(8))
                {
                    Stopwatch sw = new Stopwatch();

                    AssetDatabase.Refresh();
                    AssetDatabase.SaveAssets();

                    sw.Reset();
                    sw.Start();

                    EditorUtility.DisplayProgressBar("Bake HLOD", "Initialize Bake", 0.0f);


                    TerrainData data = m_hlod.TerrainData;

                    m_size = data.size;

                    m_heightmap = new Heightmap(data.heightmapResolution, data.heightmapResolution, data.size,
                                                data.GetHeights(0, 0, data.heightmapResolution, data.heightmapResolution));

                    string materialPath = AssetDatabase.GUIDToAssetPath(m_hlod.MaterialGUID);
                    m_terrainMaterial = AssetDatabase.LoadAssetAtPath <Material>(materialPath);
                    if (m_terrainMaterial == null)
                    {
                        m_terrainMaterial = new Material(Shader.Find("Lightweight Render Pipeline/Lit-Terrain-HLOD-High"));
                    }

                    m_terrainMaterialInstanceId = m_terrainMaterial.GetInstanceID();
                    m_terrainMaterialName       = m_terrainMaterial.name;

                    materialPath         = AssetDatabase.GUIDToAssetPath(m_hlod.MaterialLowGUID);
                    m_terrainMaterialLow = AssetDatabase.LoadAssetAtPath <Material>(materialPath);
                    if (m_terrainMaterialLow == null)
                    {
                        m_terrainMaterialLow = new Material(Shader.Find("Lightweight Render Pipeline/Lit-Terrain-HLOD-Low"));
                    }

                    m_terrainMaterialLowInstanceId = m_terrainMaterialLow.GetInstanceID();
                    m_terrainMaterialLowName       = m_terrainMaterialLow.name;

                    using (m_alphamaps = new DisposableList <WorkingTexture>())
                        using (m_layers = new DisposableList <Layer>())
                        {
                            for (int i = 0; i < data.alphamapTextures.Length; ++i)
                            {
                                m_alphamaps.Add(new WorkingTexture(Allocator.Persistent, data.alphamapTextures[i]));
                            }

                            for (int i = 0; i < data.terrainLayers.Length; ++i)
                            {
                                m_layers.Add(new Layer(data.terrainLayers[i], m_hlod.ChunkSize));
                            }


                            QuadTreeSpaceSplitter splitter =
                                new QuadTreeSpaceSplitter(0.0f);

                            SpaceNode rootNode = splitter.CreateSpaceTree(m_hlod.GetBounds(), m_hlod.ChunkSize * 2.0f,
                                                                          m_hlod.transform.position, null, progress => { });

                            EditorUtility.DisplayProgressBar("Bake HLOD", "Create mesh", 0.0f);

                            using (DisposableList <HLODBuildInfo> buildInfos = CreateBuildInfo(data, rootNode))
                            {
                                yield return(m_queue.WaitFinish());

                                //Write material & textures

                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    int curIndex = i;
                                    m_queue.EnqueueJob(() =>
                                    {
                                        ISimplifier simplifier = (ISimplifier)Activator.CreateInstance(m_hlod.SimplifierType,
                                                                                                       new object[] { m_hlod.SimplifierOptions });
                                        simplifier.SimplifyImmidiate(buildInfos[curIndex]);
                                    });
                                }

                                EditorUtility.DisplayProgressBar("Bake HLOD", "Simplify meshes", 0.0f);
                                yield return(m_queue.WaitFinish());

                                Debug.Log("[TerrainHLOD] Simplify: " + sw.Elapsed.ToString("g"));
                                sw.Reset();
                                sw.Start();
                                EditorUtility.DisplayProgressBar("Bake HLOD", "Make border", 0.0f);

                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    HLODBuildInfo info = buildInfos[i];
                                    m_queue.EnqueueJob(() =>
                                    {
                                        for (int oi = 0; oi < info.WorkingObjects.Count; ++oi)
                                        {
                                            WorkingObject o       = info.WorkingObjects[oi];
                                            int borderVertexCount = m_hlod.BorderVertexCount * Mathf.RoundToInt(Mathf.Pow(2.0f, (float)info.Distances[oi]));
                                            using (WorkingMesh m = MakeBorder(o.Mesh, info.Heightmap, borderVertexCount))
                                            {
                                                ReampUV(m, info.Heightmap);
                                                o.SetMesh(MakeFillHoleMesh(m));
                                            }
                                        }
                                    });
                                }
                                yield return(m_queue.WaitFinish());

                                Debug.Log("[TerrainHLOD] Make Border: " + sw.Elapsed.ToString("g"));
                                sw.Reset();
                                sw.Start();


                                for (int i = 0; i < buildInfos.Count; ++i)
                                {
                                    SpaceNode     node = buildInfos[i].Target;
                                    HLODBuildInfo info = buildInfos[i];
                                    if (node.HasChild() == false)
                                    {
                                        SpaceNode parent = node.ParentNode;
                                        node.ParentNode = null;

                                        GameObject go = new GameObject(buildInfos[i].Name);

                                        for (int wi = 0; wi < info.WorkingObjects.Count; ++wi)
                                        {
                                            WorkingObject wo       = info.WorkingObjects[wi];
                                            GameObject    targetGO = null;
                                            if (wi == 0)
                                            {
                                                targetGO = go;
                                            }
                                            else
                                            {
                                                targetGO = new GameObject(wi.ToString());
                                                targetGO.transform.SetParent(go.transform, false);
                                            }

                                            List <Material> materials = new List <Material>();
                                            for (int mi = 0; mi < wo.Materials.Count; ++mi)
                                            {
                                                WorkingMaterial wm = wo.Materials[mi];
                                                if (wm.NeedWrite() == false)
                                                {
                                                    materials.Add(wm.ToMaterial());
                                                    continue;
                                                }

                                                Material mat          = new Material(wm.ToMaterial());
                                                string[] textureNames = wm.GetTextureNames();
                                                for (int ti = 0; ti < textureNames.Length; ++ti)
                                                {
                                                    WorkingTexture wt  = wm.GetTexture(textureNames[ti]);
                                                    Texture2D      tex = wt.ToTexture();
                                                    tex.wrapMode = wt.WrapMode;
                                                    mat.name     = targetGO.name + "_Mat";
                                                    mat.SetTexture(textureNames[ti], tex);
                                                }
                                                mat.EnableKeyword("_NORMALMAP");
                                                materials.Add(mat);
                                            }

                                            targetGO.AddComponent <MeshFilter>().sharedMesh = wo.Mesh.ToMesh();

                                            var mr = targetGO.AddComponent <MeshRenderer>();
                                            mr.sharedMaterials = materials.ToArray();
                                            mr.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;
                                        }

                                        go.transform.SetParent(m_hlod.transform, false);
                                        m_hlod.AddGeneratedResource(go);

                                        parent.Objects.Add(go);
                                        buildInfos.RemoveAt(i);
                                        i -= 1;
                                    }
                                }

                                //controller
                                IStreamingBuilder builder =
                                    (IStreamingBuilder)Activator.CreateInstance(m_hlod.StreamingType,
                                                                                new object[] { m_hlod, m_hlod.StreamingOptions });

                                builder.Build(rootNode, buildInfos, m_hlod.gameObject, m_hlod.CullDistance, m_hlod.LODDistance, true, false,
                                              progress =>
                                {
                                    EditorUtility.DisplayProgressBar("Bake HLOD", "Storing results.",
                                                                     0.75f + progress * 0.25f);
                                });

                                Debug.Log("[TerrainHLOD] Build: " + sw.Elapsed.ToString("g"));
                            }
                        }

                    EditorUtility.SetDirty(m_hlod.gameObject);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
                GC.Collect();
            }
        }
예제 #48
0
    private void OldAssignTextures()
    {
        // Get a reference to the terrain data
        TerrainData terrainData = _terrain.terrainData;

        // Splatmap data is stored internally as a 3d array of floats, so declare a new empty array ready for your custom splatmap data:
        float[,,] splatmapData = new float[terrainData.alphamapWidth,
                                           terrainData.alphamapHeight,
                                           terrainData.alphamapLayers];

        for (int y = 0; y < terrainData.alphamapHeight; y++)
        {
            for (int x = 0; x < terrainData.alphamapWidth; x++)
            {
                // Normalise x/y coordinates to range 0-1
                float y_01 = (float)y / (float)terrainData.alphamapHeight;
                float x_01 = (float)x / (float)terrainData.alphamapWidth;

                // Sample the height at this location (note GetHeight expects int coordinates corresponding to locations in the heightmap array)
                //float height = terrainData.GetHeight(Mathf.RoundToInt(y_01 * terrainData.heightmapHeight), Mathf.RoundToInt(x_01 * terrainData.heightmapWidth));

                // Calculate the normal of the terrain (note this is in normalised coordinates relative to the overall terrain dimensions)
                //Vector3 normal = terrainData.GetInterpolatedNormal(y_01, x_01);

                // Calculate the steepness of the terrain
                // float steepness = terrainData.GetSteepness(y_01, x_01);

                // Setup an array to record the mix of texture weights at this point
                float[] splatWeights = new float[terrainData.alphamapLayers];

                // CHANGE THE RULES BELOW TO SET THE WEIGHTS OF EACH TEXTURE ON WHATEVER RULES YOU WANT
                CaseInfos caseInfo   = _mapInfosManager.GetInfosAtPos(new Vector2(x, y));
                CaseInfos infoXPlus  = _mapInfosManager.GetInfosAtPos(new Vector2(x + 10, y));
                CaseInfos infoXMoins = _mapInfosManager.GetInfosAtPos(new Vector2(x - 10, y));
                CaseInfos infoYPlus  = _mapInfosManager.GetInfosAtPos(new Vector2(x, y + 10));
                CaseInfos infoYMoins = _mapInfosManager.GetInfosAtPos(new Vector2(x, y - 10));

                int idCase   = GetTextureId(caseInfo);
                int idXPlus  = GetTextureId(infoXPlus);
                int idXMoins = GetTextureId(infoXMoins);
                int idYPlus  = GetTextureId(infoYPlus);
                int idYMoins = GetTextureId(infoYMoins);

                if (caseInfo == null)
                {
                    //Debug.LogWarning("Case infos not found at pos (" + x + "," + y + ")");
                    splatWeights[0] = 0.5f;
                    splatWeights[1] = 0.5f;
                }
                else
                {
                    int yunit = y - (y / 10) * 10;
                    int xunit = x - (x / 10) * 10;

                    float currentRatio;

                    if (xunit < 4 && xunit != 0 && idXMoins != -1 && idXMoins != idCase)
                    {
                        currentRatio           = (-2 * xunit + 7) / 10.0f;
                        splatWeights[idXMoins] = currentRatio + splatWeights[idXMoins] - splatWeights[idXMoins] * currentRatio;
                    }
                    else if (xunit > 7 && idXPlus != -1 && idXPlus != idCase)
                    {
                        currentRatio          = (2 * xunit - 15) / 10.0f;
                        splatWeights[idXPlus] = currentRatio + splatWeights[idXPlus] - splatWeights[idXPlus] * currentRatio;
                    }
                    else if (xunit == 0 && idXPlus != -1 && idXPlus != idCase)
                    {
                        currentRatio          = 0.49f;
                        splatWeights[idXPlus] = currentRatio + splatWeights[idXPlus] - splatWeights[idXPlus] * currentRatio;
                    }

                    if (yunit < 4 && yunit != 0 && idYMoins != -1 && idYMoins != idCase)
                    {
                        currentRatio           = (-2 * yunit + 7) / 10.0f;
                        splatWeights[idYMoins] = currentRatio + splatWeights[idYMoins] - splatWeights[idYMoins] * currentRatio;
                    }
                    else if (yunit > 7 && idYPlus != -1 && idYPlus != idCase)
                    {
                        currentRatio          = (2 * yunit - 15) / 10.0f;
                        splatWeights[idYPlus] = currentRatio + splatWeights[idYPlus] - splatWeights[idYPlus] * currentRatio;
                    }
                    else if (yunit == 0 && idYPlus != -1 && idYPlus != idCase)
                    {
                        currentRatio          = 0.50f;
                        splatWeights[idYPlus] = currentRatio + splatWeights[idYPlus] - splatWeights[idYPlus] * currentRatio;
                    }
                    splatWeights[idCase] = splatWeights[idCase] == 0 ? 1 - splatWeights.Sum() : splatWeights[idCase] * (1 - splatWeights.Sum());
                }


                // Texture[2] stronger on flatter terrain
                // Note "steepness" is unbounded, so we "normalise" it by dividing by the extent of heightmap height and scale factor
                // Subtract result from 1.0 to give greater weighting to flat surfaces
                //splatWeights[2] = 1.0f - Mathf.Clamp01(steepness * steepness / (terrainData.heightmapHeight / 5.0f));

                // Texture[3] increases with height but only on surfaces facing positive Z axis
                //splatWeights[3] = height * Mathf.Clamp01(normal.z);

                // Sum of all textures weights must add to 1, so calculate normalization factor from sum of weights
                float z = splatWeights.Sum();

                // Loop through each terrain texture
                for (int i = 0; i < terrainData.alphamapLayers; i++)
                {
                    // Normalize so that sum of all texture weights = 1
                    splatWeights[i] /= z;

                    // Assign this point to the splatmap array
                    splatmapData[x, y, i] = splatWeights[i];
                }
            }
        }

        // Finally assign the new splatmap to the terrainData:
        terrainData.SetAlphamaps(0, 0, splatmapData);
    }
예제 #49
0
 /// <summary>
 /// Calculate the new height after lowering
 /// </summary>
 /// <param name="currentHeight">Current terrain height</param>
 /// <param name="terrainData">The used terrain Data</param>
 /// <returns>The new height</returns>
 private float NewLowerHeight(float currentHeight, TerrainData terrainData)
 {
     return(Mathf.Clamp(currentHeight - (m_ModificationSpeed * Time.deltaTime) / terrainData.size.y, m_MinHeight / terrainData.size.y, m_MaxHeight / terrainData.size.y));
 }
    void OnGUI()
    {
        //Выводим текст
        GUILayout.Label("Procedurally texture terrain, by Christian S.");

        GUILayout.Label("Terrain:");
        ter = (Terrain)EditorGUILayout.ObjectField(ter, typeof(Terrain), true);

        if (ter != null)
        {
            blendByAngle = GUILayout.Toggle(blendByAngle, "Blend by Angle");



            // Array stuff goes here


            ScriptableObject   target          = this;
            SerializedObject   so              = new SerializedObject(target);
            SerializedProperty stringsProperty = so.FindProperty("splatHeights");

            EditorGUILayout.PropertyField(stringsProperty, true); // True means show children
            so.ApplyModifiedProperties();                         // Remember to apply modified properties


            if (GUILayout.Button("Apply"))
            {
                Debug.Log("Applied");



                TerrainData terrainData = Terrain.activeTerrain.terrainData;
                float[,,] splatmapData = new float[terrainData.alphamapWidth, terrainData.alphamapHeight, terrainData.alphamapLayers];

                for (int y = 0; y < terrainData.alphamapHeight; y++)
                {
                    for (int x = 0; x < terrainData.alphamapWidth; x++)
                    {
                        float terrainHeight = terrainData.GetHeight(y, x);

                        float[] splat = new float[splatHeights.Length];

                        for (int i = 0; i < splatHeights.Length; i++)
                        {
                            float thisNoise = Mathf.Clamp(Mathf.PerlinNoise(x * 0.05f, y * 0.05f), 0.5f, 1f);

                            float thisHeightStart = findHeightByIndex(i).startingHeight *thisNoise - findHeightByIndex(i).overlap *thisNoise;

                            float nextHeightStart = 0;

                            if (i != splatHeights.Length - 1)
                            {
                                nextHeightStart = findHeightByIndex(i + 1).startingHeight *thisNoise + findHeightByIndex(i + 1).overlap *thisNoise;
                            }

                            if (i == splatHeights.Length - 1 && terrainHeight >= findHeightByIndex(i).startingHeight)
                            {
                                splat[findHeightByIndex(i).textureIndex] = 1;
                            }

                            else if (terrainHeight >= findHeightByIndex(i).startingHeight&& terrainHeight <= findHeightByIndex(i + 1).startingHeight)
                            {
                                splat[findHeightByIndex(i).textureIndex] = 1;
                            }

                            //normalize(splat);

                            for (int j = 0; j < splatHeights.Length; j++)
                            {
                                splatmapData[x, y, j] = splat[findHeightByIndex(j).textureIndex];
                            }
                        }

                        if (blendByAngle)
                        {
                            // Get the normalized terrain coordinate that
                            // corresponds to the the point.
                            float normX = x * 1.0f / (terrainData.alphamapWidth - 1);
                            float normY = y * 1.0f / (terrainData.alphamapHeight - 1);

                            var angle = terrainData.GetSteepness(normX, normY);

                            // Steepness is given as an angle, 0..90 degrees. Divide
                            // by 90 to get an alpha blending value in the range 0..1.
                            var frac = angle / 180.0;
                            splatmapData[x, y, 0] = (float)frac;
                            splatmapData[x, y, 1] = (float)(1 - frac);

                            float[] dirHi = new float[5];

                            dirHi[0] = terrainData.GetHeight(y, x);
                            dirHi[1] = terrainData.GetHeight(y + 1, x);
                            dirHi[2] = terrainData.GetHeight(y, x + 1);
                            dirHi[3] = terrainData.GetHeight(y - 1, x);
                            dirHi[4] = terrainData.GetHeight(y, x - 1);

                            // convert to a-n...
                        }



                        //Based on height of it and nearby pos, change texture.
                    }

                    terrainData.SetAlphamaps(0, 0, splatmapData);
                }
            }
        }
    }
    public static void GenerateSplatMap(ChunkData chunkData)
    {
        // Get the attached terrain component
        Terrain terrain = chunkData.terrain;

        // Get a reference to the terrain data
        TerrainData terrainData = chunkData.terrainData;

        TextureData[] textureData = ProceduralTerrain.Current.TerrainMapData.TerrainTextures;

        float constantWeight     = ProceduralTerrain.Current.TerrainMapData.Texture1ConstantWeight;
        float steepnessScale     = ProceduralTerrain.Current.TerrainMapData.TextureSteepnessScaleFactor;
        float textureBlendAmount = ProceduralTerrain.Current.TerrainMapData.TextureBlendAmount;

        // Splatmap data is stored internally as a 3d array of floats, so declare a new empty array ready for your custom splatmap data:
        float[,,] splatmapData = new float[terrainData.alphamapWidth, terrainData.alphamapHeight, terrainData.alphamapLayers];

        for (int y = 0; y < terrainData.alphamapHeight; y++)
        {
            for (int x = 0; x < terrainData.alphamapWidth; x++)
            {
                // Normalise x/y coordinates to range 0-1
                float y_01 = (float)y / (float)terrainData.alphamapHeight;
                float x_01 = (float)x / (float)terrainData.alphamapWidth;

                // Sample the height at this location (note GetHeight expects int coordinates corresponding to locations in the heightmap array)
                float height = terrainData.GetHeight(Mathf.RoundToInt(y_01 * terrainData.heightmapHeight), Mathf.RoundToInt(x_01 * terrainData.heightmapWidth));

                // Calculate the normal of the terrain (note this is in normalised coordinates relative to the overall terrain dimensions)
                Vector3 normal = terrainData.GetInterpolatedNormal(y_01, x_01);

                // Calculate the steepness of the terrain
                float steepness = terrainData.GetSteepness(y_01, x_01);

                // Setup an array to record the mix of texture weights at this point
                float[] splatWeights = new float[terrainData.alphamapLayers];

                // CHANGE THE RULES BELOW TO SET THE WEIGHTS OF EACH TEXTURE ON WHATEVER RULES YOU WANT

                height = height / ProceduralTerrain.Current.TerrainMapData.TerrainHeight;

                //For steeper terrains, last value in array is always for steepness
                splatWeights[textureData.Length - 1] = Mathf.Clamp01(steepness * steepness / (terrainData.heightmapHeight / steepnessScale));

                //If is not too steep apply other textures
                if (splatWeights[textureData.Length - 1] < 0.8f)
                {
                    //Go backwards through textures
                    for (int i = 0; i < textureData.Length; i++)
                    {
                        if (height > textureData[i].TextureStartHeight)
                        {
                            //If not last element in array and height value is less than the next textures start height
                            if (i < textureData.Length - 1 && textureData[i + 1].TextureStartHeight > height)
                            {
                                splatWeights[i] = 1;
                            }
                        }
                    }
                }

                //if(height - 0.1f > 0.1f)
                //for (int i = 0; i < splatWeights.Length - 1; i++) {

                //    splatWeights[i] -= textureBlendAmount;
                //    splatWeights[i + 1] += textureBlendAmount;
                //}

                // Texture[0] has constant influence
                //splatWeights[0] = constantWeight;

                // Texture[1] is stronger at lower altitudes
                //splatWeights[1] = 1; //Mathf.Clamp01(1 - height / ProceduralTerrain.Current.TerrainMapData.TerrainHeight);

                // Texture[2] stronger on flatter terrain
                // Note "steepness" is unbounded, so we "normalise" it by dividing by the extent of heightmap height and scale factor
                // Subtract result from 1.0 to give greater weighting to flat surfaces
                //splatWeights[2] = 1.0f - Mathf.Clamp01(steepness * steepness / (terrainData.heightmapHeight / steepnessScale));

                // Texture[3] steeper terrains
                //splatWeights[3] = Mathf.Clamp01(steepness * steepness / (terrainData.heightmapHeight / steepnessScale));//Mathf.Clamp01(height / ProceduralTerrain.Current.TerrainMapData.TerrainHeight); //* Mathf.Clamp01(normal.z);

                // Sum of all textures weights must add to 1, so calculate normalization factor from sum of weights
                float z = splatWeights.Sum();

                // Loop through each terrain texture
                for (int i = 0; i < terrainData.alphamapLayers; i++)
                {
                    // Normalize so that sum of all texture weights = 1
                    splatWeights[i] /= z;

                    // Assign this point to the splatmap array
                    splatmapData[x, y, i] = splatWeights[i];
                }
            }
        }

        // Finally assign the new splatmap to the terrainData:
        terrainData.SetAlphamaps(0, 0, splatmapData);
    }
예제 #52
0
    private DigResult AttemptToDig(long checkX, long checkY, long checkZ)
    {
        mnCurrentDigSizeY = digArea.CurrentHeight;
        var segment = mFrustrum != null
            ? AttemptGetSegment(checkX, checkY, checkZ)
            : WorldScript.instance.GetSegment(checkX, checkY, checkZ);

        if (segment == null || !segment.mbInitialGenerationComplete || segment.mbDestroyed)
        {
            mrDigDelay = 1f;
            return(DigResult.Fail);
        }

        ushort cube = segment.GetCube(checkX, checkY, checkZ);

        if (cube == eCubeTypes.CentralPowerHub)
        {
            return(DigResult.Dig);
        }

        if (cube == mReplaceType)
        {
            return(DigResult.Skip);
        }

        if (CubeHelper.IsReinforced(cube) && eExcavateState != ExcavateState.ClearAll)
        {
            return(DigResult.Dig);
        }

        if (CubeHelper.HasEntity((int)cube) && eExcavateState != ExcavateState.ClearAll)
        {
            if (cube != eCubeTypes.AlienPlant && cube != eCubeTypes.ArachnidRock)
            {
                return(DigResult.Dig);
            }
        }

        if (TerrainData.GetHardness(cube, 0) > 500f)
        {
            return(DigResult.Dig);
        }

        if (eExcavateState == ExcavateState.ClearGarbage)
        {
            if (CubeHelper.IsOre(cube))
            {
                return(DigResult.Dig);
            }
        }

        // Tranqs Creative Survival mod really breaks this call as nearly everything in the game is craftable.
        if (CraftingManager.IsCraftable(cube) && cube != eCubeTypes.Giger &&
            eExcavateState != ExcavateState.ClearAll)
        {
            // ore should never ever be craftable
            if (!CubeHelper.IsOre(cube))
            {
                return(DigResult.Dig);
            }
        }

        int num  = (int)(checkX - segment.baseX);
        int num2 = (int)(checkY - segment.baseY);
        int num3 = (int)(checkZ - segment.baseZ);

        if (num == 0 && base.AttemptGetSegment(checkX - 1L, checkY, checkZ) == null)
        {
            return(DigResult.Fail);
        }

        if (num == 15 && base.AttemptGetSegment(checkX + 1L, checkY, checkZ) == null)
        {
            return(DigResult.Fail);
        }

        if (num2 == 0 && base.AttemptGetSegment(checkX, checkY - 1L, checkZ) == null)
        {
            return(DigResult.Fail);
        }

        if (num2 == 15 && base.AttemptGetSegment(checkX, checkY + 1L, checkZ) == null)
        {
            return(DigResult.Fail);
        }

        if (num3 == 0 && base.AttemptGetSegment(checkX, checkY, checkZ - 1L) == null)
        {
            return(DigResult.Fail);
        }

        if (num3 == 15 && base.AttemptGetSegment(checkX, checkY, checkZ + 1L) == null)
        {
            return(DigResult.Fail);
        }

        ushort mValue = segment.GetCubeData(checkX, checkY, checkZ).mValue;

        WorldScript.instance.BuildFromEntity(segment, checkX, checkY, checkZ, this.mReplaceType,
                                             TerrainData.GetDefaultValue(this.mReplaceType));
        this.mrCurrentPower -= this.mrPowerRate;
        this.mbLocatedBlock  = true;
        this.mnBlocksDestroyed++;
        if (segment.mbInLocalFrustrum)
        {
            if (eDropState == DropState.DropSome)
            {
                bool flag = true;
                if (CubeHelper.IsGarbage(cube) && this.mRand.Next(100) > 5)
                {
                    flag = false;
                }

                if (flag)
                {
                    Vector3 velocity = new Vector3((float)this.mRand.NextDouble() - 0.5f, 0f,
                                                   (float)this.mRand.NextDouble() - 0.5f);
                    velocity.x *= 5f;
                    velocity.z *= 5f;
                    ItemManager.DropNewCubeStack(cube, mValue, 1, checkX, checkY, checkZ, velocity);
                }
            }

            if (eDropState == DropState.DropAll)
            {
                Vector3 velocity = new Vector3((float)this.mRand.NextDouble() - 0.5f, 0f,
                                               (float)this.mRand.NextDouble() - 0.5f);
                velocity.x *= 5f;
                velocity.z *= 5f;
                ItemManager.DropNewCubeStack(cube, mValue, 1, checkX, checkY, checkZ, velocity);
            }

            if (eDropState == DropState.DropOre && CubeHelper.IsOre(cube))
            {
                Vector3 velocity = new Vector3((float)this.mRand.NextDouble() - 0.5f, 0f,
                                               (float)this.mRand.NextDouble() - 0.5f);
                velocity.x *= 5f;
                velocity.z *= 5f;
                ItemManager.DropNewCubeStack(cube, mValue, 1, checkX, checkY, checkZ, velocity);
            }

            this.mrTimeSinceShoot = 0f;
        }

        return(DigResult.Dig);
    }
예제 #53
0
    Vector3 GetTerrainVertex(TerrainData terrain, int x, int y, float sampleWidthInMeter, float sampleHeightInMeter)
    {
        Vector3 v = new Vector3(x * sampleWidthInMeter, terrain.GetHeight(x, y), y * sampleHeightInMeter);

        return(v);
    }
예제 #54
0
    void DoFourWaySplit()
    {
        //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, _assetsPath + "/" + genTer.name + ".asset");

            // added chunked tiles to lists for further iterations
            terrainMatrix.Add(genTer);
            terrainAssets.Add(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

            if (_debugToLog)
            {
                Debug.Log("Split height on" + tgo.name);
            }

            //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 < parentTerrain.terrainData.alphamapLayers; s++)
            {
                for (int x = startX; x < endX; x++)
                {
                    EditorUtility.DisplayProgressBar("Split terrain", "Split splat", (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 = splatShift;
                            yShift = 0;
                        }

                        //
                        if (i == 2)
                        {
                            xShift = 0;
                            yShift = splatShift;
                        }

                        if (i == 3)
                        {
                            xShift = splatShift;
                            yShift = splatShift;
                        }

                        float ph = parentSplat[x + xShift, y + yShift, s];
                        peaceSplat[x, y, s] = ph;
                    }
                }
            }

            EditorUtility.ClearProgressBar();

            // Set heightmap to child
            genTer.terrainData.SetAlphamaps(0, 0, peaceSplat);
            #endregion

            // Split detail map
            #region split detail map

            td.SetDetailResolution(parentTerrain.terrainData.detailResolution / terraPeaces, 8);

            for (int detLay = 0; detLay < parentTerrain.terrainData.detailPrototypes.Length; detLay++)
            {
                int[,] parentDetail = parentTerrain.terrainData.GetDetailLayer(0, 0, parentTerrain.terrainData.detailResolution, parentTerrain.terrainData.detailResolution, detLay);

                int[,] peaceDetail = new int[parentTerrain.terrainData.detailResolution / terraPeaces,
                                             parentTerrain.terrainData.detailResolution / terraPeaces
                                     ];

                // Shift calc
                int detailShift = parentTerrain.terrainData.detailResolution / terraPeaces;

                if (i == 0)
                {
                    startX = startY = 0;
                    endX   = endY = parentTerrain.terrainData.detailResolution / terraPeaces;
                }

                if (i == 1)
                {
                    startX = startY = 0;
                    endX   = parentTerrain.terrainData.detailResolution / terraPeaces;
                    endY   = parentTerrain.terrainData.detailResolution / terraPeaces;
                }

                if (i == 2)
                {
                    startX = startY = 0;
                    endX   = parentTerrain.terrainData.detailResolution / terraPeaces;
                    endY   = parentTerrain.terrainData.detailResolution / terraPeaces;
                }

                if (i == 3)
                {
                    startX = startY = 0;
                    endX   = parentTerrain.terrainData.detailResolution / terraPeaces;
                    endY   = parentTerrain.terrainData.detailResolution / terraPeaces;
                }

                // iterate
                for (int x = startX; x < endX; x++)
                {
                    EditorUtility.DisplayProgressBar("Split terrain", "Split detail", (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 = detailShift;
                            yShift = 0;
                        }

                        //
                        if (i == 2)
                        {
                            xShift = 0;
                            yShift = detailShift;
                        }

                        if (i == 3)
                        {
                            xShift = detailShift;
                            yShift = detailShift;
                        }

                        int ph = parentDetail[x + xShift, y + yShift];
                        peaceDetail[x, y] = ph;
                    }
                }
                EditorUtility.ClearProgressBar();

                // Set heightmap to child
                genTer.terrainData.SetDetailLayer(0, 0, detLay, peaceDetail);
            }
            #endregion

            // Split tree data
            #region  split tree data

            for (int t = 0; t < parentTerrain.terrainData.treeInstances.Length; t++)
            {
                EditorUtility.DisplayProgressBar("Split terrain", "Split trees ", (float)t / parentTerrain.terrainData.treeInstances.Length);

                // Get tree instance
                TreeInstance ti = parentTerrain.terrainData.treeInstances[t];

                // First section
                if (i == 0 &&
                    ti.position.x > 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 BuildTerrainData(TerrainData terrainData)
    {
        // Define the size of the arrays that Unity's terrain will
        // use internally to represent the terrain. Bigger numbers
        // mean more fine details.

        //if(CoRoutineShouldPause())
        //    yield return null;

        // "Heightmap Resolution": "Pixel resolution of the terrain’s heightmap (should be a power of two plus one, eg, 513 = 512 + 1)."
        // AFAIK, this defines the size of the 2-dimensional array that holds the information about the terrain (i.e. terrainData.GetHeights())
        // Larger numbers lead to finer terrain details (if populated by a suitable source image heightmap).
        // As for actual physical size of the terrain (in Unity world space), this is defined as:
        //              terrainData.Size = terrainData.heightmapScale * terrainData.heightmapResolution
        terrainData.heightmapResolution = 128 + 1;

        // "Base Texture Resolution": "Resolution of the composite texture used on the terrain when viewed from a distance greater than the Basemap Distance"
        // AFAIK, this doesn't affect the terrain mesh -- only how the terrain texture (i.e. Splats) are rendered
        terrainData.baseMapResolution = 512 + 1;

        // "Detail Resolution" and "Detail Resolution Per Patch"
        // (used for Details -- i.e. grass/flowers/etc...)
        terrainData.SetDetailResolution(1024, 32);

        // Set the Unity worldspace size of the terrain AFTER you set the resolution.
        // This effectively just sets terrainData.heightmapScale for you, depending on the value of terrainData.heightmapResolution
        terrainData.size = new Vector3(WorldUnitsPerChunk, TerrainHeight, WorldUnitsPerChunk);

        // Get the 2-dimensional array of floats that defines the actual height data for the terrain.
        // Each float has a value from 0..1, where a value of 1 means the maximum height of the terrain as defined by terrainData.size.y
        //
        // AFAIK, terrainData.heightmapWidth and terrainData.heightmapHeight will always be equal to terrainData.heightmapResolution
        //
        float[,] heights = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight);

        float halfDegreesPerChunk = DegreesPerChunk / 2f;

        // Caching these dimensions and...
        int w = terrainData.heightmapWidth;
        int h = terrainData.heightmapHeight;

        // Replacing loop divisions with mults cuts this function by about 10%
        //  -- Shout out to Karl Goodloe
        float widthAdjust  = 1f / (w - 1f);
        float heightAdjust = 1f / (h - 1f);

        // Loop through each point in the terrainData heightmap.
        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                // Normalize x and y to a value from 0..1
                // NOTE: We are INVERTING the x and y because internally Unity does this
                float xPos = (float)x * widthAdjust;
                float yPos = (float)y * heightAdjust;

                // This converts our chunk position to a latitude/longitude,
                // which we can then use to get UV coordinates from the heightmap
                // FIXME: I think this is doing a pincushion effect
                //    Someone smarter than me will have to figure this out.
                Quaternion pointRotation = ChunkRotation *
                                           Quaternion.Euler(
                    xPos * DegreesPerChunk - halfDegreesPerChunk,
                    yPos * DegreesPerChunk - halfDegreesPerChunk,
                    0
                    );


                Vector2 uv = CoordHelper.RotationToUV(pointRotation);

                // Get the pixel from the heightmap image texture at the appropriate position
                Color pix = HeightMapTexture.GetPixelBilinear(uv.x, uv.y);

                // Update the heights array
                heights[x, y] = pix.grayscale / heightMapTextureScaling;
            }
        }

        // Update the terrain data based on our changed heights array
        terrainData.SetHeights(0, 0, heights);
    }
        public override bool OnPaint(Terrain terrain, IOnPaint editContext)
        {
            if (m_TargetTerrain == null ||
                selectedDetail == kInvalidDetail ||
                selectedDetail >= m_TargetTerrain.terrainData.detailPrototypes.Length)
            {
                return(false);
            }

            Texture2D brush = editContext.brushTexture as Texture2D;

            if (brush == null)
            {
                Debug.LogError("Brush texture is not a Texture2D.");
                return(false);
            }

            if (m_BrushRep == null)
            {
                m_BrushRep = new DetailBrushRepresentation();
            }

            PaintTreesDetailsContext ctx = PaintTreesDetailsContext.Create(terrain, editContext.uv);

            for (int t = 0; t < ctx.neighborTerrains.Length; ++t)
            {
                Terrain ctxTerrain = ctx.neighborTerrains[t];
                if (ctxTerrain != null)
                {
                    int detailPrototype = PaintDetailsToolUtility.FindDetailPrototype(ctxTerrain, m_TargetTerrain, selectedDetail);
                    if (detailPrototype == kInvalidDetail)
                    {
                        detailPrototype = PaintDetailsToolUtility.CopyDetailPrototype(ctxTerrain, m_TargetTerrain, selectedDetail);
                    }

                    TerrainData terrainData = ctxTerrain.terrainData;

                    TerrainPaintUtilityEditor.UpdateTerrainDataUndo(terrainData, "Terrain - Detail Edit");

                    int size = (int)Mathf.Max(1.0f, editContext.brushSize * ((float)terrainData.detailResolution / terrainData.size.x));

                    m_BrushRep.Update(brush, size);

                    float targetStrength = m_DetailsStrength;
                    if (Event.current.shift || Event.current.control)
                    {
                        targetStrength = -targetStrength;
                    }

                    DetailBrushBounds brushBounds = new DetailBrushBounds(terrainData, ctx, size, t);

                    int[] layers = { detailPrototype };
                    if (targetStrength < 0.0F && !Event.current.control)
                    {
                        layers = terrainData.GetSupportedLayers(brushBounds.min, brushBounds.bounds.size);
                    }

                    for (int i = 0; i < layers.Length; i++)
                    {
                        int[,] alphamap = terrainData.GetDetailLayer(brushBounds.min, brushBounds.bounds.size, layers[i]);

                        for (int y = 0; y < brushBounds.bounds.height; y++)
                        {
                            for (int x = 0; x < brushBounds.bounds.width; x++)
                            {
                                Vector2Int brushOffset = brushBounds.GetBrushOffset(x, y);
                                float      opa         = detailOpacity * m_BrushRep.GetStrength(brushOffset.x, brushOffset.y);

                                float targetValue = Mathf.Lerp(alphamap[y, x], targetStrength * terrainData.maxDetailScatterPerRes, opa);
                                alphamap[y, x] = Mathf.Min(Mathf.RoundToInt(targetValue - .5f + Random.value), terrainData.maxDetailScatterPerRes);
                            }
                        }

                        terrainData.SetDetailLayer(brushBounds.min, layers[i], alphamap);
                    }
                }
            }

            return(false);
        }
예제 #57
0
    private static void GenerateTrees()
    {
        Terrain     t  = Terrain.activeTerrain;
        TerrainData td = t.terrainData;

        TreePrototype[] treeprototypes = new TreePrototype[] { new TreePrototype()
                                                               {
                                                                   prefab = BigTree
                                                               }, new TreePrototype()
                                                               {
                                                                   prefab = Tree
                                                               } };

        td.treePrototypes = treeprototypes;

        //float[, ,] splatmaps = td.GetAlphamaps(0, 0, td.alphamapWidth, td.alphamapHeight);
        td.treeInstances = new TreeInstance[0];

        List <Vector3> treePos = new List <Vector3>();

        print(td.alphamapWidth + "," + td.alphamapHeight);
        float[,] noisemap = new float[td.alphamapWidth, td.alphamapHeight];
        Generator noise_tree = new Max(
            new PinkNoise((int)UnityEngine.Random.Range(0, int.MaxValue))
        {
            Frequency = 0.01f, OctaveCount = 6, Persistence = 0.66f, Lacunarity = 0.1f
        },
            new PinkNoise((int)UnityEngine.Random.Range(0, int.MaxValue))
        {
            Frequency = 0.015f, OctaveCount = 2, Persistence = 0.66f, Lacunarity = 0.2f
        });

        for (int ny = 0; ny < noisemap.GetLength(1); ny++)
        {
            for (int nx = 0; nx < noisemap.GetLength(0); nx++)
            {
                noisemap[nx, ny] = noise_tree.GetValue(nx, ny, 0);
            }
        }
        if (maxSteepness == 0)
        {
            maxSteepness = 70.0f;
        }
        if (waterLevel == 0)
        {
            waterLevel = 0.0f;
        }
        float x = 0.0f;

        while (x < td.alphamapWidth)
        {
            float y = 0.0f;
            while (y < td.alphamapHeight)
            {
                float height       = td.GetHeight((int)x, (int)y);
                float heightScaled = height / td.size.y;
                float xScaled      = (x + Random.Range(-1f, 1f)) / td.alphamapWidth;
                float yScaled      = (y + Random.Range(-1f, 1f)) / td.alphamapHeight;
                float steepness    = td.GetSteepness(xScaled, yScaled);

                if (Random.Range(0f, 1f) > 1f - noisemap[(int)x, (int)y] * 2f && steepness <maxSteepness && height> waterLevel)
                {
                    treePos.Add(new Vector3(xScaled, heightScaled, yScaled));
                }

                y++;
            }
            x++;
        }

        TreeInstance[] treeInstances = new TreeInstance[treePos.Count];

        for (int ii = 0; ii < treeInstances.Length; ii++)
        {
            treeInstances[ii].position       = treePos[ii];
            treeInstances[ii].prototypeIndex = Random.Range(0, treeprototypes.Length);
            treeInstances[ii].color          = Color.white;//new Color(Random.Range(200, 255), Random.Range(200, 255), Random.Range(200, 255));
            treeInstances[ii].lightmapColor  = Color.white;
            treeInstances[ii].heightScale    = 1.0f + Random.Range(-0.25f, 0.5f);
            treeInstances[ii].widthScale     = 1.0f + Random.Range(-0.5f, 0.25f);
        }
        td.treeInstances = treeInstances;
    }
예제 #58
0
    public void LoadTerrain()
    {
        string fileName = "elevation.bhm";

        using (FileStream stream = new FileStream(fileName, FileMode.Open))
        {
            BinaryReader reader = new BinaryReader(stream);
            int          width  = reader.ReadInt32();
            int          height = reader.ReadInt32();

            int[] intData = new int[width * height];
            int   minValue = Int32.MaxValue, maxValue = 0;
            for (int i = 0; i < width * height; i++)
            {
                intData[i] = reader.ReadInt32();
                if (intData[i] < 0)
                {
                    intData[i] = 0;
                }
                if (intData[i] > 0 && minValue > intData[i])
                {
                    minValue = intData[i];
                }
                if (maxValue < intData[i])
                {
                    maxValue = intData[i];
                }
            }
            for (int i = 0; i < width * height; i++)
            {
                if (intData[i] >= minValue)
                {
                    intData[i] = intData[i] - minValue;
                }
            }
            maxValue = maxValue - minValue;
            float maxValueF  = maxValue;
            int   resolution = 2049;
            if (width < resolution)
            {
                resolution = width;
            }
            if (height < resolution)
            {
                resolution = height;
            }

            float[,] data = new float[resolution, resolution];
            for (int y = 0; y < resolution; y++)
            {
                for (int x = 0; x < resolution; x++)
                {
                    data[x, y] = intData[y * width + x] / maxValueF;
                }
            }

            TerrainData terrainData = new TerrainData();
            terrainData.heightmapResolution = resolution;
            terrainData.SetHeights(0, 0, data);
            terrainData.size = new Vector3(1000, 100, 1000);
            GameObject terrain = Terrain.CreateTerrainGameObject(terrainData);
            Instantiate(terrain, Vector3.zero, Quaternion.identity);
            //Instantiate(terrain, new Vector3 (1000, 0, 0), Quaternion.identity);
            //Instantiate(terrain, new Vector3(1000, 0, 1000), Quaternion.identity);
            //Instantiate(terrain, new Vector3(0, 0, 1000), Quaternion.identity);
        }
    }
예제 #59
0
    public void Start()
    {
        terrainData            = Terrain.activeTerrain.terrainData;
        float[,,] splatmapData = new float[terrainData.alphamapWidth,
                                           terrainData.alphamapHeight,
                                           terrainData.alphamapLayers];

        newHeightData = new float[terrainData.alphamapWidth, terrainData.alphamapHeight];

        ApplyPerlin();
        RoughTerrain();
        ApplyMountains();
        ApplyHoles();
        ApplyRiver();
        for (int i = 0; i < smoothAmount; i++)
        {
            SmoothTerrain();
        }

        terrainData.SetHeights(0, 0, newHeightData);

        for (int y = 0; y < terrainData.alphamapHeight; y++)
        {
            for (int x = 0; x < terrainData.alphamapWidth; x++)
            {
                float   terrainHeight = terrainData.GetHeight(y, x);
                float[] splat         = new float[splatHeights.Length];

                for (int i = 0; i < splatHeights.Length; i++)
                {
                    float thisNoise = map(Mathf.PerlinNoise(x * 0.05f, y * 0.05f), 0f, 1f, 0.5f, 1f);

                    float thisHeightStart = splatHeights[i].startHeight * thisNoise
                                            - splatHeights[i].overlap * thisNoise;
                    float nextHeightStart = 0;

                    if (i != splatHeights.Length - 1)
                    {
                        nextHeightStart = splatHeights[i + 1].startHeight * thisNoise
                                          + splatHeights[i + 1].overlap * thisNoise;
                    }

                    if (i == splatHeights.Length - 1 && terrainHeight >= thisHeightStart)
                    {
                        splat[i] = 1;
                    }
                    else if (terrainHeight >= thisHeightStart && terrainHeight <= nextHeightStart)
                    {
                        splat[i] = 1;
                    }
                }

                normalize(splat);

                for (int j = 0; j < splatHeights.Length; j++)
                {
                    splatmapData[x, y, j] = splat[j];
                }
            }
        }

        terrainData.SetAlphamaps(0, 0, splatmapData);
    }
예제 #60
0
        public void Export()
        {
            GameObject TerrainGO    = new GameObject();
            string     terrainName  = TerrainGO.name;
            string     FinalExpName = terrainName;

            int   tCount;
            int   counter;
            int   totalCount;
            float progressUpdateInterval = 10000;

            /*建立路径
             * if (!System.IO.Directory.Exists(T4MPrefabFolder + "Terrains/"))
             * {
             *  System.IO.Directory.CreateDirectory(T4MPrefabFolder + "Terrains/");
             * }
             * if (!System.IO.Directory.Exists(T4MPrefabFolder + "Terrains/Material/"))
             * {
             *  System.IO.Directory.CreateDirectory(T4MPrefabFolder + "Terrains/Material/");
             * }
             * if (!System.IO.Directory.Exists(T4MPrefabFolder + "Terrains/Texture/"))
             * {
             *  System.IO.Directory.CreateDirectory(T4MPrefabFolder + "Terrains/Texture/");
             * }
             * if (!System.IO.Directory.Exists(T4MPrefabFolder + "Terrains/Meshes/"))
             * {
             *  System.IO.Directory.CreateDirectory(T4MPrefabFolder + "Terrains/Meshes/");
             * }*/
            AssetDatabase.Refresh();
            TerrainData terrain = TerrainGO.GetComponent <Terrain>().terrainData;



            int     w         = terrain.heightmapWidth;
            int     h         = terrain.heightmapHeight;
            float   tRes      = w / 256;
            Vector3 meshScale = terrain.size;

            meshScale = new Vector3(meshScale.x / (h - 1) * tRes, meshScale.y, meshScale.z / (w - 1) * tRes);
            Vector2 uvScale = new Vector2((float)(1.0 / (w - 1)), (float)(1.0 / (h - 1)));

            float[,] tData = terrain.GetHeights(0, 0, w, h);
            w = (int)((w - 1) / tRes + 1);
            h = (int)((h - 1) / tRes + 1);
            Vector3[] tVertices = new Vector3[w * h];
            Vector2[] tUV       = new Vector2[w * h];
            int[]     tPolys    = new int[(w - 1) * (h - 1) * 6];
            int       y         = 0;
            int       x         = 0;

            for (y = 0; y < h; y++)
            {
                for (x = 0; x < w; x++)
                {
                    //tVertices[y*w + x] = Vector3.Scale(meshScale, new Vector3(x, tData[(int)(x*tRes),(int)(y*tRes)], y));
                    tVertices[y * w + x] = Vector3.Scale(meshScale, new Vector3(-y, tData[(int)(x * tRes), (int)(y * tRes)], x)); //Thank Cid Newman
                    tUV[y * w + x]       = Vector2.Scale(new Vector2(y * tRes, x * tRes), uvScale);
                }
            }

            y = 0;
            x = 0;
            int index = 0;

            for (y = 0; y < h - 1; y++)
            {
                for (x = 0; x < w - 1; x++)
                {
                    tPolys[index++] = (y * w) + x;
                    tPolys[index++] = ((y + 1) * w) + x;
                    tPolys[index++] = (y * w) + x + 1;

                    tPolys[index++] = ((y + 1) * w) + x;
                    tPolys[index++] = ((y + 1) * w) + x + 1;
                    tPolys[index++] = (y * w) + x + 1;
                }
            }

            bool   ExportNameSuccess = false;
            int    num = 1;
            string Next;

            do
            {
                Next = terrainName + num;

                if (!System.IO.File.Exists("Assets/RTSGameTools/TerrainData" + terrainName + ".prefab"))
                {
                    FinalExpName      = terrainName;
                    ExportNameSuccess = true;
                }
                else if (!System.IO.File.Exists("Assets/RTSGameTools/TerrainData" + Next + ".prefab"))
                {
                    FinalExpName      = Next;
                    ExportNameSuccess = true;
                }
                num++;
            } while (!ExportNameSuccess);

            //StreamWriter  sw = new StreamWriter(T4MPrefabFolder+"Terrains/Meshes/"+FinalExpName+".obj");
            StreamWriter sw = new StreamWriter(FinalExpName + ".obj");

            try
            {
                sw.WriteLine("# T4M File");
                System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
                counter    = tCount = 0;
                totalCount = (int)((tVertices.Length * 2 + (tPolys.Length / 3)) / progressUpdateInterval);
                for (int i = 0; i < tVertices.Length; i++)
                {
                    // UpdateProgress();
                    StringBuilder sb = new StringBuilder("v ", 20);
                    sb.Append(tVertices[i].x.ToString()).Append(" ").
                    Append(tVertices[i].y.ToString()).Append(" ").
                    Append(tVertices[i].z.ToString());
                    sw.WriteLine(sb);
                }

                for (int i = 0; i < tUV.Length; i++)
                {
                    // UpdateProgress();
                    StringBuilder sb = new StringBuilder("vt ", 22);
                    sb.Append(tUV[i].x.ToString()).Append(" ").
                    Append(tUV[i].y.ToString());
                    sw.WriteLine(sb);
                }
                for (int i = 0; i < tPolys.Length; i += 3)
                {
                    // UpdateProgress();
                    StringBuilder sb = new StringBuilder("f ", 43);
                    sb.Append(tPolys[i] + 1).Append("/").Append(tPolys[i] + 1).Append(" ").
                    Append(tPolys[i + 1] + 1).Append("/").Append(tPolys[i + 1] + 1).Append(" ").
                    Append(tPolys[i + 2] + 1).Append("/").Append(tPolys[i + 2] + 1);
                    sw.WriteLine(sb);
                }
            }
            catch (Exception err)
            {
                Debug.Log("Error saving file: " + err.Message);
            }
            sw.Close();
            AssetDatabase.SaveAssets();



            //UpdateProgress();

            /*  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
             *
             * //Deplacement de l'obj dans les repertoire mesh
             * FileUtil.CopyFileOrDirectory(FinalExpName + ".obj", T4MPrefabFolder + "Terrains/Meshes/" + FinalExpName + ".obj");
             * FileUtil.DeleteFileOrDirectory(FinalExpName + ".obj");
             *
             *
             *
             * //Force Update
             * AssetDatabase.ImportAsset(T4MPrefabFolder + "Terrains/Meshes/" + FinalExpName + ".obj", ImportAssetOptions.ForceUpdate);
             *
             * UpdateProgress();
             *
             * //Instance du T4M
             * GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(T4MPrefabFolder + "Terrains/Meshes/" + FinalExpName + ".obj", typeof(GameObject));
             *
             * AssetDatabase.Refresh();
             *
             *
             * GameObject forRotate = (GameObject)Instantiate(prefab, TerrainGO.transform.position, Quaternion.identity) as GameObject;
             * Transform childCheck = forRotate.transform.Find("default");
             * Child = childCheck.gameObject;
             * forRotate.transform.DetachChildren();
             * DestroyImmediate(forRotate);
             * Child.name = FinalExpName;
             * Child.AddComponent<T4MObjSC>();
             * //Child.transform.rotation= Quaternion.Euler(0, 90, 0);
             *
             * UpdateProgress();
             *
             * //Application des Parametres sur le Script
             * Child.GetComponent<T4MObjSC>().T4MMaterial = Tmaterial;
             * Child.GetComponent<T4MObjSC>().ConvertType = "UT";
             *
             * //Regalges Divers
             * vertexInfo = 0;
             * partofT4MObj = 0;
             * trisInfo = 0;
             * int countchild = Child.transform.childCount;
             * if (countchild > 0)
             * {
             *  Renderer[] T4MOBJPART = Child.GetComponentsInChildren<Renderer>();
             *  for (int i = 0; i < T4MOBJPART.Length; i++)
             *  {
             *      if (!T4MOBJPART[i].gameObject.AddComponent<MeshCollider>())
             *          T4MOBJPART[i].gameObject.AddComponent<MeshCollider>();
             *      T4MOBJPART[i].gameObject.isStatic = true;
             *      T4MOBJPART[i].material = Tmaterial;
             *      T4MOBJPART[i].gameObject.layer = 30;
             *      T4MOBJPART[i].gameObject.AddComponent<T4MPartSC>();
             *      Child.GetComponent<T4MObjSC>().T4MMesh = T4MOBJPART[0].GetComponent<MeshFilter>();
             *      partofT4MObj += 1;
             *      vertexInfo += T4MOBJPART[i].gameObject.GetComponent<MeshFilter>().sharedMesh.vertexCount;
             *      trisInfo += T4MOBJPART[i].gameObject.GetComponent<MeshFilter>().sharedMesh.triangles.Length / 3;
             *  }
             * }
             * else
             * {
             *  Child.AddComponent<MeshCollider>();
             *  Child.isStatic = true;
             *  Child.GetComponent<Renderer>().material = Tmaterial;
             *  Child.layer = 30;
             *  vertexInfo += Child.GetComponent<MeshFilter>().sharedMesh.vertexCount;
             *  trisInfo += Child.GetComponent<MeshFilter>().sharedMesh.triangles.Length / 3;
             *  partofT4MObj += 1;
             * }
             *
             * UpdateProgress();
             *
             *
             * GameObject BasePrefab2 = PrefabUtility.CreatePrefab(T4MPrefabFolder + "Terrains/" + FinalExpName + ".prefab", Child);
             * AssetDatabase.ImportAsset(T4MPrefabFolder + "Terrains/" + FinalExpName + ".prefab", ImportAssetOptions.ForceUpdate);
             * GameObject forRotate2 = (GameObject)PrefabUtility.InstantiatePrefab(BasePrefab2) as GameObject;
             *
             * DestroyImmediate(Child.gameObject);
             *
             * Child = forRotate2.gameObject;
             *
             * TerrainGO.GetComponent<Terrain>().enabled = false;
             *
             * EditorUtility.SetSelectedWireframeHidden(Child.GetComponent<Renderer>(), true);
             *
             * UnityTerrain = TerrainGO.gameObject;
             *
             * EditorUtility.ClearProgressBar();
             *
             * AssetDatabase.DeleteAsset(T4MPrefabFolder + "Terrains/Meshes/Materials");
             * terrainName = "";
             * AssetDatabase.StartAssetEditing();
             * //Modification des attribut du mesh avant de le pr茅fabriquer
             * ModelImporter OBJI = ModelImporter.GetAtPath(T4MPrefabFolder + "Terrains/Meshes/" + FinalExpName + ".obj") as ModelImporter;
             * OBJI.globalScale = 1;
             * OBJI.splitTangentsAcrossSeams = true;
             * OBJI.normalImportMode = ModelImporterTangentSpaceMode.Calculate;
             * OBJI.tangentImportMode = ModelImporterTangentSpaceMode.Calculate;
             * OBJI.generateAnimations = ModelImporterGenerateAnimations.None;
             * OBJI.meshCompression = ModelImporterMeshCompression.Off;
             * OBJI.normalSmoothingAngle = 180f;
             * //AssetDatabase.ImportAsset (T4MPrefabFolder+"Terrains/Meshes/"+FinalExpName+".obj", ImportAssetOptions.TryFastReimportFromMetaData);
             * AssetDatabase.ImportAsset(T4MPrefabFolder + "Terrains/Meshes/" + FinalExpName + ".obj", ImportAssetOptions.ForceSynchronousImport);
             * AssetDatabase.StopAssetEditing();
             * PrefabUtility.ResetToPrefabState(Child);
             *
             *
             *//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        }