unity 通过图片信息制作地形图

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class testTerrain : MonoBehaviour {
	public Material diffuseMap;
	public Texture2D heightMap;
	//顶点、uv、索引信息
	private Vector3[] vertives;
	private Vector2[] uvs;
	private int[] triangles;

	//生成信息
	private Vector2 size;//长宽
	private float minHeight = -10;
	private float maxHeight = 10;
	private Vector2 segment;
	private float unitH;

	//面片mesh
	private GameObject terrain;

	// Use this for initialization
	void Start()
	{
		//默认生成一个地形,如果不喜欢,注销掉然后用参数生成
		SetTerrain();
	}


	/// <summary>
	/// 生成默认地形
	/// </summary>
	public void SetTerrain()
	{
		SetTerrain(100, 100, 50, 50, -10, 10);
	}

	/// <summary>
	/// 通过参数生成地形
	/// </summary>
	/// <param name="width">地形宽度</param>
	/// <param name="height">地形长度</param>
	/// <param name="segmentX">宽度的段数</param>
	/// <param name="segmentY">长度的段数</param>
	/// <param name="min">最低高度</param>
	/// <param name="max">最高高度</param>
	public void SetTerrain(float width, float height, uint segmentX, uint segmentY, int min, int max)
	{
		Init(width, height, segmentX, segmentY, min, max);
		GetVertives();
		DrawMesh();
	}

	/// <summary>
	/// 初始化计算某些值
	/// </summary>
	/// <param name="width"></param>
	/// <param name="height"></param>
	/// <param name="segmentX"></param>
	/// <param name="segmentY"></param>
	/// <param name="min"></param>
	/// <param name="max"></param>
	private void Init(float width, float height, uint segmentX, uint segmentY, int min, int max)
	{
		size = new Vector2(width, height);
		maxHeight = max;
		minHeight = min;
		unitH = maxHeight - minHeight;
		segment = new Vector2(segmentX, segmentY);
		if (terrain != null)
		{
			Destroy(terrain);
		}
		terrain = new GameObject();
		terrain.name = "plane";
	}

	/// <summary>
	/// 绘制网格
	/// </summary>
	private void DrawMesh()
	{
		Mesh mesh = terrain.AddComponent<MeshFilter>().mesh;
		terrain.AddComponent<MeshRenderer>();
		if (diffuseMap == null)
		{
			Debug.LogWarning("No material,Create diffuse!!");
			diffuseMap = new Material(Shader.Find("Diffuse"));
		}
		if (heightMap == null)
		{
			Debug.LogWarning("No heightMap!!!");
		}
		//terrain.renderer.material = diffuseMap;
		//给mesh 赋值
		mesh.Clear();
		mesh.vertices = vertives;//,pos);
		mesh.uv = uvs;
		mesh.triangles = triangles;
		//重置法线
		mesh.RecalculateNormals();
		//重置范围
		mesh.RecalculateBounds();
	}

	/// <summary>
	/// 生成顶点信息
	/// </summary>
	/// <returns></returns>
	private Vector3[] GetVertives()
	{
		int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));
		float w = size.x / segment.x;
		float h = size.y / segment.y;

		int index = 0;
		GetUV();
		GetTriangles();
		vertives = new Vector3[sum];
		for (int i = 0; i < segment.y + 1; i++)
		{
			for (int j = 0; j < segment.x + 1; j++)
			{
				float tempHeight = 0;
				if (heightMap != null)
				{
					tempHeight = GetHeight(heightMap, uvs[index]);
				}
				vertives[index] = new Vector3(j * w, tempHeight, i * h);
				index++;
			}
		}
		return vertives;
	}

	/// <summary>
	/// 生成UV信息
	/// </summary>
	/// <returns></returns>
	private Vector2[] GetUV()
	{
		int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));
		uvs = new Vector2[sum];
		float u = 1.0F / segment.x;
		float v = 1.0F / segment.y;
		uint index = 0;
		for (int i = 0; i < segment.y + 1; i++)
		{
			for (int j = 0; j < segment.x + 1; j++)
			{
				uvs[index] = new Vector2(j * u, i * v);
				index++;
			}
		}
		return uvs;
	}

	/// <summary>
	/// 生成索引信息
	/// </summary>
	/// <returns></returns>
	private int[] GetTriangles()
	{
		int sum = Mathf.FloorToInt(segment.x * segment.y * 6);
		triangles = new int[sum];
		uint index = 0;
		for (int i = 0; i < segment.y; i++)
		{
			for (int j = 0; j < segment.x; j++)
			{
				int role = Mathf.FloorToInt(segment.x) + 1;
				int self = j + (i * role);
				int next = j + ((i + 1) * role);
				triangles[index] = self;
				triangles[index + 1] = next + 1;
				triangles[index + 2] = self + 1;
				triangles[index + 3] = self;
				triangles[index + 4] = next;
				triangles[index + 5] = next + 1;
				index += 6;
			}
		}
		return triangles;
	}

	private float GetHeight(Texture2D texture, Vector2 uv)
	{
		if (texture != null)
		{
			//提取灰度。如果强制读取某个通道,可以忽略
			Color c = GetColor(texture, uv);
			float gray = c.grayscale;//或者可以自己指定灰度提取算法,比如:gray = 0.3F * c.r + 0.59F * c.g + 0.11F * c.b;
			float h = unitH * gray;
			return h;
		}
		else
		{
			return 0;
		}
	}
	/// <summary>
	/// 获取图片上某个点的颜色
	/// </summary>
	/// <param name="texture"></param>
	/// <param name="uv"></param>
	/// <returns></returns>
	private Color GetColor(Texture2D texture, Vector2 uv)
	{

		Color color = texture.GetPixel(Mathf.FloorToInt(texture.width * uv.x), Mathf.FloorToInt(texture.height * uv.y));
		return color;
	}

	/// <summary>
	/// 从外部设置地形的位置坐标
	/// </summary>
	/// <param name="pos"></param>
	public void SetPos(Vector3 pos)
	{
		if (terrain)
		{
			terrain.transform.position = pos;
		}
		else
		{
			SetTerrain();
			terrain.transform.position = pos;
		}
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值