🥪

Unityで始めるコンピュータ・グラフィックス (1) 三角形

2022/07/03に公開

三角形を作る

Meshとは何か?

material made of a network of wire or thread. Oxford Dictionary

ワイヤーとか紐をつなぎ繋ぎ合わせて作った素材ということのようです. Unityではデータ構造の名前と思えば良いと思います.

このデータ構造を絵で描くとメッシュのように見えるから・・・ということだと思います..

頂点と辺, そして面

主な構成要素は以下のようになります.

要素 説明
Vertext (頂点) 位置を表す要素
Edge (辺) 頂点を繋いでできる辺
Face (面) 実際に表示される面

一番基本となる面は三角形です. 3つの頂点, 3つの辺からなる面のことです.

三角形を作る

Triangleオブジェクト

空のオブジェクトをTriangleとでも名前を付けて作成します.

MeshFilter & MeshRenderer

TriangleオブジェクトにMeshFilterとMeshRenderというコンポーネントを追加しておきましょう.

MeshFilterは実際のメッシュの描画を担当するMeshRendererにメッシュ・データを渡す役割です.

Meshクラス

まずメッシュをデータで表現してみましょう. Meshクラスを使います. meshインスタンスをMeshFilterに渡すだけです.

private void OnEnable()
{
    Mesh mesh = new Mesh { name = "ComiX Mesh"};
    MeshFilter meshFilter = GetComponent<MeshFilter>();
    meshFilter.mesh = mesh;
    Mesh duplicated = meshFilter.mesh;
}

頂点データの定義

以下のように頂点の座標と三角形を定義します.

readonly Vector3[] vertices = new Vector3[]
    {
        new Vector3(0f, 0f, 0f),
        new Vector3(0f, 1f, 0f),
        new Vector3(1f, 0f, 0f),
    };

readonly int[] triangles = new int[]{ 0, 2, 1};

意味としては以下のようなことになります.

readonly Dictionary<int, Vector3> triangle = new Dictionary<int, Vector3>()
{
    { 0, new Vector3(0f, 0f, 0f) },
    { 1, new Vector3(1f, 0f, 0f) },
    { 2, new Vector3(0f, 1f, 0f) },
};

各頂点は座標とは別にインデックスも持っているわけです.

なぜこのような情報が必要なのでしょうか?

Winding order

これは三角形を構成する頂点の順番によって面の法線の向きが違ってくるからです. これをWinding orderと呼びます.

よって下の場合左の絵は表面として描画されますが, 右は裏面と判断されカリングの対象となり描画されません.

結果

コード

Triangle.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ComiX {
    [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
    public class Triangle : MonoBehaviour
    {

        readonly Vector3[] vertex_positions = new Vector3[]
            {
                new Vector3(0f, 0f, 0f),
                new Vector3(0f, 1f, 0f),
                new Vector3(1f, 0f, 0f),
            };

        readonly int[] triangles = new int[]{ 0, 1, 2};
        private void OnEnable()
        {
            Mesh mesh = new Mesh { name = "ComiX Mesh"};
            MeshFilter meshFilter = GetComponent<MeshFilter>();
            meshFilter.mesh = mesh;
            mesh.vertices = vertex_positions;
            mesh.triangles = triangles;
        }
    }
}

References

Discussion