unity读取灰度图生成三维地形mesh
准备灰度图 IGray.png及草地贴图 IGrass.jpg ,放入Assets下StreamingAssets文件夹中。
创建空材质,用作参数传入脚本。
脚本如下,挂载并传入材质球即可根据灰度图生成mesh。
using System.Collections; using System.Collections.Generic; using UnityEngine; //根据灰度图创建mesh地形 public class MeshTerrainCreate : MonoBehaviour { private Texture textureGray;//灰度图 private Texture textureGrass;//草地贴图 private int tGrayWidth = 0, tGrayHeight = 0;//灰度图的宽和高 private bool bCreate = false;//是否完成创建 private List<GameObject> meshList;//mesh对象集合 private Texture2D texture2dGray; public float zScale=100;//高度参数 [Tooltip("传入mesh使用的材质")] public Material meshMaterial; void Start() { StartCoroutine(loadImage("IGray.png", (t) => textureGray = t)); StartCoroutine(loadImage("IGrass.jpg", (t) => textureGrass = t)); meshList = new List<GameObject>(); } void Update() { if (textureGray != null && textureGrass != null) { if (bCreate == false) { tGrayWidth = textureGray.width; tGrayHeight = textureGray.height; meshMaterial.mainTexture = textureGrass;//设置材质贴图 //mesh顶点数目最大65000,则取mesh顶点为250*250=62500 int xNum = 1+tGrayWidth / 250;//x方向mesh个数 int yNum = 1+tGrayHeight / 250; //y方向mesh个数 texture2dGray = (Texture2D)textureGray; //根据灰度图创建mesh for (int i = 0; i <xNum; i++) { for (int j = 0; j <yNum; j++) { if (i < xNum-1 && j < yNum-1) { meshList.Add( createMesh("meshX" + i.ToString() + "Y" + j.ToString(), 251, 251, i * new Vector3(2500, 0, 0) + j * new Vector3(0, 2500, 0), (i + 1) * new Vector3(2500, 0, 0) + (j + 1) * new Vector3(0, 2500, 0)+new Vector3(10,10,0), i * new Vector2(250, 0) + j * new Vector2(0, 250), (i + 1) * new Vector2(250, 0) + (j + 1) * new Vector2(0, 250)+new Vector2(1,1))); } else if (i == xNum-1 && j < yNum-1) { meshList.Add(createMesh("meshX" + i.ToString() + "Y" + j.ToString(), tGrayWidth%250, 251, i * new Vector3(2500, 0, 0) + j * new Vector3(0, 2500, 0), i* new Vector3(2500, 0, 0)+new Vector3(10*(tGrayWidth % 250),10,0) + (j + 1) * new Vector3(0, 2500, 0), i * new Vector2(250, 0) + j * new Vector2(0, 250), i * new Vector2(250, 0)+new Vector2(tGrayWidth % 250,1) + (j + 1) * new Vector2(0, 250))); } else if (i < xNum-1 && j == yNum-1) { meshList.Add(createMesh("meshX" + i.ToString() + "Y" + j.ToString(),251, tGrayHeight%250, i * new Vector3(2500, 0, 0) + j * new Vector3(0, 2500, 0), (i + 1) * new Vector3(2500, 0, 0) + j * new Vector3(0, 2500, 0)+new Vector3(10,10* (tGrayHeight % 250),0), i * new Vector2(250, 0) + j * new Vector2(0, 250), (i + 1) * new Vector2(250, 0) + j * new Vector2(0, 150)+new Vector2(1, tGrayHeight % 250) ) ); } else if (i == xNum-1 && j == yNum-1) { meshList.Add(createMesh("meshX" + i.ToString() + "Y" + j.ToString(),tGrayWidth%250,tGrayHeight%250, i * new Vector3(2500, 0, 0) + j * new Vector3(0, 2500, 0), i * new Vector3(2500, 0, 0) + j * new Vector3(0, 2500, 0)+new Vector3(10 * (tGrayWidth % 250), 10 * (tGrayHeight % 250),0), i * new Vector2(250, 0) + j * new Vector2(0, 250), i * new Vector2(250, 0) + j * new Vector2(0, 250) +new Vector2(tGrayWidth % 250, tGrayHeight % 250)) ); } } } bCreate = true; } } } //加载图片 IEnumerator loadImage(string imagePath, System.Action<Texture> action) { WWW www = new WWW("file://" + Application.streamingAssetsPath + "/" + imagePath); yield return www; if (www.error == null) { action(www.texture); } } /// <summary> ///创建mesh /// </summary> /// <param name="meshName">mesh名称</param> /// <param name="row">行数</param> /// <param name="col">列数</param> /// <param name="minPoint">最小点位置</param> /// <param name="maxPoint">最大点位置</param> /// <param name="minImgPosition">最小点灰度图位置</param> /// <param name="maxImgPosition">最大点灰度图位置</param> /// <returns></returns> /// private GameObject createMesh(string meshName, int row, int col, Vector3 minPoint, Vector3 maxPoint, Vector2 minImgPosition, Vector2 maxImgPosition) { GameObject meshObject = new GameObject(meshName); int verticeNum = row * col; Vector3[] vertices = new Vector3[verticeNum];//顶点数组大小 int[] triangles = new int[verticeNum * 3 * 2];//三角集合数组,保存顶点索引 // Vector3[] normals = new Vector3[verticeNum];//顶点法线数组大小 Vector2[] uvs = new Vector2[verticeNum]; float rowF = (float)row; float colF = (float)col; Vector3 xStep = new Vector3((maxPoint.x - minPoint.x) / rowF, 0, 0); Vector3 ySetp = new Vector3(0, (maxPoint.y - minPoint.y) / colF, 0); int k = 0; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { float tempZ = texture2dGray.GetPixel((int)minImgPosition.x + i, (int)minImgPosition.y + j).grayscale; vertices[i + j * row] = minPoint + xStep * i + ySetp * j+new Vector3(0,0,tempZ* zScale); uvs[i + j * row] = new Vector2((float)i / rowF, (float)j / colF); if (j < col - 1 && i < row - 1) { triangles[k++] = j * row + i; triangles[k++] = j * row + i + 1; triangles[k++] = j * row + i + row; triangles[k++] = j * row + i + row; triangles[k++] = j * row + i + 1; triangles[k++] = j * row + i + row + 1; } } } Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = triangles; // mesh.normals = normals; mesh.uv = uvs; mesh.RecalculateBounds(); mesh.RecalculateNormals(); meshObject.AddComponent<MeshFilter>(); meshObject.AddComponent<MeshRenderer>(); meshObject.GetComponent<MeshFilter>().mesh = mesh; meshObject.GetComponent<MeshRenderer>().material = meshMaterial; return meshObject; } }
效果如下