3D游戏从入门到精通-28 .30

  /***********************************
 *作者:蔡军生
 *出处:
http://blog.csdn.net/caimouse/
 ************************************/
加载网格模型文件
在游戏里,最常的东西是什么呢?肯定是各种怪物和场境。比如在《传奇世界》就有很多猪和青铜兽。在3D游戏里,要显示一个地图,就需要加载网格模型文件来显示。比如像《半条命》里的练习场,就是一个3D模型文件。因此,游戏要显示的东西,大多是从文件里加载模型来显示的。游戏显示的模型都是比较复杂的,比前面所用到的三角形、立方体等模型,要复杂很多。如果每个模型都是用程序来实时创建,速度也是很慢的。目前大多数模型是使用建模型软件来创建,然后保存为文件,再程序来加载显示。比较流行的建模软件有3DS MAX、Maya等,美工就可以使用它们来创建地图中的场境、怪物的模型。在开发一个游戏里,美工的人员往往占了绝大部份,几个G的游戏,图片和模型占了绝大多数空间。
 
X文件格式
美工做出来的模型和图片,可能是各式各样的,格式也不一致,并且分离的。这样就需要把它们转换成统一的文件格式,方便游戏引擎加载,当然这种文件格式也是作了优化的工作。比如《半条命》里的mdl文件,就是作了很多预计算,并且优化了顶点和三角形列表。对于初学者来说,越简单的文件格式,就越容易学习。因此,就采用了D3D里的X文件格式。X文件格式的功能也是非常强大的,它可以自定义各种数据结构,可以支持静态模型,也可以支持动画。X文件格式可以文本方式保存,也可以二进制方式保存。使用X文件格式特别方便,因为D3D里已经完全支持读取和输出X文件格式,同时D3D也提供给3DS MAX、Maya等插件输出X文件格式。
 
如果觉得X文件格式不好,当然也可以自己定义一种更好的文件格式,但就需要自己去写加载、保存、优化和导出程序。
 
下面就来看看怎么样加载一个X文件的模型显示,显示的效果如下:
  
 

电子书MM3D引擎源程序例子源程序49元一套

联系人:蔡军生 

联系方式:

QQ: 9073204

EMAIL: caimouse1976 at sina.com

 

加载X文件步骤
 
在3D游戏里,大部份的动作,就是加载不同的模型文件。在这里先从最简单的学起,从原理性学起,再多,再复杂的东西都是一样的。在这里只是加载了一个简单的立方体,它的文件名称是Cube_txt.x。立即来看看程序是怎么样加载的呢?

 3D游戏从入门到精通-30

加载复杂网格模型
上面都是简单的网格例子,并且只能作为演示作用,没有多少实用价值,下面来加载一个更复杂的网格模型。在我们玩过的游戏里,绝大多数都有室内场境的地方,比如到武器店里买东西,就需要有一个室内场境。在我们最常见的房子,大多数都是长方形的,也就是有6个面的立方体,而在这六个面贴上纹理,就是室内环境了。由于我没有美工,只能拿现成的网格模型来加载显示,模型文件放在目录G:/MM3D/Engine/bin/models里,其中room.x是网格模型文件,DoorDiff.dds、FireplaceDiff.dds、oldwood.dds、wallpaper.dds都是纹理图片。实现的效果图如下:
 
电子书MM3D引擎源程序例子源程序49元一套
联系人:蔡军生 
联系方式:
QQ: 9073204
EMAIL: caimouse1976 at sina.com
 
在这个场境里,主要有四部份组成,地板是由贴木板纹理的模型组成。四周的墙是由花纹纹理的模型组成。还有一个门模型,以及火墙模型。在这个例子里,比上面一个复杂的地方,就是多了纹理贴图。
先看看加载网格模型的函数,看看怎么样实现加载网格和纹理。
//
//加载网格模型。
//蔡军生 2006/09/15
//
HRESULT CCAIRoom::LoadMeshFromFile(void)
{
 //网格模型路径。
 char chPath[MAX_PATH];
 if ( !GetModuleFileName( NULL, chPath, MAX_PATH ) )
 {
       return S_FALSE;
 }
 
 std::string strName(chPath);
 std::basic_string <char>::size_type stPos = strName.find_last_of("//");
 if(stPos != std::string::npos)
 {
       strName = strName.substr(0,stPos);
 }
 
 std::string strPath = strName;
 const std::string strFile("//bin//models//room.x");
 strName += strFile;
 
 //加载X文件。
  LPD3DXBUFFER pAdjacencyBuffer = NULL;
 LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
 HRESULT hr = D3DXLoadMeshFromX( strName.c_str(), D3DXMESH_MANAGED,
       m_pd3dDevice, &pAdjacencyBuffer,
       &pD3DXMtrlBuffer, NULL, &m_dwNumRoomMaterials,
       &m_pMeshRoom );
 if (FAILED(hr))
 {
       return DXTRACE_ERR( "D3DXLoadMeshFromX", hr );
 }
 
 // 优化网格显示。
 if( FAILED( hr = m_pMeshRoom->OptimizeInplace(
       D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
       (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
 {
       if (pAdjacencyBuffer)
       {
             pAdjacencyBuffer->Release();
       }
 
       if (pD3DXMtrlBuffer)
       {
             pD3DXMtrlBuffer->Release();
       }
       return DXTRACE_ERR("OptimizeInplace",hr);
 }
 
 //是否有材料。
 if (pD3DXMtrlBuffer && m_dwNumRoomMaterials > 0)
 {
       //
       D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
       m_pMeshRoomMaterials = new D3DMATERIAL9[m_dwNumRoomMaterials];
       if (!m_pMeshRoomMaterials)
       {
             //        
             pD3DXMtrlBuffer->Release();
             return E_OUTOFMEMORY;
       }
 
       //保存材料和纹理。
       for( DWORD i = 0; i < m_dwNumRoomMaterials; i++ )
       {
             //
             m_pMeshRoomMaterials[i] = d3dxMaterials[i].MatD3D;
             m_pMeshRoomMaterials[i].Ambient = m_pMeshRoomMaterials[i].Diffuse;
 
             //
             if( d3dxMaterials[i].pTextureFilename != NULL &&
                  lstrlen(d3dxMaterials[i].pTextureFilename) > 0 )
             {
                  //
                  LPDIRECT3DTEXTURE9 pMeshTextures = NULL;
                  std::string strTemp = strPath + "//bin//models//";
                  strTemp += d3dxMaterials[i].pTextureFilename;
 
                  hr = D3DXCreateTextureFromFile( m_pd3dDevice,
                        strTemp.c_str(),
                        &pMeshTextures );
 
                  if (SUCCEEDED(hr))
                  {
                        m_vMeshRoomTextures.push_back(pMeshTextures);
                  }
                  else
                  {
                        m_vMeshRoomTextures.push_back(NULL);
                  }                    
 
                  OutputDebugString("Texture/n");
             }
             else
             {
                  m_vMeshRoomTextures.push_back(NULL);
             }
       }
 
 }
 
 //
 if (pD3DXMtrlBuffer)
 {
       pD3DXMtrlBuffer->Release();
 }
 
 if (pAdjacencyBuffer)
 {
       pAdjacencyBuffer->Release();
 }
 
 
 return S_OK;
}
 
 

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值