🐕

3Dモデルの仕組み

2024/04/12に公開

サーフェスモデルとは

サーフェスモデル(Surface Model)についての説明から始めます。
3DCGの基本的な概念として、「モデリング」があります。モデリングとは、3次元空間において物体を作り出すプロセスのことを指します。サーフェスモデルは、そのモデリング技術の一つで、物体の表面を表現する方法です。

サーフェスモデルの特徴

  • 表面のみをモデリングする: サーフェスモデルは、物体の「皮」の部分だけを作り出します。内部構造は表現されません。これにより、視覚的にはリアルな物体を比較的少ない計算量で表現することができます。
  • ポリゴン(多角形)による構成: 多くの場合、サーフェスモデルはポリゴンという三角形や四角形などの平面で構成されます。これらのポリゴンを組み合わせて、複雑な形状の表面を作り出します。
  • テクスチャやマテリアルによる表現: 物体の表面の質感や色は、テクスチャ(画像)やマテリアル(素材の特性を表す設定)によって詳細に設定することができます。これにより、リアルな見た目の3Dオブジェクトを作成することが可能です。

Unityにおけるサーフェスモデルの扱い

Unityでは、3Dモデルをインポートして使うことが一般的です。これらのモデルは外部の3Dモデリングソフトウェア(例:Blender、Mayaなど)で作成されたもので、多くの場合、サーフェスモデルの形式になっています。Unity内でこれらのモデルを操作し、ゲームやアプリケーション内でのビジュアルとして使用します。

Unityで3DCGの基礎を学ぶ際は、まずサーフェスモデルの構成要素(ポリゴン、テクスチャ、マテリアル)を理解し、それらがどのように組み合わさって最終的なビジュアルを形成するのかを学ぶことが重要です。また、Unityのインターフェースや基本操作に慣れることも、3DCG制作の基礎を固める上で役立ちます。

サーフェスモデルをC#コードで作る

UnityでC#スクリプトを使用してサーフェスモデルを作成することが可能です。
プログラム的にメッシュ(ポリゴンの集合体)を生成し、そのメッシュを使用して3Dオブジェクトのサーフェスモデルを形成する方法です。このプロセスは少し複雑に思えるかもしれませんが、基本的なステップを理解すれば、独自の形状や動的に変化するオブジェクトを作成することができます。

ステップバイステップでのサーフェスモデル作成

  1. メッシュコンポーネントの準備:
    Unityで3Dオブジェクトを作成し、それにMeshFilterMeshRendererコンポーネントを追加します。MeshFilterはメッシュデータを保持し、MeshRendererはそのメッシュの描画を担当します。

  2. 頂点(Vertices)とポリゴン(Triangles)の定義:
    オブジェクトの形状を定義するために、頂点(3D空間内の点)のリストと、それらの点をつないでポリゴンを形成する三角形のリストを定義します。

  3. メッシュの作成:
    C#スクリプト内でMeshクラスのインスタンスを作成し、ステップ2で定義した頂点とポリゴン(三角形)のデータをメッシュに割り当てます。

  4. メッシュの適用:
    作成したメッシュをMeshFilterコンポーネントに適用します。これにより、定義した形状がゲーム内で表示されます。

サンプルコード

以下は、単純な平面を生成する基本的な例です。

using UnityEngine;

public class SimpleMeshGenerator : MonoBehaviour
{
    void Start()
    {
        // メッシュコンポーネントを取得
        MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
        MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
        
        // メッシュとマテリアルの作成
        Mesh mesh = new Mesh();
        meshFilter.mesh = mesh;
        
        // 頂点の定義
        Vector3[] vertices = {
            new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(0, 1, 0),
            new Vector3(1, 1, 0)
        };
        
        // 頂点インデックスによる三角形の定義
        int[] triangles = {
            0, 2, 1, // 最初の三角形
            2, 3, 1  // 二番目の三角形
        };
        
        // メッシュに頂点と三角形のデータを割り当て
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        
        // 法線の再計算(オプション)
        mesh.RecalculateNormals();
    }
}

このスクリプトを空のGameObjectにアタッチし、ゲームを実行すると、平面が生成されるのを見ることができます。これは最も基本的な例ですが、頂点と三角形のデータを変更することで、様々な形状を作成することができます。

Unityでサーフェスモデルをスクリプトから作成する際は、頂点の配置や三角形の構成に注意する必要があります。複雑な形状を作成する場合は、これらの基本を応用し、より高度なアルゴリズムを用いることになります。

コード解説

3Dモデルを形成する基本要素である頂点(Vertices)とポリゴン(Triangles)について、より詳しく説明します。

頂点(Vertices)

頂点は、3D空間内のある点を表します。3Dモデリングにおいて、これらの点はオブジェクトの形状を定義するために使用されます。頂点には、その位置情報(X、Y、Z座標)の他にも、色、テクスチャ座標(UV座標)、法線ベクトル(表面の向きを表すベクトル)などの情報が含まれることがあります。

ポリゴン(Triangles)

ポリゴンは、頂点を結んで形成される平面図形です。3Dモデリングでは、特に三角形(Triangles)が広く使用されます。これは、三角形が最も単純な多角形であり、どんなに複雑な表面も三角形の集合で表現できるためです。また、三角形は平面であるため、計算が単純で効率的です。

頂点とポリゴンの関係

3Dモデルを作る際、まず複数の頂点を定義します。その後、これらの頂点をつないでポリゴン(主に三角形)を形成します。例えば、4つの頂点がある場合、これらをつないで2つの三角形を作ることができます。

定義方法

頂点は、通常、Vector3配列で定義されます。これは、各頂点の3D空間内の位置(X、Y、Z座標)を保持します。

Vector3[] vertices = {
    new Vector3(0, 0, 0), // 頂点1
    new Vector3(1, 0, 0), // 頂点2
    new Vector3(0, 1, 0), // 頂点3
    new Vector3(1, 1, 0)  // 頂点4
};

ポリゴン(三角形)は、これらの頂点のインデックスを使用して定義されます。int配列で、頂点配列内のインデックスを指定して三角形を形成します。Unityでは、この配列の順番が重要で、時計回りに頂点を指定すると表面が表側になります(カリングの設定によりますが、デフォルトでは時計回りが表です)。

int[] triangles = {
    0, 2, 1, // 最初の三角形(頂点0、2、1をつなぐ)
    2, 3, 1  // 二番目の三角形(頂点2、3、1をつなぐ)
};

このようにして、頂点とポリゴンを定義し、3Dオブジェクトのメッシュを作成します。実際のモデリングでは、これらの基本的な要素を使って、さまざまな形状やサイズの3Dオブジェクトを作成することができます。頂点とポリゴンの数が多ければ多いほど、モデルはより詳細になりますが、その分、計算コストも高くなります。

ピンク色の板ポリゴン

Unityでオブジェクトがピンク色に表示される場合、そのオブジェクトにマテリアルが割り当てられていない、またはマテリアルが見つからないときによく見られる現象です。
ピンク色は、Unityが「マテリアルが欠けている」または「シェーダーが見つからない」ことを示すデフォルトの色です。

マテリアルは、3Dオブジェクトの表面の「見た目」を定義します。色、テクスチャ、光の反射の仕方など、視覚的な特性をコントロールするために使用されます。マテリアルがない場合、Unityはオブジェクトを正しくレンダリングできないため、代わりにピンク色で表示します。

マテリアルの設定方法

マテリアルをオブジェクトに割り当てるには、次のステップに従います。

  1. マテリアルの作成:
    Projectビューで右クリックし、「Create > Material」と進んで新しいマテリアルを作成します。作成されたマテリアルに名前を付けます。

  2. マテリアルのカスタマイズ:
    作成したマテリアルを選択し、Inspectorビューでマテリアルのプロパティを編集します。色やテクスチャなど、必要に応じて変更します。

  3. マテリアルの適用:
    マテリアルを3Dオブジェクトに割り当てます。これを行うには、マテリアルをオブジェクトにドラッグ&ドロップするか、オブジェクトを選択してInspectorビューでMeshRendererコンポーネントのマテリアルスロットにマテリアルを割り当てます。

スクリプトからマテリアルを割り当てる

スクリプトから直接マテリアルを割り当てることも可能です。以下はその例です。

using UnityEngine;

public class ApplyMaterial : MonoBehaviour
{
    public Material materialToApply; // Inspectorから割り当てるマテリアル

    void Start()
    {
        GetComponent<MeshRenderer>().material = materialToApply;
    }
}

このスクリプトでは、public Material materialToApply;行でマテリアルを公開変数として宣言し、UnityのEditorで直接そのマテリアルをスクリプトに割り当てることができます。Startメソッド内で、MeshRendererコンポーネントのmaterialプロパティを使用して、そのマテリアルをオブジェクトのマテリアルとして設定します。

これで、スクリプトからオブジェクトにマテリアルを割り当てる方法が完成し、ピンク色の問題を解決できるはずです。

スクリプトからマテリアルを受け渡す

Unityのデフォルトのマテリアルをスクリプト経由で新規に作成したオブジェクトに自動で割り当てる方法には、直接的な方法はありませんが、ある程度対応する方法があります。

Unityには、あらかじめ定義されたマテリアルやシェーダーがいくつか用意されており、その中から選択して使用することができます。しかし、これらのデフォルトのマテリアルを直接新規オブジェクトに割り当てる専用のAPIや機能は提供されていません。

デフォルトのマテリアルを使用したい場合の一般的なアプローチは、以下の2つです。

1. プリセットマテリアルの使用

予めエディタでデフォルトマテリアルを設定したマテリアルアセットを作成し、それをスクリプトで新規オブジェクトに割り当てる方法です。

  1. Unityエディタでマテリアルを作成し、好みの設定(例えば、標準のシェーダーを使用)にします。
  2. このマテリアルをプロジェクト内に保存します。
  3. スクリプトでこのマテリアルを読み込み、新規オブジェクトに割り当てます。

2. Shader.Findを使った動的なマテリアルの生成

Unityでデフォルトのシェーダーを使って動的にマテリアルを生成し、それをオブジェクトに割り当てることもできます。この方法では、Shader.Findメソッドを使用して、特定のシェーダーをプログラムで検索し、新しいマテリアルを作成時にそのシェーダーを使用します。

using UnityEngine;

public class DefaultMaterialExample : MonoBehaviour
{
    void Start()
    {
        // "Standard"シェーダーを使用して新しいマテリアルを生成
        Material newMaterial = new Material(Shader.Find("Standard"));

        // 新しいマテリアルをこのオブジェクトのマテリアルとして設定
        GetComponent<MeshRenderer>().material = newMaterial;
    }
}

Shader.Findメソッドを使用する際は、正確なシェーダー名を指定する必要があります。"Standard"はUnityが標準で提供するシェーダーの一つで、多くの用途に適しています。ただし、この方法はシェーダーがプロジェクト内に存在し、その名前が正確であることが前提です。シェーダー名が間違っている場合、nullを返し、マテリアルが正しく作成されません。

これらの方法を使って、Unityのデフォルトマテリアルに似たマテリアルを新規オブジェクトに動的に割り当てることができます。

Discussion