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