LoginSignup
2
0

More than 5 years have passed since last update.

Unityでプロシージャルモデリング (平面)

Last updated at Posted at 2018-07-14

Unityでメッシュをスクリプトでプロシージャルに生成する方法について何回かに分けて解説します。

今回は平面のメッシュを生成してみます。

plane.PNG

Plane.cs
using UnityEngine;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Plane : MonoBehaviour
{
    [SerializeField] private Vector2 size = new Vector2(4, 3);
    [SerializeField] private Vector2Int segment = new Vector2Int(4, 3);

    private void Awake()
    {
        Mesh mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        Vector3[] vertices = new Vector3[(segment.x + 1) * (segment.y + 1)];
        int[] triangles = new int[segment.x * segment.y * 2 * 3];


        Vector2 halfSize = size * 0.5f;
        Vector2 sizeStep = size / segment;
        int vi = 0;
        for (int y = 0; y < segment.y + 1; y++)
        {
            for (int x = 0; x < segment.x + 1; x++)
            {
                vertices[vi++] = new Vector3(sizeStep.x * x - halfSize.x, sizeStep.y * y - halfSize.y, 0);
            }
        }
        int ti = 0;
        for (int y = 0; y < segment.y; y++)
        {
            for (int x = 0; x < segment.x; x++)
            {
                triangles[ti] = x + y * (segment.x + 1);
                triangles[ti + 1] = triangles[ti + 5] = x + (y + 1) * (segment.x + 1);
                triangles[ti + 2] = triangles[ti + 4] = (x + 1) + y * (segment.x + 1);
                triangles[ti + 3] = (x + 1) + (y + 1) * (segment.x + 1);
                ti += 6;
            }
        }

        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
    }
}

今回生成する平面は大きさと分割数をsizesegmentでインスペクターから任意に設定できるようにしています。

メッシュは以下のように構成されています(分割数はデフォルト値)。数字は頂点のインデックス、丸で囲まれた数字は三角形を定義する順番を表しています(途中で省略)。

plane_ex.png

図のように頂点は(segment.x + 1) * (segment.y + 1)だけ必要になります。またメッシュを縦横で分割した四角形は2つの三角形で作れるので、三角形の数はsegment.x * segment.y * 2になります。そのため、triangles配列の大きさはsegment.x * segment.y * 2 * 3になります。

ソースコードの以下の箇所で頂点を定義しています。XY平面上で作成するメッシュの中心が原点に一致するように頂点を配置しています。

Vector2 halfSize = size * 0.5f;
Vector2 sizeStep = size / segment;
int vi = 0;
for (int y = 0; y < segment.y + 1; y++)
{
    for (int x = 0; x < segment.x + 1; x++)
    {
         vertices[vi++] = new Vector3(sizeStep.x * x - halfSize.x, sizeStep.y * y - halfSize.y, 0);
    }
}

三角形の定義は以下の箇所で行っています。2重ループの中では2つの三角形で四角形を作成しています。2つの三角形から四角形を作成する方法については以前の記事を参照してください。

int ti = 0;
for (int y = 0; y < segment.y; y++)
{
      for (int x = 0; x < segment.x; x++)
      {
          triangles[ti] = x + y * (segment.x + 1);
          triangles[ti + 1] = triangles[ti + 5] = x + (y + 1) * (segment.x + 1);
          triangles[ti + 2] = triangles[ti + 4] = (x + 1) + y * (segment.x + 1);
          triangles[ti + 3] = (x + 1) + (y + 1) * (segment.x + 1);
          ti += 6;
      }
}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0