Unity 生成DEM地形方法(纯代码)

Unity 生成DEM地形方法(纯代码)

(下面代码比较完整,如有需要可以下载工程文件)工程文件地址

基本思路

首先创建n × \times ×n个顶点的平面网格,用每一个网点的相对坐标对DEM(数字高程模型)进行采样,取得0~1的灰度值,将灰度值乘上高度系数得到相对高程,最后用高度值修改网格点三维坐标的Y值。

对DEM的理解

DEM是对地形高度的一种灰度图表现,越白的地方越接近1,表示越高,越黑的地方越接近0,表示越低。

n × \times ×n网格建立

为了方便采样,将建立网格的起始点定在左下角,与uv和图片的原点一致。

为了后面做位置变换,网格的原点定在中心。

网格建立完整代码

 public static class MeshExtention
    {
        /// <summary>
        /// 创建正方形面
        /// </summary>
        /// <param name="size">尺寸</param>
        /// <param name="num">细分</param>
        /// <returns></returns>
        public static Mesh CreateSquareArea(this Mesh mesh ,float size,int num)
        {
            //一共多少行/列
            int ranks = 2 * num + 1;
            int pointsCount = ranks * ranks;
            Vector3[] meshPoints = new Vector3[pointsCount];
            int[] triangles = new int[24 * num * num];
            Vector2[] uvs = new Vector2[pointsCount];
            float halfSize = size * 0.5f;
            //左下角角点
            Vector3 cornerPoint = new Vector3(-halfSize, 0, -halfSize);
            //距离单位偏移
            float unitSize = size / (num * 2);
            //距离单位偏移X
            Vector3 unitVec_x= new Vector3(unitSize, 0, 0);
            //距离单位偏移Z
            Vector3 unitVec_z = new Vector3(0, 0, unitSize);
            //UV单位偏移
            float unitUV = 1.00f / (num * 2.00f);
            //UV单位偏移X
            Vector2 uvVec_x = new Vector2(unitUV, 0);
            //UV单位偏移Y
            Vector2 uvVec_y = new Vector2(0,unitUV);
            int k = 0;
            for (int i = 0; i < ranks; i++)
            {
                for (int j = 0; j < ranks; j++)
                {
                    meshPoints[i* ranks+ j] = cornerPoint + j * unitVec_x + i * unitVec_z;
                
                    uvs[i * ranks + j] = j * uvVec_x + i * uvVec_y;
                   
                    if (i < ranks-1&& j < ranks-1)
                    {
                        triangles[k] = (i * ranks) + j+1;
                        triangles[k + 1] = (i * ranks) + j;
                        triangles[k + 2] = ((i + 1) * ranks) + j;
                        triangles[k + 3] = (i * ranks) + j+1;
                        triangles[k + 4] = ((i + 1) * ranks) + j;
                        triangles[k + 5] = ((i + 1) * ranks) + j+1;
                        k += 6;
                    }
                }
            }
            mesh.vertices = meshPoints;
            mesh.triangles = triangles;
            mesh.uv = uvs;
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();
            return mesh;
        }
    }

DEM采样

有网格的uv做为采样坐标,完美的切合了图片的坐标信息。

   public Texture texture;
    public Texture2D Dem;
    [Range(10, 100)]//高度系数范围
    public int Range;
    public int num=20;//点数量
    public float size=100;//地图尺寸

    void Start()
    {
        GameObject game = new GameObject();
        MeshFilter filter = game.AddComponent<MeshFilter>();
        MeshRenderer renderer = game.AddComponent<MeshRenderer>();
        Material material= new Material(Shader.Find("Standard"));
        material.mainTexture = texture;
        renderer.sharedMaterial = material;
        Mesh mesh = new Mesh(); 
        mesh.CreateSquareArea(size, num);
        int length = mesh.vertices.Length;
        Vector3[] newVector3s = new Vector3[length];
        for (int i = 0; i < length; i++)
        {
            Vector2 uv = mesh.uv[i];
            int x =(int)(Dem.width * uv.x);
            int y = (int)(Dem.height * uv.y);
            float heightVelue = Dem.GetPixel(x, y).grayscale * Range;//采样
            Vector3 vector3 = mesh.vertices[i];
            newVector3s[i]= new Vector3(vector3.x, heightVelue, vector3.z);
        }
        mesh.vertices = newVector3s;
        filter.mesh = mesh;
    }

猜你喜欢

转载自blog.csdn.net/dxs1990/article/details/126382760
今日推荐