以先前文章中的 DirectX 框架为基础,写了一个导入.x文件生成渐进网格的例子。按下'A'键增加网格顶点数(不超过最大值) 按下 'S' 键减小顶点数 (不小于最小值)
代码清单:
- //
- //xfile.cpp
- //by tianzhihen
- //2008.10.19
- //VC8.0
- //
- #include "d3dUtility.h"
- #include <vector>
- IDirect3DDevice9* Device = 0 ;
- const int Width = 640;
- const int Height = 480;
- ID3DXMesh* SourceMesh = 0; //网格
- ID3DXPMesh* PMesh = 0; //渐进网格
- std::vector<D3DMATERIAL9> Mtrl(0); //材质
- std::vector<IDirect3DTexture9*> Textures(0); //纹理
- bool Setup()
- {
- HRESULT hr = 0;
- ID3DXBuffer* adjBuffer = 0; // 邻接缓存
- ID3DXBuffer* mtrlBuffer = 0; // 材质缓存
- DWORD numMtrls = 0; // 材质数量
- //
- // 从 .X 文件中加载数据到网格
- //
- hr = D3DXLoadMeshFromX(
- "bigship1.x",
- D3DXMESH_MANAGED,//托管内存池
- Device,
- &adjBuffer,
- &mtrlBuffer,
- 0,
- &numMtrls,
- &SourceMesh //目的网格地址
- );
- if(FAILED(hr))
- {
- ::MessageBox(0, "D3DXLoadMeshFromX() - FAILED", 0, 0);
- return false;
- }
- if (mtrlBuffer!=0&&numMtrls!=0)
- {
- //材质存在
- /*
- typedef struct D3DXMATERIAL {
- D3DMATERIAL9 MatD3D; //材质
- LPSTR pTextureFilename; //纹理地址
- } D3DXMATERIAL, *LPD3DXMATERIAL;
- */
- D3DXMATERIAL* mtrls =(D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
- for (int i=0;i<numMtrls;i++)
- {
- mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse; // .X 文件中没有定义材质的环境光分量
- Mtrl.push_back(mtrls[i].MatD3D);
- if (mtrls[i].pTextureFilename!=0)
- {
- IDirect3DTexture9* tex = 0;
- D3DXCreateTextureFromFile(Device,mtrls[i].pTextureFilename,&tex); //加载纹理
- Textures.push_back(tex);
- }
- else
- {
- Textures.push_back(0);
- }
- }
- }
- d3d::Release<ID3DXBuffer*>(mtrlBuffer);
- //
- // 优化网格数据
- //
- hr = SourceMesh->OptimizeInplace(
- D3DXMESHOPT_ATTRSORT|
- D3DXMESHOPT_COMPACT|
- D3DXMESHOPT_VERTEXCACHE,
- (DWORD*)adjBuffer->GetBufferPointer(),
- (DWORD*)adjBuffer->GetBufferPointer(),
- 0,0
- );
- if (FAILED(hr))
- {
- ::MessageBox(0,"OptimizeInplace() - FAILED",0,0);
- d3d::Release<ID3DXBuffer*>(adjBuffer);
- return E_FAIL;
- }
- //
- // 生成渐进网格
- //
- hr = D3DXGeneratePMesh(
- SourceMesh,
- (DWORD*)adjBuffer->GetBufferPointer(),
- 0,
- 0,
- 1,
- D3DXMESHSIMP_FACE,
- );
- d3d::Release<ID3DXMesh*>(SourceMesh);
- d3d::Release<ID3DXBuffer*>(adjBuffer);
- if(FAILED(hr))
- {
- ::MessageBox(0, "D3DXGeneratePMesh() - FAILED", 0, 0);
- return E_FAIL;
- }
- // 设置渐进网格初始面片值为最大
- DWORD maxFaces = PMesh->GetMaxFaces();
- PMesh->SetNumFaces(maxFaces);
- //纹理采样模式
- Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
- Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
- Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
- //
- // 设置光照
- //
- D3DXVECTOR3 dir(1.0f,-1.0f,1.0f);
- D3DXCOLOR col(1.0f,1.0f,1.0f,1.0f);
- D3DLIGHT9 light = d3d::InitDirectionalLight(&dir,&col);
- Device->SetLight(0,&light);
- Device->LightEnable(0,true);
- Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
- Device->SetRenderState(D3DRS_SPECULARENABLE, true);
- //
- // 设置取景变换矩阵
- //
- D3DXVECTOR3 pos(-8.0f, 4.0f, -12.0f);
- D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
- D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
- D3DXMATRIX V;
- D3DXMatrixLookAtLH(
- &V,
- &pos,
- &target,
- &up);
- Device->SetTransform(D3DTS_VIEW, &V);
- //
- // 设置投影矩阵
- //
- D3DXMATRIX proj;
- D3DXMatrixPerspectiveFovLH(
- &proj,
- D3DX_PI * 0.5f, // 90 - degree
- (float)Width / (float)Height,
- 1.0f,
- 1000.0f);
- Device->SetTransform(D3DTS_PROJECTION, &proj);
- return true;
- }
- void Cleanup()
- {
- d3d::Release<ID3DXPMesh*>(PMesh);
- for (int i=0;i<Textures.size();i++)
- {
- d3d::Release<IDirect3DTexture9*>(Textures[i]);
- }
- }
- bool Display(float timeDelta)
- {
- if (Device)
- {
- int numFaces = PMesh->GetNumFaces();
- if (::GetAsyncKeyState('A')&0x8000f)
- {
- //按下'A'键则增加面片数
- PMesh->SetNumFaces(numFaces+1);
- if(PMesh->GetNumFaces()==numFaces)
- PMesh->SetNumFaces(numFaces+2);
- }
- if(::GetAsyncKeyState('S')&0x8000f)
- {
- //按下'S'键则减少面片数
- PMesh->SetNumFaces(numFaces-1);
- }
- //
- // 绘制场景
- //
- Device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,0xffffffff,1.0f,0);
- Device->BeginScene();
- for (int i=0;i<Mtrl.size();i++)
- {
- //绘制模型
- Device->SetMaterial(&Mtrl[i]);
- Device->SetTexture(0,Textures[i]);
- PMesh->DrawSubset(i);
- // 绘制面片线框
- Device->SetMaterial(&d3d::YELLOW_MTRL);
- Device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
- PMesh->DrawSubset(i);
- Device->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
- }
- Device->EndScene();
- Device->Present(0,0,0,0);
- }
- return true;
- }
- //
- // WndProc
- //
- LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch( msg )
- {
- case WM_DESTROY:
- ::PostQuitMessage(0);
- break;
- case WM_KEYDOWN:
- if( wParam == VK_ESCAPE )
- ::DestroyWindow(hwnd);
- break;
- }
- return ::DefWindowProc(hwnd, msg, wParam, lParam);
- }
- //
- // WinMain
- //
- int WINAPI WinMain(HINSTANCE hinstance,
- HINSTANCE prevInstance,
- PSTR cmdLine,
- int showCmd)
- {
- if(!d3d::InitD3D(hinstance,
- Width, Height, true, D3DDEVTYPE_HAL, &Device))
- {
- ::MessageBox(0, "InitD3D() - FAILED", 0, 0);
- return 0;
- }
- if(!Setup())
- {
- ::MessageBox(0, "Setup() - FAILED", 0, 0);
- return 0;
- }
- d3d::EnterMsgLoop( Display );
- Cleanup();
- Device->Release();
- return 0;
- }