17.プリミティブメッシュの作成

BaseCrossには「平面」「立方体」「球」などのプリミティブな形状を作り出す関数が一通りそろっています。それらの関数は「シンプルバージョン」からもアクセスできます。
この項では、その方法と仕組みについて説明します。
この機能は「共有領域」である「DxLib」に実装されています。ですので、Dx12、Dx11いずれのソリューションで開いても同じです。

この記事は、
コミット「Dx11版ウインドウ作成と共有ファイルの追加」
から、
コミット「Dx11、Dx12両頂点定義とプリミティブメッシュ作成の追加」
の間の作業です。
GitHubサイト

https://github.com/WiZFramework/BaseCross

を参照して下さい。

この後ろのコミットでは「DxLib」に「MeshHelper.h/cpp」という新しいヘッダ、cppファイルが作成されています。自分で実装する場合は、「DxLib」共有アイテムプロジェクトに作成してください。

これらのファイルには「MeshUtillクラス」の宣言、定義が記述されています。private関数もありますが、publicな関数には、直接形状を作成する「Createなんとか」という関数がそろってます・
例えば、立方体を作り出す「CreateCube関数」は以下のような引数になります。

    //--------------------------------------------------------------------------------------
    /*!
    @brief  VertexPositionNormalTextureフォーマットの立方体を作成する(static関数)
    @param[in]  size 1つの辺のサイズ
    @param[out] vertices    頂点を作成するための配列
    @param[out] indices インデックスを作成するための配列
    @return なし
    */
    //--------------------------------------------------------------------------------------
    static void CreateCube(float size,
        vector<VertexPositionNormalTexture>& vertices, vector<uint16_t>& indices);

コメントにありますように[out]として指定されている引数が二つ「vertices」と「indices」があります。これはどういう意味かというとこの関数に「VertexPositionNormalTexture型の配列(空のvector)」と「uint16_t型の配列(空のvector)」を渡し、sizeを指定すると、指定されたサイズの頂点データ(立方体)とインデックスデータを作成する関数です。
頂点データについては前項で説明しました。ではインデックスとは何でしょう?
例えば三角形を表現する頂点データが3つの頂点が100個並んでいたとします。これを描画するときに、この頂点データをDirectXに渡し、300個の頂点を三角形描画で行いなさい、と命令すると描画されます。
しかしこの方法のほかに、この頂点データとは別に、頂点に番号(つまり何番目の頂点か)を定義する「インデックス」というのを作成し、「そのインデックス番号が指し示す頂点を使って300個三角形描画を行いなさい」というのがインデックス描画です(わかりやすく解説するつもりが、余計わかりにくくなった・・・)。
まあ、ちょっと説明方法を変えましょう。以下の図を見てください。これは、平面です。

001

ここには4つの頂点があります。これを、三角形描画するには、「A,B,D」「B,C,D」で描画します(2つの三角形)。必ず時計回りに見えるほうが表面になります。頂点だけで描画する場合、頂点データには、「A,B,D,B,C,D」と6つの頂点を並べて作っておく必要があります、これはわかりますね。そうすると、「BとD」を2回ずつデータ化する必要があります。
しかし頂点データ化するのは4つ「A,B,C,D」で、描画はその並び順を指定して、「0,1,3」で1つ「1,2,3」で1つと指定できたら、そのほうが頂点データ量は少なくなると思いませんか?それがインデックスです。この「A,B,C,D」の頂点と「0,1,3,1,2,3」というインデックスがあれば平面を作ることができます。

立方体の場合、全体で頂点の数は8個です。描画すべき三角形は1つの面に対して2つなので、インデックスの数は1つの面で6個です。全部で6つの面がありますので、インデックスは36個です。そうすれば、頂点8個でインデックス36個にすれば「これは効率がいい!」と考えるかもしれませんが、じつは、そこまでは話はうまくいきません。
頂点データの中に「法線」が含まれてないか、あるいは「フラット」と呼ばれる描画方法ならこれでいいのですが(球は通常この方法です)、立方体の法線は面に対して垂直になるので、各頂点も「どの面に属する頂点か」によって別に作らなければいけません。
ですから「立方体」の場合、通常、頂点数は「24個」、インデックス数は「36個」になります。

立方体を作成する関数を実行するためには以下のように行います。

    vector<VertexPositionNormalTexture> vertices;
    vector<uint16_t> indices;
    MeshUtill::CreateCube(1.0f,vertices,indices);

こんな感じで「MeshUtillクラス」の「Createなんとか」を呼び出せば「vertices」には頂点データ、「indices」にはインデックスデータが入ります。
「MeshUtillクラス」にはこのようにして作れる形状が「面(CreateSquare)」「立方体(CreateCube)」「球(CreateSphere)」「カプセル(CreateCapsule)」「シリンダー(CreateCylinder)」「コーン(CreateCone)」「ドーナッツ(CreateTorus)」「正四面体(CreateTetrahedron)」「正八面体(CreateOctahedron)」「正12面体(CreateDodecahedron)」「正20面体(CreateIcosahedron)」を作成できます。これらの形状作成には、全部ではないですが、DirectXのサンプルを参考にしています。
このほかにも、「自分の形状」を「MeshUtillクラス」に追加したり、あるいは、別に「vertices」には頂点データ、「indices」にはインデックスデータを渡せば、自分の形状を作成できるような関数を作れば、今後、これらの形状を、実際にDirectXで使用できるよう「頂点バッファ」を作成するわけですが(コミットはもう少しあとです)、その作成に互換が取れるようになります。

ここでちょっと待ってください。「MeshUtillクラス」で作成できる形状は「VertexPositionNormalTexture」ですので、ほかのFVFに対応するにはどうしたらいいんでしょうか?
これは、作成した頂点データの中身を修正すればできます。たとえば以下の感じです。

    //VertexPositionNormalTextureの配列
    vector<VertexPositionNormalTexture> BaseVertices;
    //VertexPositionColorの配列
    vector<VertexPositionColor> vertices;
    vector<uint16_t> indices;
    MeshUtill::CreateCube(1.0f,BaseVertices,indices);
    for(auto& v : BaseVertices){
        VertexPositionColor v2;
        v2.position = v.position;
        v2.color = Color4(1.0f,0,0,1.0f);
        vertices.push_back(v2);
    }

このように記述すれば、VertexPositionColor型の配列であるverticesを作成できます。position、normalなど必要なデータだけ残し他はその時その時で設定すれば問題ありません。多くの場合、形状作成で厄介なのは「position」「normal」「texture」のいずれかだと思いますので、その部分だけでもデータ化できればあとは何とかなると思います。

「MeshHelper.h/cpp」は、個別プロジェクトの「Dx12」「Dx11」内にある、「Common.h」に以下のように追記することで、プログラムで実装できます。

#pragma once

//中略

//プリミティブ作成関数等
#include "../DxLib/MeshHelper.h"

ここまでで、コミット「Dx11、Dx12両頂点定義とプリミティブメッシュ作成の追加」までの作業は終了です。
次項は、アプリケーションクラス、の解説です。

カテゴリー

ピックアップ記事

  1. 2016092201
    今回は前回のサンプルを少し機能を追加しまして、いろんなオブジェクトを追加しています。FullTuto…
  2. 2016092001
    前回更新から時間がたってしまいましたが、今回はフルバージョンチュートリアル003をアップしました。内…
  3. eyecatch
    前回更新から時間がたってしまいましたが、今回はフルバージョンチュートリアル002で懸案となっていまし…
PAGE TOP