夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Unityでワイヤフレーム表示に対応する新しいメッシュを作る その②UV更新

本日はUnity枠です。

先日に引き続きUnityでMetalなどのプラットフォームについてジオメトリシェーダーを使用せずにワイヤフレーム表示に対応するための新しいメッシュを作る機能を紹介します。

前回はUntiyEditor拡張でターゲットオブジェクトを指定できるフィールドを定義しました。

今回は実際にメッシュを編集します。

redhologerbera.hatenablog.com

〇ワイヤフレームのアプローチ

 今回はUVと画像(テクスチャ)を用いてワイヤフレーム表示を実装していきます。

 具体的にはオブジェクトを構成するすべてのメッシュについて同じUVを持つ新しいメッシュを作成し、対応する画像を使用するというものです。

〇UVの計算

Object objとしてUVを計算するコードは以下のようになります。

       public void CreateNewWireframeMeshObject()
        {

            if (obj != null)
            {
                GameObject newObject = new GameObject();
                 //新しく定義したワイヤフレームオブジェクトの名称を定義
                newObject.name = obj.name + "_Wireframe";
               //メッシュを取得
                Mesh mesh = obj.GetComponent<MeshFilter>().sharedMesh;

                //meshのUVをポリゴンごとに再計算 Indexごとに3つの頂点を取得
                int[] oldTriangles = mesh.triangles;
                Vector3[] oldVertices = mesh.vertices;
                Vector2[] uvs = new Vector2[oldTriangles.Length]; // 頂点数と同じ数のUV座標を用意
                Vector3[] vertices = new Vector3[oldTriangles.Length]; // 頂点数と同じ数の頂点を用意
                int[] triangles = new int[oldTriangles.Length]; // 新しいインデックス配列を用意

                for (int i = 0; i < oldTriangles.Length; i += 3)
                {
                    // 各三角形ごとに独立した頂点を作成
                    vertices[i + 0] = oldVertices[oldTriangles[i + 0]];
                    vertices[i + 1] = oldVertices[oldTriangles[i + 1]];
                    vertices[i + 2] = oldVertices[oldTriangles[i + 2]];

                    // UVを計算
                    Vector2 uv0 = new Vector2(0, 0);
                    Vector2 uv1 = new Vector2(0f, 1);
                    Vector2 uv2 = new Vector2(1, 0);

                    // UVを格納
                    uvs[i + 0] = uv0;
                    uvs[i + 1] = uv1;
                    uvs[i + 2] = uv2;

                    // 新しいインデックスを設定
                    triangles[i + 0] = i + 0;
                    triangles[i + 1] = i + 1;
                    triangles[i + 2] = i + 2;
                }

                //新しいMeshを作成
                Mesh newMesh = new Mesh();
                newMesh.vertices = vertices;
                newMesh.triangles = triangles;
                newMesh.uv = uvs;
                newMesh.RecalculateNormals();
                newMesh.RecalculateBounds();
                newMesh.name = mesh.name + "_Wireframe";

                //新しいオブジェクトにMeshFilterをアタッチ
                MeshFilter meshFilter = newObject.AddComponent<MeshFilter>();
                meshFilter.sharedMesh = newMesh;
                //新しいオブジェクトにMeshRendererをアタッチ
                MeshRenderer meshRenderer = newObject.AddComponent<MeshRenderer>();
                //matがnullの場合
                if (mat == null)
                {
                    //GraphicsTools/Standardシェーダーの新しいマテリアルを作成して適応
                    Shader shader = Shader.Find("GraphicsTools/Standard");
                    mat = new Material(shader);
                    mat.color = Color.white;
                    meshRenderer.material = mat;
                }
                else
                meshRenderer.material = mat;
            }
            
        }

重要な部分はfor文内になります。

  for (int i = 0; i < oldTriangles.Length; i += 3)
                {
                    // 各三角形ごとに独立した頂点を作成
                    vertices[i + 0] = oldVertices[oldTriangles[i + 0]];
                    vertices[i + 1] = oldVertices[oldTriangles[i + 1]];
                    vertices[i + 2] = oldVertices[oldTriangles[i + 2]];

                    // UVを計算
                    Vector2 uv0 = new Vector2(0, 0);
                    Vector2 uv1 = new Vector2(0f, 1);
                    Vector2 uv2 = new Vector2(1, 0);

                    // UVを格納
                    uvs[i + 0] = uv0;
                    uvs[i + 1] = uv1;
                    uvs[i + 2] = uv2;

                    // 新しいインデックスを設定
                    triangles[i + 0] = i + 0;
                    triangles[i + 1] = i + 1;
                    triangles[i + 2] = i + 2;
                }

ここではUVを計算する際にすべてのポリゴンを構成する3つの頂点グループに対して(0, 0);(0, 1)(1, 0)のUVを与えています。

これによってすべてのポリゴンで同じUVを持つようになります。

こうして新しいメッシュオブジェクトが作成できました。

本日は以上です。