Cone.x の頂点データを定義

Cone.x の頂点データを定義

DirectX10 で Cone.x の頂点データを定義して、X座標とY座標で回転しながら描画します。
DirectX10 では X-FILE を直接描画することが出来ないようです。 (^_^;)

前田稔(Maeda Minoru)の超初心者のプログラム入門

X-FILE(Cone.x) の説明

  1. MultiMon10 のプロジェクトを使って Cone.x の頂点データをテーブルで定義して描画して見ましょう。
    ネット上で「DirectX10 で X-FILE を描画するプログラムを作成したい」などの書き込みがありましたが、このプログラムが参考になると思います。
    X-FILE(Cone.x) のメッシュを描画するために Cone.x に記述されている内容を簡単に説明します。
    興味の無い方は読み飛ばしてプログラムの作成に進んで下さい。 (^_^;)
    Cone.x の説明は、ページの後部から Cone.x をダウンロードして、TEXT EDITOR などで表示しながら読んで下さい。
    X-FILE は TEXT 形式で記述されているので Editor で開けばファイルに書かれている内容を見ることができます。
    (binary 形式の X-FILE もあり、こちらは TEXT Editor では表示出来ません)
  2. 最初の一行はファイルのIDです。
    「xof」が X-FILE の識別で、次の「03」はメジャーバージョン、次の「02」はマイナーバージョンです。
    「txt」はテキストファイルであることを示し、バイナリモードでは「bin」となります。
    最後の「0064」は、数字を 64bit で読み込むことを宣言しています。
    xof 0302txt 0064
  3. template から始まる記述は、モデルデータのテンプレートで、Cone.x のモデルには直接関係ありません。
    template の次に来る <3D82AB43-62DA-11cf-AB39-0020AF71E433> という数字の羅列は「ユニークID」です。
    ユニークID はテンプレートを識別する固有のIDで「GuidGen.exe」という生成するツールを用いて取得します。
    続いて構造体のような記述が続きます。
    X-FILE は template と呼ばれる構造体のような記述に従って作成されています。
    詳細は 矩形ポリゴンを X-FILE に保存する を参照して下さい。
  4. 「Header {」に続く「Material」からがモデルの定義です。
    LIGHTWAVE などのツールを使って、ポリゴンに色を設定したモデルは、頂点座標と色と法線ベクトルで構成されています。
    「Material Matpi {」はピンク色のマテリアルの定義で、以下同様の記述が続きます。
  5. 「Mesh { 25; 」から頂点座標の記述です。
    25 は頂点座標の数で、X,Y,Z 座標がセミコロンまたはカンマで区切って記述されています。
  6. 続く「25;」がポリゴンの記述で頂点座標の Index 番号が並んでいます。
    最初の長い行は24角形の Cone のキャップ(蓋)です。
    TRIANGLEFAN を使えば簡単に定義できるのですが DirectX10 には宣言が見当たりません。
    続いて 24 個の三角形ポリゴンでボディが定義されています。
  7. 「MeshMaterialList { 5; 25; 」からがマテリアルの記述です。
    5; はポリゴンで使われている色の数で?、25; は定義されたポリゴンの数です。
    ポリゴンに割り当てる色の番号が、ポリゴンの数だけ並べられています。
    続いて色の番号で指定した5個の色の名前が記述されています。
    「{Matpi}」対応する色の定義は「Material Matpi {」として定義されています。
  8. 「MeshNormals { 25; 」からが法線ベクトルの記述です。
    25 は法線ベクトルの数で、X,Y,Z 座標がセミコロンまたはカンマで区切って記述されています。
  9. 続く「25;」が定義されたポリゴンの数で、ポリゴンに対応する法線ベクトルの番号が並んでいます。
  10. Main.cpp の vertices[] で Cone.x のメッシュデータを定義しています。
    Cone.x の記述と比べてみて下さい。

プログラムの説明

  1. EmptyProject10 には DirectX10 と DirectX9 のソースファイルが格納されていて、両方のプログラムが可能です。
    今回は純粋な DirectX10 のアプリケーションを作成します。
    DirectX10 のプロジェクトは幾つかあるのですが、MultiMon10 を使うことにします。
    DirectX Sample Browser で MultiMon10 のプロジェクトを作成して下さい。
    MultiMon10 のプロジェクトをコンパイルして、正常に実行されることを確かめて下さい。
    エラーが発生するときや、正常に実行出来ないときは、残念ながら現在の構成は相性が悪いようです。
  2. MultiMon10 のプロジェクトを使って Cone.x の頂点データをテーブルで定義して描画して見ましょう。
    ソースプログラムと Shader と X-FILE を圧縮形式で提供します。
    ファイル名 説明
    ConeData.zip 圧縮ファイル
  3. MultiMon10.cpp の説明です。
    VER_N は頂点フォーマットを定義する配列の大きさです。
    今回は index を使わずに直接描画します。
    SimpleVertex は頂点フォーマットの形式で、三次元座標と色と法線ベクトルを定義します。
    最初にコーンのボディ部を、続いてコーンのキャップ(蓋)を定義しています。
    コーンのボディ部は、24個の三角形ポリゴンで構成します。
    各ポリゴンには、6個ごとに異なる色と法線ベクトルを設定します。
    コーンのキャップ(蓋)は TRIANGLEFAN を使えば簡単に定義できるのですが、DirectX10 には宣言が見当たりません。
    仕方が無いので、ボディと同様に24個の三角形ポリゴンで構成します。
    ボディ部と併せて定義する方が簡単なので、ボディ部に続いて定義しています。
    キャップは一枚の多角形で、色と法線ベクトルは全て同じです。
    #define VER_N   144     //24*3*2
    
    struct SimpleVertex
    {
        D3DXVECTOR3 Pos;  
        D3DXVECTOR4 Color; 
        D3DXVECTOR3 Normal; 
    };
    SimpleVertex vertices[VER_N] =
    {
    //Cone Body
        { D3DXVECTOR3(-0.019889f,  1.093908f,  0.000000f), D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f), D3DXVECTOR3(0.894501f, 0.431277f, 0.117763f) },  //24  0-5 赤
        { D3DXVECTOR3( 1.017533f, -1.133686f,  0.277976f), D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f), D3DXVECTOR3(0.894501f, 0.431277f, 0.117763f) },  //1
            :
            :
        { D3DXVECTOR3( 1.054129f, -1.133686f,  0.0f),      D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f), D3DXVECTOR3(0.894501f, 0.431277f, -0.117763f) },  //0
        { D3DXVECTOR3( 1.017533f, -1.133686f, -0.277976f), D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f), D3DXVECTOR3(0.894501f, 0.431277f, -0.117763f) },  //23
    //Cone Cap
        { D3DXVECTOR3(-0.019889f, -1.133686f,  0.0f),      D3DXVECTOR4(0.5f, 0.96f, 0.996f, 1.0f), D3DXVECTOR3(0.0f, -1.0f, 0.0f) },  //24
        { D3DXVECTOR3( 1.054129f, -1.133686f,  0.0f),      D3DXVECTOR4(0.5f, 0.96f, 0.996f, 1.0f), D3DXVECTOR3(0.0f, -1.0f, 0.0f) },  //0
            :
            :
        { D3DXVECTOR3( 1.017533f, -1.133686f, -0.277976f), D3DXVECTOR4(0.5f, 0.96f, 0.996f, 1.0f), D3DXVECTOR3(0.0f, -1.0f, 0.0f) },  //23
        { D3DXVECTOR3( 1.054129f, -1.133686f,  0.0f),      D3DXVECTOR4(0.5f, 0.96f, 0.996f, 1.0f), D3DXVECTOR3(0.0f, -1.0f, 0.0f) },  //0
    };
    
  4. DirectX の領域定義です。
    特別な領域は無いので、これまでの説明を参照して下さい。
    ID3D10Effect*               g_pEffect = NULL;
    ID3D10InputLayout*          g_pLayout = NULL;
    ID3D10EffectTechnique*      g_pRender = NULL;
    ID3D10EffectMatrixVariable* g_pWorldVariable = NULL;
    ID3D10EffectMatrixVariable* g_pViewVariable = NULL;
    ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL;
    ID3D10Buffer*               g_pVertexBuffer = NULL;
    D3DXMATRIX                  g_World;
    D3DXMATRIX                  g_View;
    D3DXMATRIX                  g_Projection;
    
  5. OnD3D10CreateDevice() はデバイスを生成するときに呼ばれます。
    D3DX10CreateEffectFromFile() で "MultiMon10.fx" を入力して Shader を作成します。
    今回の頂点データは、三次元座標と色と法線ベクトルを定義しています。
    Vertex Buffer を確保して、コーンのデータを格納する処理は何時もと同じです。
    多角形の Cap が思ったより大きく Body が短く感じたので、視野角を少し狭めて、カメラを引いて描画してみました。
    HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
    {
        HRESULT hr = S_OK;
            :
            :
        // Define the input layout
        D3D10_INPUT_ELEMENT_DESC layout[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },  
            { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, 
            { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 28, D3D10_INPUT_PER_VERTEX_DATA, 0 }, 
        };
        UINT numElements = sizeof(layout)/sizeof(layout[0]);
            :
            :
        // Initialize the world matrix
        D3DXMatrixIdentity(&g_World);
        // Initialize the view matrix
        D3DXVECTOR3 Eye( 0.0f, 1.0f, -5.0f );
        D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f );
        D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );
        D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up );
    
        // Initialize the projection matrix
        D3DXMatrixPerspectiveFovLH(&g_Projection, (float)D3DX_PI * 0.3f, 640.0f/480.0f, 0.1f, 100.0f);
        return S_OK;
    }
    
  6. OnD3D10FrameRender() は Rendering を行う CALLBACK 関数です。
    X軸とY軸の周期をずらせて回転しながら描画してみました。
    レンダリングを行う処理は何時もと同じです。
    void CALLBACK OnD3D10FrameRender( ID3D10Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
    {
       D3DXMATRIX matw;
        //World 座標の回転
        D3DXMatrixIdentity(&g_World);
        D3DXMatrixRotationX(&matw, (float)fTime/2.0f);
        D3DXMatrixMultiply(&g_World, &g_World, &matw);
        D3DXMatrixRotationY(&matw, (float)fTime/5.0f);
        D3DXMatrixMultiply(&g_World, &g_World, &matw);
            :
            :
    
  7. OnD3D10DestroyDevice() では取得した Object を開放して下さい。
    Shader は色と法線ベクトルを持つモデルに光源を設定して描画するものを使って下さい。
    プロジェクトの名前(フォルダの名前)は自由に変更することが出来ます。

超初心者のプログラム入門(DirectX10 game program)