浅谈DirectX的模型加载

浅谈DirectX的模型加载

喜欢这篇文章吗?分享给你的朋友吧~ 

基于DirectX的游戏开发中,人物和模型由针对每个对象的成千上万个多边形组成的,对纹理映射而言这是非常复杂的,假设不加索引的几何图形,而只是用三角形(DirectX的模型基础是三角形)。那将会是一场恐怖的噩梦。所以现在将简单地介绍从游戏程序外获取那些图形开发资源。

加载模型的方法多种多样,鉴于现实生活中各式各样的模型文件格式,加载的渠道也不太一致。文件格式只是在特定文件中保存信息的方式。Direct3D中的文件格式也是多种多样,如X模型文件,OBJ模型,UMF模型等。现在主要对X模型也就是DirectX模型的加载进行介绍:首先先对X模型进行些微介绍,X模型是在Direct3D中使用的模型,可以使用内置的Direct3d函数加载,渲染,和释放X模型。X文件是基于Mesh模板网格的,这种模板包括外观,纹理,法线等。X模板可以被保存为文本文件,也可以被保存为二进制文件。这意味这可以在任意的文本编辑器中打开X文件并修改其内容。下面介绍一下由两个三角形组成的X模型:

两个三角形组成的X文件模型的实例

 xof     0302txt      0032       //xof意味着正在加载的是某个版本的X文件,
                                      //后面是组版本号与次版本号32(0032)
 
   Material   UgpMat {               //Material    0.
 
      1.0;  1.0  1.0;   1.0;  ;        //Diffuse    Color(反射颜色)
 
      0.0;                               //Specular   power
 
      0.0;  0.0;  0.0; ;             //Specular      color(颜色三坐标意味RGB)
 
      0.0;    0.0; 0.0;;             //Emissive    color
 
      TextureFilename("ugp.bmp";)  //Texture      filename(纹理文件名)
 
   }
 
      //   The   square  mesh  data.
 
 Mesh   Square   {          //定义了完整网格
 
        4;                         //Number   of   vertexs.
 
       1.0;   1.0;   0.0;//Vertex   1
 
       - 1.0;   1.0;   0.0;//Vertex    2
 
     - 1.0;   -1.0;   0.0;//Vertex     3
 
       1.0;   -1.0;   0.0;        //Vertex       4
 
       2;                             //Number   of   triangles.
 
       3;   0,   1,  2;           //Triangle   indices   1.
 
       3  ;   0,   2,  3;        //Triangle  indices    2.
 
     MeshMaterialList {       //该模板指明网格中的外观使用哪种材质
 
        1;                                 //Number  of  materials.
 
        2;                                  //Number    of    faces.
 
        0;                              //Face   0   use  material    0.
 
        0; ;                           //Face   1    use   material   0.
 
       {UgpMat}                    //Reference    of   material.
 
            }
 
     MeshTextureCoords  {       //该模板将纹理映射到网格
 
       4;
 
       0.0;     0.0;,              //Vertex  1   tex      coord,
 
       0.0;     1.0;,            //Vertex    2   tex      coord.
 
       1.0;     1.0;,        //Vertex   3  tex      coord.
 
       1.0;    0.0; ;       //Vertex    4    tex     coord.
 
      }
  }    //End      of    Mesh   Squar

这就是一个完整的X模型实例代码   , 它包含了 几个模块:Material模板, Mesh模板,
MeshMaterial List模板,MeshTextureCoords模板。

下面将介绍次模型的加载,加载一个老虎模型,主要可分为两种类型的:Common与非Common类的。

非Common结构

1,模型的全局变量

     LPDIRECT3D9             g_pD3D           = NULL;      // Direct3D对象
     LPDIRECT3DDEVICE9       g_pd3dDevice     = NULL; // Direct3D设备
 
      LPD3DXMESH              g_pMesh          = NULL;     // mesh模型指针
      D3DMATERIAL9*           g_pMeshMaterials = NULL;   //mesh模型所用材质指针
      LPDIRECT3DTEXTURE9*     g_pMeshTextures  = NULL; // mesh模型所用纹理指针
      DWORD                   g_dwNumMaterials = 0L;          //mesh模型材质数量

2.初始化D3D流程

  HRESULT InitD3D( HWND hWnd )
       {
          // 创建direct3D对象
            if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
                     return E_FAIL;
 
        //填写结构体创建direct3D设备,使用z深度缓冲
         D3DPRESENT_PARAMETERS d3dpp;
           ZeroMemory( &d3dpp, sizeof(d3dpp) );
          d3dpp.Windowed = TRUE;
          d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
          d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
          d3dpp.EnableAutoDepthStencil = TRUE;
          d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
 
        //创建D3D设备
     if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
              D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                         &d3dpp, &g_pd3dDevice ) ) )
            {
                  return E_FAIL;
                }
 
        // 开启z深度缓冲
         g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
 
       // 开启环境光
        g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );
 
           return S_OK;
   }

3,初始化几何数据流程

     HRESULT InitGeometry()
       {
              LPD3DXBUFFER pD3DXMtrlBuffer;
 
             // 从文件中加载Mesh模型
          if( FAILED( D3DXLoadMeshFromX( "Tiger.x", D3DXMESH_SYSTEMMEM,
                                                       g_pd3dDevice, NULL,
                                                      &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials,
                                                      &g_pMesh ) ) )
             {
                      // 如果当前文件夹中没有需要加载的X文件,则尝试在上一级目录加载
                if( FAILED( D3DXLoadMeshFromX( "../Tiger.x", D3DXMESH_SYSTEMMEM,
                                                              g_pd3dDevice, NULL,
                                                              &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials,
                                                              &g_pMesh ) ) )
                        {
                          MessageBox(NULL, "Could not find tiger.x", "Meshes.exe", MB_OK);
                          return E_FAIL;
                          }
               }
 
   //需要从pD3DXMtrlBuffer指向的缓冲区中释放材质信息和纹理名称
     D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
     g_pMeshMaterials = new    D3DMATERIAL9[g_dwNumMaterials];
     g_pMeshTextures  = new   LPDIRECT3DTEXTURE9[g_dwNumMaterials];
 
       for( DWORD i=0; i<g_dwNumMaterials; i++ )
       {
              // 复制材质
               g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
 
              // 为材质设定环境光颜色
              g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
 
             g_pMeshTextures[i] = NULL;
             if(    d3dxMaterials[i].pTextureFilename != NULL &&
                    lstrlen(d3dxMaterials[i].pTextureFilename) > 0 )
              {
                 //通过纹理文件名加载纹理
                      if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice,
                                                          d3dxMaterials[i].pTextureFilename,
                                                                       &g_pMeshTextures[i] ) ) )
                     {
                        //如果纹理文件不在当前文件夹中尝试上一级文件夹
                          const TCHAR* strPrefix = TEXT("../");
                          const int lenPrefix = lstrlen( strPrefix );
                          TCHAR strTexture[MAX_PATH];
                          lstrcpyn( strTexture, strPrefix, MAX_PATH );
                          lstrcpyn( strTexture +      lenPrefix,    
                                       d3dxMaterials[i].pTextureFilename,                
                                                              MAX_PATH - lenPrefix );
                       // 从上一文件夹创建
                      if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice,
                                               strTexture,
                                                 &g_pMeshTextures[i] ) ) )
                        {
                        MessageBox(NULL, "Could not find texture map", "Meshes.exe", MB_OK);
                       }
                     }
                }
      }
 
   // 释放材质缓冲区
   pD3DXMtrlBuffer->Release();
 
    return S_OK;
  }

程序刚开始使用的缓冲区ID3DXBuffer,它是数据缓冲区接口,可以储存定点项目数据,索引数据,邻近数据,材质信息等。
它有两个非常重要的接口GetBufferPointer()和GetBufferSize(),分别是返回缓冲区数据指针和缓冲区大小指针。
(这上面的代码还缺少了一些渲染之类的,和释放处理内存的步棸)
其中包含了一个结构:

       HRESULT WINAPI D3DXLoadMeshFromX(
                 LPCTSTR pFilename,//加载的X文件名可以是相对路径名或绝对路径名
                 DWORD Options,                        //Mesh模型标识符
                 LPDIRECT3DDEVICE9 pD3DDevice,
                 LPD3DXBUFFER *ppAdjacency,                                 //邻近三角形信息
 
                LPD3DXBUFFER *ppMaterials,                               //   返回材质指针
 
                LPD3DXBUFFER *PPEffectTnstances,                 //   返回特效实例指针
                DWORD *pNumMaterials,                                      //     返回材质数量
               LPD3DXMESH *ppMesh                                      //    返回被加载的Mesh模型
          );

使用Common结构

步棸 1,在派生类CMyD3DApplication的声明中添加一行成员变量声明。

CD3DMesh*   m_pMesheh;

步棸2,在CMyD3DApplication构造函数里添加一行。

m_pMesh  = new  CD3DMesh;

步棸3,在可重写函数InitDeviceObjects()里添加一行。

m_pMesh->Create(m_pd3dDevice, “Map.X”);

步棸4,可重写函数RestoreDeviceObjects()里添加

m_pd3dMesh->RestoreDeviceObjects(m_pd3dDevice);

步棸5, 在可重写函数Render()里添加

m_pMesh->Render(M_pd3dDevice);

步棸6,在可重写函数InvalidareDeviceObjects()中添加一行

m_pMesh->InvalidareDeviceObjects();

步棸7,在可重写函数DeleteDeviceObjects()中添加一行

m_pMesh->Destroy();

编译后即可完成加载 ,再用Common时应注意在安装DirectX时的环境配置应该添加DXSDK/Sampels/c++/common/include   以及其下的/Src.


——————————————–

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值