Unity generates DEM terrain method (pure code)

Unity generates DEM terrain method (pure code)

(The code below is relatively complete, and you can download the project file if necessary) Project file address

The basic idea

First create n × \timesA plane grid with n vertices, use the relative coordinates of each network point to sample the DEM (Digital Elevation Model), obtain the gray value of 0~1, multiply the gray value by the height coefficient to obtain the relative elevation, and finally use the height The value modifies the Y value of the 3D coordinate of the grid point.

Understanding of DEM

DEM is a grayscale representation of terrain height. The whiter the place is, the closer to 1, it means higher, and the darker the place, the closer to 0, it means lower.

n × \times × n grid build

In order to facilitate sampling, the starting point of establishing the grid is set at the lower left corner, which is consistent with the origin of uv and the picture.

In order to do position transformation later, the origin of the grid is set at the center.

Grid build complete code

 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 sampling

The uv with a grid is used as the sampling coordinates, which perfectly fits the coordinate information of the picture.

   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;
    }

Guess you like

Origin blog.csdn.net/dxs1990/article/details/126382760