MRが楽しい

MRやVRについて学習したことを書き残す

UnityでMeshクラスを使ってメッシュオブジェクトを作成する

本日は Unity の技術調査枠です。
UnityでMeshクラスを使ってメッシュオブジェクトを作成する手順を記事にします。
f:id:bluebirdofoz:20200803210313j:plain

Meshクラス

スクリプトからメッシュの作成や変更を行う UnityEngine のクラスです。
Mesh クラスには頂点データや面データが含まれていてサーフェス形式の3Dモデルを形成します。
docs.unity3d.com
bluebirdofoz.hatenablog.com

Meshのレンダリング

作成した Mesh をレンダリング(描画)するには MeshRenderer コンポーネントを利用します。
docs.unity3d.com

MeshRenderer は MeshFilter または TextMesh によって挿入された Mesh をレンダリングします。
今回は MeshFilter を使って、作成した Mesh を MeshRenderer に受け渡します。
docs.unity3d.com

Unity プロジェクトに空オブジェクトを作成し、MeshRenderer と MeshFilter コンポーネントを追加しました。
f:id:bluebirdofoz:20200803210340j:plain

スクリプトの作成

Cubeオブジェクトの形状を作成するスクリプトを作成します。
立方体は8つの頂点と12個の三角面で構成されます。
・CubeMesh.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeMesh : MonoBehaviour
{
    void Start()
    {
        // メッシュを作成
        Mesh mesh = new Mesh();

        // 頂点リストを作成
        List<Vector3> vertices = new List<Vector3>
        {
            new Vector3(1.0f, 1.0f, 1.0f),
            new Vector3(-1.0f, 1.0f, 1.0f),
            new Vector3(-1.0f, -1.0f, 1.0f),
            new Vector3(1.0f, -1.0f, 1.0f),
            new Vector3(1.0f, -1.0f, -1.0f),
            new Vector3(-1.0f, -1.0f, -1.0f),
            new Vector3(-1.0f, 1.0f, -1.0f),
            new Vector3(1.0f, 1.0f, -1.0f),
        };

        // 面を構成するインデックスリストを作成
        List<int> triangles = new List<int> {
            0, 1, 2,  // 奥面
            0, 2, 3,  // 奥面
            4, 5, 6,  // 前面
            4, 6, 7,  // 前面
            0, 4, 7,  // 右面
            0, 3, 4,  // 右面
            6, 2, 1,  // 左面
            6, 5, 2,  // 左面
            6, 1, 0,  // 上面
            7, 6, 0,  // 上面
            4, 3, 2,  // 下面
            5, 4, 2,  // 下面
        };

        // メッシュに頂点を登録する
        mesh.SetVertices(vertices);

        // メッシュに面を構成するインデックスリストを登録する
        mesh.SetTriangles(triangles, 0);

        // 作成したメッシュをメッシュフィルターに設定する
        MeshFilter meshFilter = GetComponent<MeshFilter>();
        meshFilter.mesh = mesh;
    }
}

作成したスクリプトをオブジェクトにアタッチします。
f:id:bluebirdofoz:20200803210329j:plain

[再生]ボタンをクリックすると、シーンの中央に以下の通り、Cube 型のメッシュがレンダリングされます。
f:id:bluebirdofoz:20200803210423j:plain

マテリアルの設定

マテリアルを設定したい場合は、予めマテリアルを作成し、MeshRenderer に設定しておく事でマテリアルが使用されます。
f:id:bluebirdofoz:20200803210433j:plain

複数マテリアルの設定

1つのメッシュに複数のマテリアルを設定する場合は submesh の機能を使います。
以下の通り、MeshRenderer に複数のマテリアルを登録します。
f:id:bluebirdofoz:20200803210446j:plain

その後、スクリプトを以下の通り変更し、上面と下面をインデックス 1 のサブメッシュに割り当てます。
・CubeMesh.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeMesh : MonoBehaviour
{
    void Start()
    {
        // メッシュを作成
        Mesh mesh = new Mesh();

        // 頂点リストを作成
        List<Vector3> vertices = new List<Vector3>
        {
            new Vector3(1.0f, 1.0f, 1.0f),
            new Vector3(-1.0f, 1.0f, 1.0f),
            new Vector3(-1.0f, -1.0f, 1.0f),
            new Vector3(1.0f, -1.0f, 1.0f),
            new Vector3(1.0f, -1.0f, -1.0f),
            new Vector3(-1.0f, -1.0f, -1.0f),
            new Vector3(-1.0f, 1.0f, -1.0f),
            new Vector3(1.0f, 1.0f, -1.0f),
        };

        // 面を構成するインデックスリストを作成
        List<int> triangles = new List<int> {
            0, 1, 2,  // 奥面
            0, 2, 3,  // 奥面
            4, 5, 6,  // 前面
            4, 6, 7,  // 前面
            0, 4, 7,  // 右面
            0, 3, 4,  // 右面
            6, 2, 1,  // 左面
            6, 5, 2,  // 左面
        };

        // 面を構成するインデックスリストを作成
        List<int> subtriangles = new List<int> {
            6, 1, 0,  // 上面
            7, 6, 0,  // 上面
            4, 3, 2,  // 下面
            5, 4, 2,  // 下面
        };

        // メッシュに頂点を登録する
        mesh.SetVertices(vertices);

        // サブメッシュの格納数を2つに設定する。
        mesh.subMeshCount = 2;
        
        // インデックス 0 のサブメッシュに面を構成するインデックスリストを登録する
        mesh.SetTriangles(triangles, 0);

        // インデックス 1 のサブメッシュに面を構成するインデックスリストを登録する
        mesh.SetTriangles(subtriangles, 1);

        // 作成したメッシュをメッシュフィルターに設定する
        MeshFilter meshFilter = GetComponent<MeshFilter>();
        meshFilter.mesh = mesh;
    }
}

[再生]ボタンをクリックすると、以下の通り、サブメッシュごとに異なるマテリアルが割り当てられます。
f:id:bluebirdofoz:20200803210457j:plain