using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System;
///
/// 地形切分 引擎工具类
///
public class MySplitTerrain : EditorWindow
{
// 目标地形
private Terrain LargeTargetTerrain;
// 目标数据
private TerrainData LargeTargetData;
// 切分次数
private int TerrainNum = 4;
//
private int TerrainNumKH = 2;
// 地图切片
private Terrain[,] IndividualTerrain;
// 地图切片数据
private TerrainData[,] IndividualTerrainData;
// 宽长高
private float W, L, H;
private float X, Z;
// 缩放
private Vector3 scale;
// 植被数量
private TreeInstance[] TreeNum;
private GameObject[] treeainS;
private int Pixel_Error = 200;
private int Base_Map_Dist = 30;
private bool Cast_Shadows = true;
private Material Material;
private bool Draw = true;
private int Detail_Distance = 30;
private float Detail_Density = 1f;
private int Tree_Distance = 30;
private int Billboad_Start = 30;
private int Fabe_Length = 5;
private int Max_Mesh_Trees = 30;
private float Speed = 0.5f;
private float Size = 0.5f;
private float Bending = 0.5f;
private Color Grass_Tint = new Color(0.7F, 0.6F, 0.5F, 0);
private Vector2 scrollPosTerrain;
[MenuItem("地图/地形切分工具")]
public static void OpenSplitTerrainWindow()
{
EditorWindow.GetWindow(typeof(MySplitTerrain));
}
void Update()
{
}
void OnGUI()
{
GUILayout.Label("目标地形预制体");
LargeTargetTerrain = EditorGUILayout.ObjectField(LargeTargetTerrain, typeof(Terrain), true) as Terrain;
GUILayout.Label("切分数量2的幂");
//248
TerrainNumKH = EditorGUILayout.IntField(TerrainNumKH);
if (!Mathf.IsPowerOfTwo(TerrainNumKH))
{
return;
}
if (GUILayout.Button("生成"))
{
Split();
}
GUILayout.BeginArea(new Rect(10, 120, 500, 700));
GUILayout.Label("地形数据检测");
GUILayout.Label("---Base Terrain---");
GUILayout.Label("像素误差");
Pixel_Error = (int)EditorGUILayout.Slider(Pixel_Error, 1, 200);
GUILayout.Label("基础切片区域");
Base_Map_Dist = (int)EditorGUILayout.Slider(Base_Map_Dist, 0, 2000);
//GUILayout.Label("Cast shadows");
Cast_Shadows = EditorGUILayout.Toggle("阴影品质", Cast_Shadows);
//GUILayout.Label("Material");
//Material = EditorGUILayout.ObjectField(Material, typeof(Material), true) as Material;
//GUILayout.Label("---Tree &Detail Objects---");
//// GUILayout.Label("Draw");
//Draw = EditorGUILayout.Toggle("Draw", Draw);
//GUILayout.Label("细节距离");
//Detail_Distance = (int)EditorGUILayout.Slider(Detail_Distance, 0, 250);
//GUILayout.Label("细节密度");
//Detail_Density = EditorGUILayout.Slider(Detail_Density, 0, 1);
//GUILayout.Label("植被距离");
//Tree_Distance = (int)EditorGUILayout.Slider(Tree_Distance, 0, 2000);
//GUILayout.Label("Billboad Start");
//Billboad_Start = (int)EditorGUILayout.Slider(Billboad_Start, 5, 2000);
//GUILayout.Label("Fabe Length");
//Fabe_Length = (int)EditorGUILayout.Slider(Fabe_Length, 0, 200);
//GUILayout.Label("Max Mesh Trees");
//Max_Mesh_Trees = (int)EditorGUILayout.Slider(Max_Mesh_Trees, 0, 10000);
//GUILayout.Label("---Wind Settings---");
//GUILayout.Label("Speed");
//Speed = EditorGUILayout.Slider(Speed, 0, 1);
//GUILayout.Label("Size");
//Size = EditorGUILayout.Slider(Size, 0, 1);
//GUILayout.Label("Bending");
//Bending = EditorGUILayout.Slider(Bending, 0, 1);
// GUILayout.Label("Grass Tint");
//Grass_Tint = EditorGUILayout.ColorField("Grass Tint", Grass_Tint);
if (GUILayout.Button("地形批量修改"))
{
Terrainbatchchange();
}
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(520, 120, 300, 700));
GUILayout.Label("Treeain) ");
if (GUILayout.Button("地形列表"))
{
GetTerrainNumList();
}
scrollPosTerrain = GUILayout.BeginScrollView(scrollPosTerrain, GUILayout.Width(300), GUILayout.Height(500));
if (treeainS != null)
for (int i = 0; i < treeainS.Length; i++)
{
treeainS[i] = EditorGUILayout.ObjectField(treeainS[i], typeof(GameObject), true) as GameObject;
}
GUILayout.EndScrollView();
GUILayout.EndArea();
GUILayout.Space(20);
}
void GetTerrainNumList()
{
treeainS = GameObject.FindGameObjectsWithTag("Terrain");
}
void Terrainbatchchange()
{
for (int i = 0; i < treeainS.Length; i++)
{
treeainS[i].GetComponent().heightmapPixelError = LargeTargetTerrain.heightmapPixelError;
treeainS[i].GetComponent().basemapDistance = LargeTargetTerrain.basemapDistance;
treeainS[i].GetComponent().castShadows = LargeTargetTerrain.castShadows;
treeainS[i].GetComponent().materialTemplate = LargeTargetTerrain.materialTemplate;
treeainS[i].GetComponent().enabled = LargeTargetTerrain.enabled;
treeainS[i].GetComponent().detailObjectDistance = LargeTargetTerrain.detailObjectDistance;
treeainS[i].GetComponent().detailObjectDensity = LargeTargetTerrain.detailObjectDensity;
treeainS[i].GetComponent().treeDistance = LargeTargetTerrain.treeDistance;
treeainS[i].GetComponent().treeBillboardDistance = LargeTargetTerrain.treeBillboardDistance;
treeainS[i].GetComponent().treeCrossFadeLength = LargeTargetTerrain.treeCrossFadeLength;
treeainS[i].GetComponent().treeMaximumFullLODCount = LargeTargetTerrain.treeMaximumFullLODCount;
treeainS[i].GetComponent().terrainData.wavingGrassStrength = LargeTargetTerrain.terrainData.wavingGrassStrength;
treeainS[i].GetComponent().terrainData.wavingGrassSpeed = LargeTargetTerrain.terrainData.wavingGrassSpeed;
treeainS[i].GetComponent().terrainData.wavingGrassAmount = LargeTargetTerrain.terrainData.wavingGrassAmount;
treeainS[i].GetComponent().terrainData.wavingGrassTint = LargeTargetTerrain.terrainData.wavingGrassTint;
treeainS[i].GetComponent().terrainData.terrainLayers = LargeTargetData.terrainLayers;
}
}
void Split()
{
GetDataLargeTargetTerrain();
IndividualTerrainCreat();
divisionTreeainData();
DiveisionTreeatinAlphamapData();
DiveisionTreeatinTree();
DiveisionTreeatinGrass();
}
void GetDataLargeTargetTerrain()
{
LargeTargetData = LargeTargetTerrain.terrainData;
scale = LargeTargetData.size;
TreeNum = LargeTargetData.treeInstances;
}
void IndividualTerrainCreat()
{
TerrainNum = TerrainNumKH * TerrainNumKH;
try
{
double num = Mathf.Sqrt(TerrainNum);
string str = num.ToString();
str = str.Substring(str.LastIndexOf('.'), 2);
}
catch (Exception)
{
string path = AssetDatabase.GetAssetPath(LargeTargetTerrain);
if(path == "")
{
return;
}
W = LargeTargetTerrain.terrainData.size.x;
H = LargeTargetTerrain.terrainData.size.y;
L = LargeTargetTerrain.terrainData.size.z;
TerrainNumKH = (int)Mathf.Sqrt(TerrainNum);
IndividualTerrainData = new TerrainData[TerrainNumKH, TerrainNumKH];
IndividualTerrain = new Terrain[TerrainNumKH, TerrainNumKH];
Vector3[,] TerrainPoint = new Vector3[TerrainNumKH, TerrainNumKH];
X = W / TerrainNumKH;
Z = W / TerrainNumKH;
for (int i = 0; i < TerrainNumKH; i++)
{
for (int j = 0; j < TerrainNumKH; j++)
{
IndividualTerrainData[i, j] = new TerrainData();
IndividualTerrain[i, j] = Terrain.CreateTerrainGameObject(IndividualTerrainData[i, j]).GetComponent();
TerrainPoint[i, j] = new Vector3(i * X, 0, j * Z);
IndividualTerrainData[i, j].heightmapResolution = (int)LargeTargetData.heightmapResolution / TerrainNumKH;
IndividualTerrainData[i, j].size = new Vector3(W / TerrainNumKH, LargeTargetData.size.y, L / TerrainNumKH);
IndividualTerrain[i, j].transform.position = TerrainPoint[i, j];
IndividualTerrain[i, j].transform.name = (IndividualTerrain[i, j].transform.name + i + j);
IndividualTerrain[i, j].heightmapPixelError = LargeTargetTerrain.heightmapPixelError;
IndividualTerrain[i, j].basemapDistance = LargeTargetTerrain.basemapDistance;
IndividualTerrain[i, j].castShadows = LargeTargetTerrain.castShadows;
IndividualTerrain[i, j].reflectionProbeUsage = LargeTargetTerrain.reflectionProbeUsage;
IndividualTerrain[i, j].materialTemplate = LargeTargetTerrain.materialTemplate;
IndividualTerrain[i, j].enabled = LargeTargetTerrain.enabled;
IndividualTerrain[i, j].detailObjectDistance = LargeTargetTerrain.detailObjectDistance;
IndividualTerrain[i, j].detailObjectDensity = LargeTargetTerrain.detailObjectDensity;
IndividualTerrain[i, j].treeDistance = LargeTargetTerrain.treeDistance;
IndividualTerrain[i, j].treeBillboardDistance = LargeTargetTerrain.treeBillboardDistance;
IndividualTerrain[i, j].treeCrossFadeLength = LargeTargetTerrain.treeCrossFadeLength;
IndividualTerrain[i, j].treeMaximumFullLODCount = LargeTargetTerrain.treeMaximumFullLODCount;
IndividualTerrain[i, j].terrainData.wavingGrassStrength = LargeTargetTerrain.terrainData.wavingGrassStrength;
IndividualTerrain[i, j].terrainData.wavingGrassSpeed = LargeTargetTerrain.terrainData.wavingGrassSpeed;
IndividualTerrain[i, j].terrainData.wavingGrassAmount = LargeTargetTerrain.terrainData.wavingGrassAmount;
IndividualTerrain[i, j].terrainData.wavingGrassTint = LargeTargetTerrain.terrainData.wavingGrassTint;
IndividualTerrain[i, j].terrainData.terrainLayers = LargeTargetData.terrainLayers;
IndividualTerrain[i, j].transform.parent = LargeTargetTerrain.transform;
MySplitTerrainTile mystt = IndividualTerrain[i, j].gameObject.GetOrAddComponent();
mystt.refreshTime = 1;
AssetDatabase.CreateAsset(IndividualTerrainData[i, j], AssetDatabase.GetAssetPath(LargeTargetTerrain) + IndividualTerrain[i, j].transform.name + i + j + ".asset");
}
}
}
}
void divisionTreeainData()
{
for (int i = 0; i < TerrainNumKH; i++)
{
for (int j = 0; j < TerrainNumKH; j++)
{
IndividualTerrain[i, j].basemapDistance = 100;
int X, Y;
X = LargeTargetData.heightmapResolution / TerrainNumKH;
Y = LargeTargetData.heightmapResolution / TerrainNumKH;
float[,] height = LargeTargetData.GetHeights(X * i, Y * j, X + 1, Y + 1);
IndividualTerrainData[i, j].SetHeights(0, 0, height);
}
}
}
void DiveisionTreeatinAlphamapData()
{
for (int i = 0; i < TerrainNumKH; i++)
{
for (int j = 0; j < TerrainNumKH; j++)
{
int X, Y;
X = LargeTargetData.alphamapWidth / TerrainNumKH;
Y = LargeTargetData.alphamapHeight / TerrainNumKH;
float[,,] aMap = LargeTargetData.GetAlphamaps(X * i, Y * j, X, Y);
IndividualTerrainData[i, j].alphamapResolution = LargeTargetData.alphamapResolution / TerrainNumKH;
//IndividualTerrainData[i, j].splatPrototypes = LargeTargetData.splatPrototypes;
IndividualTerrainData[i, j].SetAlphamaps(0, 0, aMap);
}
}
}
void DiveisionTreeatinTree()
{
List TreesPoint = new List();
for (int k = 0; k < TreeNum.Length; k++)
{
Vector3 treespoint = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L);
TreesPoint.Add(treespoint);
}
for (int i = 0; i < TerrainNumKH; i++)
{
for (int j = 0; j < TerrainNumKH; j++)
{
IndividualTerrainData[i, j].treePrototypes = LargeTargetData.treePrototypes;
Vector3 IndividualTerrainSize = IndividualTerrain[i, j].terrainData.size;
Vector3 IndividualTerrainPoint = IndividualTerrain[i, j].transform.position;
Rect rect = new Rect(IndividualTerrainPoint.x, IndividualTerrainPoint.z, IndividualTerrainSize.x, IndividualTerrainSize.z);
List trees = new List();
trees.Clear();
for (int k = 0; k < TreeNum.Length; k++)
{
if (rect.Contains(new Vector2(TreeNum[k].position.x * W, TreeNum[k].position.z * L)))
{
Vector3 treesList = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L);
for (int p = 0; p < TreesPoint.Count; p++)
{
if (treesList == TreesPoint[p])
{
Vector3 ScreenTreeS = new Vector3(TreeNum[k].position.x * W, TreeNum[k].position.y * H, TreeNum[k].position.z * L);
Vector3 ZDTreeS = new Vector3(ScreenTreeS.x - IndividualTerrainPoint.x, ScreenTreeS.y, ScreenTreeS.z - IndividualTerrainPoint.z);
Vector3 shareTree = new Vector3(ZDTreeS.x / IndividualTerrainSize.x, ZDTreeS.y / IndividualTerrainSize.y, ZDTreeS.z / IndividualTerrainSize.z);
TreeNum[k].position = shareTree;
trees.Add(TreeNum[k]);
}
}
}
}
IndividualTerrainData[i, j].treeInstances = trees.ToArray();
}
}
}
void DiveisionTreeatinGrass()
{
DetailPrototype[] Grass = LargeTargetData.detailPrototypes;
int LargetSize = LargeTargetData.detailResolution;
for (int i = 0; i < TerrainNumKH; i++)
{
for (int j = 0; j < TerrainNumKH; j++)
{
IndividualTerrainData[i, j].detailPrototypes = Grass;
IndividualTerrainData[i, j].SetDetailResolution(LargetSize / TerrainNumKH, 8);
for (int k = 0; k < Grass.Length; k++)
{
int[,] text = LargeTargetData.GetDetailLayer(LargetSize / TerrainNumKH * i, LargetSize / TerrainNumKH * j, LargetSize / TerrainNumKH, LargetSize / TerrainNumKH, k);
IndividualTerrainData[i, j].SetDetailLayer(0, 0, k, text);
}
}
}
}
}