夜風のMixedReality

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

3DモデルのUVについてさらに理解する

本日は3Dモデリング枠です。

現在MixedRealityModeringToolsを開発していますが、UVについて難航していますので今回は3DモデルにおけるUVについてもっと理解していきます。

〇UVとは?

UVはテクスチャ座標とも呼ばれ、一般的にメッシュに対してテクスチャのどの部分をサンプルするかを決めるデータです。

座標のXYZなどと同様にU軸、V軸から構成されます。

〇UVがどのようにメッシュの中で定義されているか?

UVは頂点情報に紐づいています。 これはシェーダーを見ればよくわかりますが一般的にグラフィックスパイプライン上でUVは頂点シェーダーステージで処理されます。

頂点情報としてUVは格納されています。(以下の例はUnityでの頂点シェーダー)

v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);//頂点を配置
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);//UV座標
                return o;
            }

また、UVは頂点一つに対して1つ紐づいています。(もしくはNull)

しかしながら頂点に対して1つのUVでは困ってしまう場面があります。

例えば次のような平面のメッシュを考えます。

こちらのメッシュでは頂点数は4であり、すべての頂点がUVを持っていても特に問題は発生しません。

しかし次のような例では問題があります。

上記メッシュでは赤丸部は一つの頂点ながら2つのUVを持つようになっています。

上述の通り、頂点1つに対して1つのUVが紐づくというのが前提です。 このため、通常はUVの数頂点が複製されることになります。

Unityなどで頂点数がもともと想定していたものよりも増えていることがあるのはこのためです。(下記図では頂点数8のキューブをUnityに導入した場合の情報です。)

〇頂点数とUVの関係

では、どのようにUV数に応じて頂点数が増減するかという点ですが、UVは実のところポリゴン(面)に紐づいています。

ポリゴンの基本単位は3つの頂点から構成される3角ポリゴンであり、先ほどの例では下図のように計4つの面で構成されており、各面につき3つの頂点で構成される為必要な頂点数は3×すべてのポリゴン数ということになります。

個々の例では6頂点(2面)で構成されていたオブジェクトが、3角ポリゴンの場合4面、4×3=12の12の頂点からUVを適応したオブジェクトが構成されることになります。

UVは頂点に対応しているためこれを基に面に頂点を対応させるためには次のように処理を行う必要があります。

これをUntiyのC#で再現すると次のようになります。

  //Triangles :メッシュのインデックス
  //UV : 頂点ごとのUV
  for (int i = 0; i < Triangles.Length; i += 3)
        {
            Vector3 v0 = cubeVertices[cubeTriangles[i]]; //頂点の決定
            Vector3 v1 = cubeVertices[cubeTriangles[i + 1]];
            Vector3 v2 = cubeVertices[cubeTriangles[i + 2]];
            //3つの頂点から面を構成する=ポリゴン

            Vector3 normal = Vector3.Cross(v1 - v0, v2 - v0).normalized;
            //頂点ごとのUVの適応
            Vector2 uv0 = new Vector2(UV[i],UV[i+1]);
            Vector2 uv1 = new Vector2(UV[i+2],UV[i+3]);
            Vector2 uv2 = new Vector2(UV[i+4],UV[i+5]);

            uvs.Add(uv0);
            uvs.Add(uv1);
            uvs.Add(uv2);

            vertices.Add(v0);
            vertices.Add(v1);
            vertices.Add(v2);

            triangles.Add(i);
            triangles.Add(i + 1);
            triangles.Add(i + 2);
        }

        mesh.vertices = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.uv = uvs.ToArray();

上記では面を作成して面のUVとして登録しています。

同時に頂点数がメッシュのインデックスに応じて増えていることがわかります。

〇まとめ

UVは頂点に紐づいているが、その事態はポリゴン数に依存しており、頂点数=UV数という条件を満たすために頂点の方がUVに応じて増えています。

本日は以上です。