X_FILE Object Class

X_FILE Object Class を使って、虎のメッシュ(tiger.x)を描画します。
MyD3D Object Class には、X_FILE を入力するメンバー関数が含まれているのですが、 今回は X_FILE を描画する専用の Object Class を作成してみました。

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

X_FILE Object Class の使い方

  1. X_FILE.h を include して下さい。
    *xfile が X_FILE Object Class の定義です。
        #include    "X_FILE.h"
        X_FILE      *xfile  = NULL;         // X_FILE Object Class
        
  2. LPDIRECT3DDEVICE9 と X_file 名を指定してオブジェクトを生成します。
        xfile= new X_FILE(g_pDEV,"Cone.x");
        
  3. Render() メンバー関数でメッシュを描画します。
        xfile->Render();
        
  4. プログラムを終了する前に Object Class を削除して下さい。
        SAFE_DELETE(xfile);
        
  5. どうです、簡単でしょう。 (^_^;)
    面倒な処理は全て Object Class の中で行っています。

X_FILE Object Class

  1. X_FILE Object Class のヘッダーファイル(X_FILE.h)です。
    /****************************************/
    /* X_FILE Object Class Header   前田 稔 */
    /****************************************/
    #ifndef _X_FILE
    #define _X_FILE
    
    #include 
    #define SAFE_DELETE(p)  { if (p) { delete (p);     (p)=NULL; } }
    #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
    
    class X_FILE
    { protected:
        LPDIRECT3DDEVICE9       pDEV;        // 描写用デバイス
        LPD3DXMESH              pMesh;       // Our mesh object in sysmem
        D3DMATERIAL9*           pMat;        // Materials for our mesh
        LPDIRECT3DTEXTURE9*     pTex;        // Textures for our mesh
        DWORD                   dwNum;       // Number of mesh materials
    
      public:
        X_FILE(LPDIRECT3DDEVICE9, LPSTR);    //Constructor
        ~X_FILE();                           //Destructor
        void	Render();
    };
    
    #endif
    
  2. X_FILE Object Class のプログラムファイル(X_FILE.cpp)です。
    /*****************************************/
    /* X_FILE Object Class Program   前田 稔 */
    /*****************************************/
    #include    "X_FILE.h"
    
    //★ Constructor
    X_FILE::X_FILE(LPDIRECT3DDEVICE9 dev, LPSTR model)
    {   LPD3DXBUFFER pD3DXMtrlBuffer;
    
        pDEV= dev;
        pMesh= NULL;
        pMat= NULL;
        pTex= NULL;
        dwNum= 0L;
    
        if (FAILED(D3DXLoadMeshFromX(model, D3DXMESH_SYSTEMMEM, pDEV, NULL,
                &pD3DXMtrlBuffer, NULL, &dwNum, &pMesh)))
        {   MessageBox(NULL, "Could not find x file", "LoadMeshFromX",MB_OK);
            return;
        }
        D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
        pMat= new D3DMATERIAL9[dwNum];
        if (pMat==NULL)     return;
        pTex = new LPDIRECT3DTEXTURE9[dwNum];
        if (pTex==NULL)     return;
        for(DWORD i=0; i<dwNum; i++)
        {   pMat[i]= d3dxMaterials[i].MatD3D;
            pTex[i] = NULL;
            if (d3dxMaterials[i].pTextureFilename!=NULL && 
               lstrlen(d3dxMaterials[i].pTextureFilename)>0)
            {   if (FAILED(D3DXCreateTextureFromFile(pDEV,
                        d3dxMaterials[i].pTextureFilename,&pTex[i])))
                    MessageBox(NULL,"Could not find texture map","X File Object",MB_OK);
            }
        }
        pD3DXMtrlBuffer->Release();
    
        // 法線ベクトルが設定されていないときの処理
        if (!( (pMesh)->GetFVF() & D3DFVF_NORMAL ))
        {
            ID3DXMesh* pTempMesh;
            (pMesh)->CloneMeshFVF((pMesh)->GetOptions(), (pMesh)->GetFVF() | D3DFVF_NORMAL, pDEV, &pTempMesh);
            D3DXComputeNormals(pTempMesh, NULL);
            SAFE_RELEASE(pMesh);
            (pMesh) = pTempMesh;
        }
    }
    
    //★ Destructor
    X_FILE::~X_FILE()
    {
        SAFE_DELETE(pMat);
        if (pTex)
        {   for(DWORD i=0; i<dwNum; i++)   SAFE_RELEASE(pTex[i]);
            SAFE_DELETE(pTex);
        }
        SAFE_RELEASE(pMesh);
    }
    
    // モデルを描画
    void X_FILE::Render()
    {
        if (pMesh)
        {   for(DWORD i=0; i<dwNum; i++)
            {   pDEV->SetMaterial(&pMat[i]);
                pDEV->SetTexture(0,pTex[i]);
                pMesh->DrawSubset(i);
            }
        }
    }
    

Object Class の説明

  1. X_FILE Object Class の Header File です。
    pMesh は X_file の Mesh のオブジェクトです。
    pMat は X_file の Materials 情報です。
    pTex は X_file の Textures 情報です。
    dwNum には X-file に格納されている「属性テーブル」のエントリ数?が格納されます。
    メンバー関数は Constructor と Destructor と Render() だけです。
            LPDIRECT3DDEVICE9       pDEV;   // 描写用デバイス
            LPD3DXMESH              pMesh;  // Our mesh object in sysmem
            D3DMATERIAL9*           pMat;   // Materials for our mesh
            LPDIRECT3DTEXTURE9*     pTex;   // Textures for our mesh
            DWORD                   dwNum;  // Number of mesh materials
    
          public:
            X_FILE(LPDIRECT3DDEVICE9, LPSTR);   //Constructor
            ~X_FILE();                          //Destructor
            void    Render();
        };
        
  2. Constructor で描画に必要な情報を設定します。
    D3DXLoadMeshFromX() で X-file を入力します。
    詳細は マテリアルを設定して、虎のモデルを描画する を参照して下さい。
        //★ Constructor
        X_FILE::X_FILE(LPDIRECT3DDEVICE9 dev, LPSTR model)
        {   LPD3DXBUFFER pD3DXMtrlBuffer;
    
            pDEV= dev;
            pMesh= NULL;
            pMat= NULL;
            pTex= NULL;
            dwNum= 0L;
    
            if (FAILED(D3DXLoadMeshFromX(model, D3DXMESH_SYSTEMMEM, pDEV, NULL,
                    &pD3DXMtrlBuffer, NULL, &dwNum, &pMesh)))
            {   MessageBox(NULL, "Could not find x file", "LoadMeshFromX",MB_OK);
                return;
            }
               ・・・
        
  3. メッシュ(X_file)を描画する Render() 関数です。
    SetMaterial() でマテリアルを設定して DrawSubset() で描画します。
        void X_FILE::Render()
        {
            if (pMesh)
            {   for(DWORD i=0; i<dwNum; i++)
                {   pDEV->SetMaterial(&pMat[i]);
                    pDEV->SetTexture(0,pTex[i]);
                    pMesh->DrawSubset(i);
                }
            }
        }
        

tiger.x を描画する

  1. 今までの説明で普通に作成された X_file は描画できるのですが、残念ながら tiger.x を描画すると真っ黒になってしまいます。 (;_;)
    最初の頃は随分悩んだのですが、原因は法線ベクトルが設定されたいないために光源を設定しても光を反射しないブラックホールのようになっていたためです。
  2. Constructor の最後に追加されている、次のソースコードで法線ベクトルを設定します。
    法線ベクトルが設定されていないときに、D3DXComputeNormals() で法線ベクトルの計算を行います。
            // 法線ベクトルが設定されていないときの処理
            if (!( (pMesh)->GetFVF() & D3DFVF_NORMAL ))
            {
                ID3DXMesh* pTempMesh;
                (pMesh)->CloneMeshFVF((pMesh)->GetOptions(), (pMesh)->GetFVF() | D3DFVF_NORMAL, pDEV, &pTempMesh);
                D3DXComputeNormals(pTempMesh, NULL);
                SAFE_RELEASE(pMesh);
                (pMesh) = pTempMesh;
            }
        

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

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