Unity は DEM テレイン メソッドを生成します (純粋なコード)

Unity は DEM テレイン メソッドを生成します (純粋なコード)

(以下のコードは比較的完成度が高く、必要に応じてプロジェクト ファイルをダウンロードできます)プロジェクト ファイルのアドレス

基本的な考え方

最初に n × \timesを作成しますn 個の頂点を持つ平面グリッド、各ネットワーク ポイントの相対座標を使用して DEM (デジタル標高モデル) をサンプリングし、0 ~ 1 のグレー値を取得し、グレー値に高さ係数を掛けて相対標高を取得し、最後に高さ

DEMの理解

DEM は地形の高さをグレースケールで表したもので、白い場所ほど 1 に近いほど高く、暗い場所ほど 0 に近いほど低いことを意味します。

n × \回× 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