【Unity】フラクタル地形を生成する
こんにちは電車君です。
今回はUnityでフラクタル地形を生成する方法を紹介します。
ここで紹介するフラクタル地形とは、
「中点変位法」を用いた方法を使います。
まず、四角形を作成します。
Mesh mesh = new Mesh ();
mesh.vertices = new Vector3{ Vector3.zero, Vector3.forward, Vector3.right + Vector3.forward, Vector3.right };
mesh.uv = new Vector2{ Vector2.zero, Vector2.up, Vector2.right + Vector2.up, Vector2.right };
mesh.triangles = new int{ 0, 1, 2, 2, 3, 0 };
mesh.RecalculateBounds ();
mesh.RecalculateNormals ();
この四角形は二つの三角形で出来ています。
頂点は4つあり、最初の頂点は四角形の左下の頂点です。
四角形の左下の座標は0,0(X,Y)です。
次に、左上、右上と、右下の頂点があります。
Vector3 verts = mesh.vertices;
for (int a = 0; a < verts.Length; a++) {
verts [a].y = Random.Range (0f, height);
}
mesh.vertices = verts;
for (int a = 0; a < fineness; a++) {
int b = mesh.vertices.Length;
mesh = FractalTerrain.Subdivide_Half (mesh);
verts = mesh.vertices;
while (b < verts.Length) {
float c = height / 2 / (a + 1);
setVert (verts, verts [b], verts [b] + Vector3.up * Random.Range (-c, c));
b++;
}
mesh.vertices = verts;
}
FractalTerrain.Subdivide_Half (mesh); は、
メッシュの細分化をします。
public static Mesh Subdivide_Half (Mesh mesh)
{
Mesh m = mesh_copy (mesh);
List<Vector3> newverts = new List<Vector3> (m.vertices);
List<Vector2> newuv = new List<Vector2> (m.uv);
List<int> newtris = new List<int> ();
for (int c = 0; c <= m.triangles.Length - 3; c += 3) {
int vn0 = m.triangles [c];
int vn1 = m.triangles [c + 1];
int vn2 = m.triangles [c + 2];
Vector2 vu0 = m.uv [vn0];
Vector2 vu1 = m.uv [vn1];
Vector2 vu2 = m.uv [vn2];
newverts.Add ( (m.vertices [vn0] + m.vertices [vn1]) / 2);
newverts.Add ( (m.vertices [vn1] + m.vertices [vn2]) / 2);
newverts.Add ( (m.vertices [vn2] + m.vertices [vn0]) / 2);
newuv.Add ( (vu0 + vu1) / 2);
newuv.Add ( (vu1 + vu2) / 2);
newuv.Add ( (vu2 + vu0) / 2);
int _vn = newverts.Count - 3;
newtris.Add (vn0);
newtris.Add (_vn);
newtris.Add (_vn + 2);
newtris.Add (vn1);
newtris.Add (_vn + 1);
newtris.Add (_vn);
newtris.Add (vn2);
newtris.Add (_vn + 2);
newtris.Add (_vn + 1);
newtris.Add (_vn);
newtris.Add (_vn + 1);
newtris.Add (_vn + 2);
}
m.vertices = newverts.ToArray ();
m.uv = newuv.ToArray ();
m.triangles = newtris.ToArray ();
mesh.RecalculateBounds ();
mesh.RecalculateNormals ();
return m;
}
メッシュの細分化はそれぞれの三角形を細分化します。
三角形を細分化するには、辺の中点を作り、
3つの中点を結んだ辺を作るイメージで、
4つの三角形を作成します。
細分化したら新しい頂点を移動させます。
この時、新しい頂点は同じ場所に複数の頂点がある場所があります。
四角形を細分化するため、四角形の真ん中にある点が重複しています。
この重複している頂点を結合せず一度に移動させます。*1
public static void setVert(Vector3[] verts, Vector3 target, Vector3 result) {
for (int a = 0; a < verts.Length; a++) {
if (verts [a] == target) {
verts [a] = result;
}
}
}
以下ソース
*1:頂点を結合しようと思ったのですが、うまく行きませんでした