メッシュを生成して X-FILE に保存する

D3DXCreateBox() などでメッシュを生成して X-FILE に保存します。

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

プログラムの説明

  1. DirectX には D3DXCreateBox() や D3DXCreateTeapot() など、モデルを自動的に生成する関数が用意されています。
    これらの関数を使って作成したモデルを X-FILE として保存してみましょう。
    X-FILE の形式は X-FILE(Cone.x) の頂点データを定義する を参照して下さい。
    また「X-FILE 作成」の基礎は 矩形ポリゴンを X-FILE に保存する を参照して下さい。
  2. このプログラムは、D3DXCreateBox() や D3DXCreateTeapot() などでメッシュを生成して回転しながら描画します。
    そして、プログラムを終了する前に描画中のモデルを X-FILE として保存します。
    モデルの作成と描画の基礎は MyD3D Class でティーポットを描画する を参照して下さい。
    X-FILE のインターフェイスを使うので "template.h" を取り込みます。
    template.h は DirectX10 の 矩形ポリゴンを X-FILE に保存する から取得して下さい。
    template.h の先頭部分を DirectX9 に合わせて修正して下さい。
    X-FILE のインターフェイスを使うためには d3dxof.lib をリンクして、dxfile.h をインクルードします。
    /***************************************/
    /* X-FILE X9 template Header   前田 稔 */
    /***************************************/
    #ifndef _template_
    #define _template_
    
    #include    <Windows.h>
    #include    <d3dx9.h>
    #include    <dxfile.h>   // Xファイル関連を使用するのに必要
    
    // Library
    #pragma once
    #pragma comment(lib,"d3d9.lib")
    #pragma comment(lib,"d3dx9.lib")
    #pragma comment(lib,"dxguid.lib")
    #pragma comment(lib,"d3dxof.lib")
    #pragma comment(lib,"winmm.lib")
    
  3. プログラムを終了する前に SaveXfile() で描画中のモデルを X-FILE として保存します。
        switch(msg)
        {   case WM_DESTROY:
                SaveXfile();
                Cleanup();
                PostQuitMessage(0);
                break;
        
  4. モデルを保存する SaveXfile() 関数です。
    X-FILE の作成は専用のインターフェイスが用意されています。
    保存の基礎は「矩形ポリゴンを X-FILE に保存する」を参照して下さい。
    SetMeshData() でメッシュのデータを構造体に設定します。
    D3DXCreateBox() などで生成したメッシュは、頂点座標と法線ベクトルで構成されています。
    // メッシュを X-FILE に出力する。
    void  SaveXfile()
    {
        IDirectXFile *pDXFile = NULL;
        IDirectXFileSaveObject *pDXSave = NULL;
        IDirectXFileData *pDXData = NULL;
        IDirectXFileData *pDXChildData = NULL;
    
        // セーブするテンプレート文字列を取得
        DirectXFileCreate( &pDXFile );
        if(FAILED(pDXFile->RegisterTemplates(str,strlen(str))))     goto error;
    
        // セーブオブジェクトを作成する
        if(FAILED(pDXFile->CreateSaveObject("model.x", DXFILEFORMAT_TEXT, &pDXSave )))
            goto error;
    
        //★ メッシュのデータを構造体に格納する。
        if (FAILED(SetMeshData()))  goto error;
    
        // Header を書き出す
        if(FAILED(pDXSave->CreateDataObject( Header, NULL, NULL, sizeof(hed), &hed, &pDXData)))
            goto error;
        if(FAILED(pDXSave->SaveData(pDXData)))  goto error;
        SAFE_RELEASE(pDXData);
    
        // Mesh を書き出す
        if(FAILED(pDXSave->CreateDataObject( Mesh, NULL, NULL, mesh_size, mesh_struct, &pDXData)))
            goto error;
    
        // MeshNormals を設定
        if(FAILED(pDXSave->CreateDataObject( MeshNormals, NULL, NULL, mesh_size, normal_struct, &pDXChildData)))
            goto error;
        // MeshNormals を Mesh に加える
        pDXData->AddDataObject(pDXChildData); 
        if(FAILED(pDXSave->SaveData(pDXData)))  goto error;
        goto exit;
    
    error:
        MessageBox(NULL, "失敗しました", "Error Message", MB_OK);
    exit:
        GlobalFree(mesh_struct);
        GlobalFree(normal_struct);
        SAFE_RELEASE(pDXChildData);
        SAFE_RELEASE(pDXData);
        SAFE_RELEASE(pDXSave);
        SAFE_RELEASE(pDXFile);
    }
    
  5. 描画中のメッシュのデータを構造体に設定する関数です。
    D3DXCreateBox() などで生成したメッシュは、頂点座標と法線ベクトルで構成されています。
    メッシュは全て三角形ポリゴンで定義されているようです。
    GetNumVertices() で頂点座標の個数を取得します。
    GetNumFaces() でフェース(ポリゴン)の個数を取得します。
    mesh_size に Mesh 構造体のサイズを計算して、メモリ領域を割り当てます。
    頂点座標を定義する MeshNormals 構造体のメモリ領域を割り当てます。
    構造体のメンバーにアクセスするために、アドレス(ポインタ)を設定します。
    GetVertexBuffer() で頂点座標の領域を取得します。
    GetIndexBuffer() でインデックスの領域を取得します。
    メモリ領域に割り当てた構造体に template に従ってメッシュのデータを格納します。
    // メッシュのデータを構造体に格納する。
    HRESULT SetMeshData()
    {   DWORD                   nV,nF,i;
        LPDIRECT3DVERTEXBUFFER9 pSrcVB=NULL;
        D3DVERTEX*              pVSrc;
        LPDIRECT3DINDEXBUFFER9  pSrcIB=NULL;
        WORD*                   pISrc;
        DWORD                   *nVertices;
        Vector                  *vertices;
        DWORD                   *nFaces;
        MeshFace                *faces;
        DWORD                   *nNormals;
        Vector                  *normals;
        DWORD                   *nFaceNormals;
        MeshFace                *facenormals;
    
        nV= g_pMesh->GetNumVertices();
        nF= g_pMesh->GetNumFaces();
        mesh_size= sizeof(Vector)*nV+sizeof(MeshFace)*nF+8;
        mesh_struct= (BYTE *)GlobalAlloc(GMEM_FIXED,mesh_size);
        normal_struct= (BYTE *)GlobalAlloc(GMEM_FIXED,mesh_size);
    
        // アドレスを設定
        nVertices= (DWORD*)mesh_struct;
        vertices= (Vector*)(mesh_struct+sizeof(DWORD));
        nFaces= (DWORD*)(mesh_struct+sizeof(DWORD)+sizeof(Vector)*nV);
        faces= (MeshFace*)(mesh_struct+sizeof(DWORD)+sizeof(Vector)*nV+sizeof(DWORD));
        nNormals= (DWORD*)normal_struct;
        normals= (Vector*)(normal_struct+sizeof(DWORD));
        nFaceNormals= (DWORD*)(normal_struct+sizeof(DWORD)+sizeof(Vector)*nV);
        facenormals= (MeshFace*)(normal_struct+sizeof(DWORD)+sizeof(Vector)*nV+sizeof(DWORD));
    
        // データを抽出して構造体に格納
        *nVertices= nV;
        *nNormals= nV;
        *nFaces= nF;
        *nFaceNormals= nF;
        if (FAILED(g_pMesh->GetVertexBuffer(&pSrcVB)))  return E_FAIL;
        pSrcVB->Lock(0,0,(void**)&pVSrc,0);
        if (FAILED(g_pMesh->GetIndexBuffer(&pSrcIB)))   return E_FAIL;
        pSrcIB->Lock(0,0,(void**)&pISrc,0);
        // 頂点データ
        for(i=0; i<nV; i++)
        {   vertices->x= pVSrc->x;
            vertices->y= pVSrc->y;
            vertices->z= pVSrc->z;
            vertices+= 1;
            normals->x= pVSrc->nx;
            normals->y= pVSrc->ny;
            normals->z= pVSrc->nz;
            normals+= 1;
            pVSrc+= 1;
        }
        // Face データ
        for(i=0; i<nF; i++)
        {   faces->nFaceVertexIndices= 3;
            faces->faceVertexIndices[0]= *pISrc;
            faces->faceVertexIndices[1]= *(pISrc+1);
            faces->faceVertexIndices[2]= *(pISrc+2);
            faces+= 1;
            facenormals->nFaceVertexIndices= 3;
            facenormals->faceVertexIndices[0]= *pISrc;
            facenormals->faceVertexIndices[1]= *(pISrc+1);
            facenormals->faceVertexIndices[2]= *(pISrc+2);
            facenormals+= 1;
            pISrc+= 3;
        }
    
        pSrcVB->Unlock();
        SAFE_RELEASE(pSrcVB);
        pSrcIB->Unlock();
        SAFE_RELEASE(pSrcIB);
        return S_OK;
    }
    

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

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