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;
}
 
 

 

 
發佈了2 篇原創文章 · 獲贊 13 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章