作者:StrongCoding
邮箱:StrongCoding@qq.comDX群:130302441
若文中有误,请告知.十分感谢.一起加油.
在上一篇中,我们一起学习了关于渐变网格模型的相关知识点,回顾下包括:如何生成渐变网格、渐变网格的优势、如何自定义设置渐 变网格的品质权重值、顶点权重值、如何重新再次设置最小最大面数或者顶点数。在接下来的这一篇幅中,我们主要一起学习下实现代码:
一、实现思路:
1、正常加载一个.X文件,存储于SourceMesh
2、生成我们的渐进网格模型DestMesh
3、渲染我们的渐进网格DestMesh
二、下面我们将根据以上的思路,用代码展现这一思路
1、正常加载
ID3DXBuffer* adjBuffer = 0; ID3DXBuffer* mtrlBuffer = 0; DWORD numMtrls = 0; hr = D3DXLoadMeshFromX( "bigship1.x", D3DXMESH_MANAGED, Device, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &SourceMesh
);
if( mtrlBuffer != 0 && numMtrls != 0 ) { D3DXMATERIAL* mtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer(); for(int i = 0; i < numMtrls; i++) { // the MatD3D property doesn't have an ambient value set // when its loaded, so set it now: mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse; // save the ith material Mtrls.push_back( mtrls[i].MatD3D ); // check if the ith material has an associative texture if( mtrls[i].pTextureFilename != 0 ) { // yes, load the texture for the ith subset IDirect3DTexture9* tex = 0; D3DXCreateTextureFromFile( Device, mtrls[i].pTextureFilename, &tex
); // save the loaded texture Textures.push_back( tex ); } else { // no texture for the ith subset Textures.push_back( 0 ); } } } d3d::Release<ID3DXBuffer*>(mtrlBuffer); // done w/ buffer
hr = SourceMesh->OptimizeInplace( D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjBuffer->GetBufferPointer(), (DWORD*)adjBuffer->GetBufferPointer(), // new adjacency info 0,
0
); if(FAILED(hr)) { ::MessageBox(0, "OptimizeInplace() - FAILED", 0, 0); d3d::Release<ID3DXBuffer*>(adjBuffer); // free return false; }
2 、借助原SourceMesh来生成我们的渐进网格模型DestMesh
hr = D3DXGeneratePMesh( SourceMesh, (DWORD*)adjBuffer->GetBufferPointer(), // adjacency 0, // default vertex attribute weights 0, // default vertex weights 1, // simplify as low as possible D3DXMESHSIMP_FACE, // simplify by face count &PMesh
); d3d::Release<ID3DXMesh*>(SourceMesh); // done w/ source mesh d3d::Release<ID3DXBuffer*>(adjBuffer); // done w/ buffer if(FAILED(hr)) { ::MessageBox(0, "D3DXGeneratePMesh() - FAILED", 0, 0); return false; } // set to original detail DWORD maxFaces = PMesh->GetMaxFaces(); PMesh->SetNumFaces(maxFaces);
3、此外我们还可以控制渐进网格的级别,就像下边
int numFaces = PMesh->GetNumFaces(); // Add a face, note the SetNumFaces() will automatically // clamp the specified value if it goes out of bounds. if( ::GetAsyncKeyState('A') & 0x8000f ) { // Sometimes we must add more than one face to invert // an edge collapse transformation PMesh->SetNumFaces( numFaces + 1 ); if( PMesh->GetNumFaces() == numFaces ) PMesh->SetNumFaces( numFaces + 2 ); } // Remove a face, note the SetNumFaces() will automatically // clamp the specified value if it goes out of bounds. if( ::GetAsyncKeyState('S') & 0x8000f ) PMesh->SetNumFaces( numFaces - 1 );
4、分批渲染
for(int i = 0; i < Mtrls.size(); i++) { // draw pmesh Device->SetMaterial( &Mtrls[i] ); Device->SetTexture(0, Textures[i]); PMesh->DrawSubset(i); // draw wireframe outline Device->SetMaterial(&d3d::YELLOW_MTRL); Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); PMesh->DrawSubset(i); Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); }