Unityでスクリプトから作るMeshは法線の記述で見え方が変わる

# はじめに

- 3DCGを作るための便利なツールの一つに、Unityがあります。
- このツールの中にモデルを入れてCGを創るわけですが、この入れ方には、予め作ったデータを読込む他に、スクリプトでMesh座標を書込む方法があります。
- この方法で作るとき、法線の書き方で表示結果が異なることを知りました。
- 知ってる方には当たり前かもですが、パッと検索しても出なかったので備忘も兼ねて投稿します。

### できたこと

　Meshの角を出す/出さないを切替えできました。

# 内容
### 1.前提

　unityの使い方やMeshをスクリプトで作る方法は、以下のURLを参照しました。ここでは省略します。
（参考）
　https://matcha-choco010.net/2018/08/25/unity-mesh-from-script/
　https://bluebirdofoz.hatenablog.com/entry/2020/08/03/210520

要は、Meshを表現する三角形の頂点リストと、頂点を繋ぐ組合せリスト、各頂点の法線リストの3つを書き出します。

今回は例として、立方体を作ります。

### 2.角を出さない書き方
立方体の頂点は8つ、三角形は12ですから、シンプルに考えれば以下のようになります。法線は各頂点を含む面の平均にしました。

~~~c#
        // 頂点リストを作成
        List<Vector3> vertices = new List<Vector3>
        {
            new Vector3(-1.0f, 1.0f,-1.0f),//0
            new Vector3(-1.0f,-1.0f,-1.0f),//1
            new Vector3( 1.0f,-1.0f,-1.0f),//2
            new Vector3( 1.0f, 1.0f,-1.0f),//3
            new Vector3(-1.0f, 1.0f, 1.0f),//4
            new Vector3(-1.0f,-1.0f, 1.0f),//5
            new Vector3( 1.0f,-1.0f, 1.0f),//6
            new Vector3( 1.0f, 1.0f, 1.0f),//7
        };
        // 頂点を繋ぐ組合せリストを作成
        List<int> triangles = new List<int> {
            2, 1, 0,  // 奥面
            3, 2, 0,  // 奥面
            5, 6, 7,  // 前面
            4, 5, 7,  // 前面
            7, 3, 0,  // 右面
            4, 7, 0,  // 右面
            5, 1, 2,  // 左面
            6, 5, 2,  // 左面
            2, 3, 7,  // 上面
            6, 2, 7,  // 上面
            0, 1, 5,  // 下面
            4, 0, 5,  // 下面
        };
        // 頂点の法線リストを作成
        List<Vector3> norms = new List<Vector3>
        {
            new Vector3(-0.5f, 0.5f,-0.5f),
            new Vector3(-0.5f,-0.5f,-0.5f),
            new Vector3( 0.5f,-0.5f,-0.5f),
            new Vector3( 0.5f, 0.5f,-0.5f),
            new Vector3(-0.5f, 0.5f, 0.5f),
            new Vector3(-0.5f,-0.5f, 0.5f),
            new Vector3( 0.5f,-0.5f, 0.5f),
            new Vector3( 0.5f, 0.5f, 0.5f),
        };
~~~

これで表示すると角がわかりづらくなります。

### 3.角を出す書き方
立方体ではなく、6面の集まりと捉えます。各面が4つの頂点を持つので、頂点は24、三角形は12、法線は各面の法線にします。

~~~c#
        // 頂点リストを作成
        List<Vector3> vertices2 = new List<Vector3>
        {
            new Vector3( 1.0f,-1.0f,-1.0f),//2
            new Vector3(-1.0f,-1.0f,-1.0f),//1
            new Vector3(-1.0f, 1.0f,-1.0f),//0
            new Vector3( 1.0f, 1.0f,-1.0f),//3

            new Vector3(-1.0f,-1.0f, 1.0f),//5
            new Vector3( 1.0f,-1.0f, 1.0f),//6
            new Vector3( 1.0f, 1.0f, 1.0f),//7
            new Vector3(-1.0f, 1.0f, 1.0f),//4

            new Vector3( 1.0f, 1.0f, 1.0f),//7
            new Vector3( 1.0f, 1.0f,-1.0f),//3
            new Vector3(-1.0f, 1.0f,-1.0f),//0
            new Vector3(-1.0f, 1.0f, 1.0f),//4

            new Vector3(-1.0f,-1.0f, 1.0f),//5
            new Vector3(-1.0f,-1.0f,-1.0f),//1
            new Vector3( 1.0f,-1.0f,-1.0f),//2
            new Vector3( 1.0f,-1.0f, 1.0f),//6

            new Vector3( 1.0f,-1.0f,-1.0f),//2
            new Vector3( 1.0f, 1.0f,-1.0f),//3
            new Vector3( 1.0f, 1.0f, 1.0f),//7
            new Vector3( 1.0f,-1.0f, 1.0f),//6

            new Vector3(-1.0f, 1.0f,-1.0f),//0
            new Vector3(-1.0f,-1.0f,-1.0f),//1
            new Vector3(-1.0f,-1.0f, 1.0f),//5
            new Vector3(-1.0f, 1.0f, 1.0f),//4
        };
        // 頂点を繋ぐ組合せリストを作成
        List<int> triangles2 = new List<int> {
            0, 1, 2,  // 奥面
            3, 0, 2,  // 奥面

            4, 5, 6,  // 前面
            7, 4, 6,  // 前面

            8, 9,10,  // 上面
           11, 8,10,  // 上面

           12,13,14,  // 下面
           15,12,14,  // 下面

           16,17,18,  // 右面
           19,16,18,  // 右面

           20,21,22,  // 左面
           23,20,22,  // 左面
        };
        // 頂点の法線リストを作成
        List<Vector3> norms2 = new List<Vector3>
        {
            new Vector3( 0.0f, 0.0f,-1.0f),
            new Vector3( 0.0f, 0.0f,-1.0f),
            new Vector3( 0.0f, 0.0f,-1.0f),
            new Vector3( 0.0f, 0.0f,-1.0f),

            new Vector3( 0.0f, 0.0f, 1.0f),
            new Vector3( 0.0f, 0.0f, 1.0f),
            new Vector3( 0.0f, 0.0f, 1.0f),
            new Vector3( 0.0f, 0.0f, 1.0f),

            new Vector3( 0.0f, 1.0f, 0.0f),
            new Vector3( 0.0f, 1.0f, 0.0f),
            new Vector3( 0.0f, 1.0f, 0.0f),
            new Vector3( 0.0f, 1.0f, 0.0f),

            new Vector3( 0.0f,-1.0f, 0.0f),
            new Vector3( 0.0f,-1.0f, 0.0f),
            new Vector3( 0.0f,-1.0f, 0.0f),
            new Vector3( 0.0f,-1.0f, 0.0f),

            new Vector3( 1.0f, 0.0f, 0.0f),
            new Vector3( 1.0f, 0.0f, 0.0f),
            new Vector3( 1.0f, 0.0f, 0.0f),
            new Vector3( 1.0f, 0.0f, 0.0f),

            new Vector3(-1.0f, 0.0f, 0.0f),
            new Vector3(-1.0f, 0.0f, 0.0f),
            new Vector3(-1.0f, 0.0f, 0.0f),
            new Vector3(-1.0f, 0.0f, 0.0f),
        };
~~~

こうすると角がキレイに表示されます。

### 4.結果
動画でみるとこんな感じです。左が角を出さない書き方、右が角を出す書き方で作ったものです。
![polygon_display_test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2449065/5a0dee1d-010d-8ad5-4c75-29742744fa74.gif)
※わかりやすいようMaterialをメタリックにして、ディレクショナルライトで照らしました。

# 参考

参考コード
https://bluebirdofoz.hatenablog.com/entry/2020/08/03/210520