#include "main.h" //自定义全局变量 LPDIRECT3D9 g_D3D = NULL; LPDIRECT3DDEVICE9 g_D3DDevice = NULL; LPDIRECT3DVERTEXBUFFER9 g_VertexBuffer = NULL;//定点缓存 LPD3DXMESH g_pMesh = NULL;//网格模型对象 D3DMATERIAL9* g_pMeshMaterials = NULL;//网格模型材质 LPDIRECT3DTEXTURE9* g_pMeshTextures = NULL;//网格模型纹理 DWORD g_dNumMaterials = 0; //网格模型材质数量 int g_iScenedepth = 12; HWND g_Wnd = NULL; bool antiAlisa = false; //标志是否进行反锯齿 bool g_bShademode = false; //着色模式 int g_iFillmode = 1; //填充模式 //----------------------------------------------------------------------------- // Desc: 设置矩阵 //----------------------------------------------------------------------------- VOID SetupMatrices() { //建立一个绕X轴动态旋转的世界矩阵 D3DXMATRIX matWorld; D3DXMatrixIdentity( &matWorld );//矩阵格式化 D3DXMatrixRotationY( &matWorld, timeGetTime()/2000.0f ); //设置世界矩阵 g_D3DDevice->SetTransform( D3DTS_WORLD, &matWorld ); //建立并设置观察矩阵 D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-g_iScenedepth ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIX matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_D3DDevice->SetTransform( D3DTS_VIEW, &matView ); //建立并设置投影矩阵 D3DXMATRIX matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f ); g_D3DDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } //----------------------------------------------------------------------------- // Desc: 设置视区 //----------------------------------------------------------------------------- VOID SetupViewPort() { RECT rect; GetClientRect(g_Wnd,&rect); D3DVIEWPORT9 vp; vp.X = 0; vp.Y = 0; vp.Width = rect.right; vp.Height = rect.bottom; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; g_D3DDevice->SetViewport(&vp); } //-------------------------------------------------------------------- //DESC:D3D初始化 //-------------------------------------------------------------------- bool InitializeD3D(HWND hWnd, bool fullscreen) { //创建Direct3D 对象,该对象用来创建Direct3D设备对象 if( NULL == ( g_D3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return false; D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp,sizeof(d3dpp)); //全屏模式 if(fullscreen) { d3dpp.Windowed = FALSE; d3dpp.BackBufferWidth = WINDOW_WIDTH; d3dpp.BackBufferHeight = WINDOW_HEIGHT; } //窗口模式 else d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; //判断硬件是否支持4倍多重采样抗锯齿,并创建Direct3D设备对象 if(FAILED(g_D3D->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DMULTISAMPLE_4_SAMPLES,NULL) ) ) { MessageBox( hWnd, L"硬件不支持多采样抗锯齿!", L"AntiAlisa", 0 ); antiAlisa = false; if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_D3DDevice))) return false; } else { antiAlisa = true; if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_D3DDevice))) return false; } //设置剔出模式为不剔出任何面 g_D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); //启用深度测试 g_D3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE); //设置视区 SetupViewPort(); return true; } //-------------------------------------------------------------------- //DESC:创建场景图形 //-------------------------------------------------------------------- bool InitializeObjects() { LPD3DXBUFFER pD3DXMtrlBuffer; //存储网格模型材质的缓存区对象 //从磁盘加载文件加载网格模型 if(FAILED(D3DXLoadMeshFromX(L"..//Data//girl//girl.X", D3DXMESH_MANAGED, g_D3DDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dNumMaterials, &g_pMesh))) { MessageBox(NULL, L"没有找到模型文件girl.x", L"MESH", MB_OK); return false; } //从网格模型中提取材质属性和纹理文件名 D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); g_pMeshMaterials = new D3DMATERIAL9[g_dNumMaterials]; if( g_pMeshMaterials == NULL ) return false; g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dNumMaterials]; if( g_pMeshTextures == NULL ) return false; //逐行提取网络模型材质属性和纹理文件名 for(DWORD i =0; i<g_dNumMaterials; i++) { //材质属性 g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D; //设置模型材料的环境反光系数,因为模型材料本身没有设置环境反光系数 g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse; g_pMeshTextures[i] = NULL; if(d3dxMaterials[i].pTextureFilename != NULL && strlen(d3dxMaterials[i].pTextureFilename) > 0) { //获取纹理文件名 WCHAR filename[100]; RemovePathFromFileName(d3dxMaterials[i].pTextureFilename, filename); WCHAR g_wMeshPath[256] = L"..//Data//girl//"; lstrcat(g_wMeshPath,filename); //创建纹理 if(FAILED(D3DXCreateTextureFromFile(g_D3DDevice, g_wMeshPath, &g_pMeshTextures[i]))) { MessageBox(NULL, L"没有找到纹理文件", L"mesh", MB_OK); } } } //释放在加载模型文件时创建的保存模型材质的纹理数据的缓冲区对象 pD3DXMtrlBuffer->Release(); return true; } //-------------------------------------------------------------------- //DESC:设置材质和灯光 //-------------------------------------------------------------------- void setLight() { //设置材质 D3DMATERIAL9 mtrl; ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) ); mtrl.Specular.r = 0.5f; mtrl.Specular.g = 0.5f; mtrl.Specular.b = 0.5f; mtrl.Specular.a = 0.5f; mtrl.Power = 20;//镜面反射强度 mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f; mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; //g_D3DDevice->SetMaterial( &mtrl ); //g_D3DDevice->SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL ); //设置灯光 D3DLIGHT9 light; ZeroMemory( &light, sizeof(D3DLIGHT9) ); light.Type = D3DLIGHT_DIRECTIONAL;//灯光类型为方向光线 D3DXVECTOR3 vecDir; vecDir = D3DXVECTOR3(0.5f, 0.0f, 0.5f);//灯光方向 D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir ); light.Diffuse.r = 1.0f; light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; light.Diffuse.a = 1.0f; light.Specular.r = 1.0f; light.Specular.g = 1.0f; light.Specular.b = 1.0f; light.Specular.a = 1.0f; light.Range = 1000.0f; light.Falloff = 0; light.Attenuation0 = 1; light.Attenuation1 = 0; light.Attenuation2 = 0; vecDir = D3DXVECTOR3(cosf(timeGetTime()/350.0f), 1.0f, sinf(timeGetTime()/350.0f) ); g_D3DDevice->SetLight( 0, &light ); g_D3DDevice->LightEnable( 0, TRUE ); g_D3DDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); g_D3DDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE ); //设置环境光 g_D3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(80,80,80)); } //-------------------------------------------------------------------- //DESC:场景渲染 //-------------------------------------------------------------------- void RenderScene() { //设置是否启用图形反锯齿 if(antiAlisa) g_D3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,TRUE); else g_D3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS,FALSE); //设置着色模式 if(g_bShademode) g_D3DDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );//平面着色模式 else g_D3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD );//格劳德着色模式 //设置填充模式 if( g_iFillmode == 1 ) g_D3DDevice->SetRenderState(D3DRS_FILLMODE , D3DFILL_SOLID );//面填充 if( g_iFillmode == 2 ) g_D3DDevice->SetRenderState(D3DRS_FILLMODE , D3DFILL_WIREFRAME );//线填充 if( g_iFillmode ==3 ) g_D3DDevice->SetRenderState(D3DRS_FILLMODE , D3DFILL_POINT );//点填充个 //设置材质和灯光 setLight(); //clear the backbuffer. g_D3DDevice->Clear( 0, NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); //准备在后台缓存区绘制图形 if( SUCCEEDED( g_D3DDevice->BeginScene() ) )//开始渲染 { //设置矩阵 SetupMatrices(); //逐个渲染场景 for(DWORD i=0; i<g_dNumMaterials;i++) { //设置材质和纹理 g_D3DDevice->SetMaterial(&g_pMeshMaterials[i]); g_D3DDevice->SetTexture(0, g_pMeshTextures[i]); //渲染模型 g_pMesh->DrawSubset(i); } //g_D3DDevice->SetStreamSource( 0, g_VertexBuffer, 0, sizeof( CUSTOMVERTEX ) ); //g_D3DDevice->SetFVF( D3DFVF_VERTEX ); //g_D3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2*50-2 ); g_D3DDevice->EndScene();//结束渲染 } //将在后台缓冲区绘制的图形提交到前台缓冲区显示 g_D3DDevice->Present(NULL, NULL, NULL, NULL); } //-------------------------------------------------------------------- //DESC:资源释放 //-------------------------------------------------------------------- void Shutdown() { //释放网络模型材质 if( g_pMeshMaterials != NULL ) delete[] g_pMeshMaterials; //释放网格模型纹理 if( g_pMeshTextures ) { for( DWORD i = 0; i < g_dNumMaterials; i++ ) { if( g_pMeshTextures[i] ) g_pMeshTextures[i]->Release(); } delete[] g_pMeshTextures; } //释放网格模型对象 if( g_pMesh != NULL ) g_pMesh->Release(); //释放DIRECTX3D设备对象 if(g_D3DDevice != NULL) g_D3DDevice ->Release(); //释放DIRECTX3D对象 if(g_D3D != NULL) g_D3D->Release(); } //-------------------------------------------------------------------- //DESC:从绝对路径提取文件名 //-------------------------------------------------------------------- void RemovePathFromFileName(LPSTR fullPath, LPWSTR fileName) { //先将fullPath的类型变换为LPWSTR WCHAR wszBuf[MAX_PATH]; MultiByteToWideChar( CP_ACP, 0, fullPath, -1, wszBuf, MAX_PATH ); wszBuf[MAX_PATH-1] = L'\0'; WCHAR* wszFullPath = wszBuf; //从绝对路径中提取文件名 LPWSTR pch=wcsrchr(wszFullPath,'\\'); if (pch) lstrcpy(fileName, ++pch); else lstrcpy(fileName, wszFullPath); } //-------------------------------------------------------------------- //DESC:消息处理 //-------------------------------------------------------------------- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: Shutdown(); PostQuitMessage(0); break; case WM_LBUTTONDOWN: g_bShademode = !g_bShademode; return 0; case WM_RBUTTONDOWN: if( g_iFillmode == 3 ) g_iFillmode = 1; else g_iFillmode++; return 0 ; //鼠标滚轮事件 case 0x020A: { int a = (short)HIWORD(wParam); if(a == -120 && g_iScenedepth < 30.0f) g_iScenedepth = g_iScenedepth + 1.0f; else if(a == 120 && g_iScenedepth > 3.0f) g_iScenedepth = g_iScenedepth - 1.0f; return 0; } default: return DefWindowProc(hWnd, message, wParam, lParam); break; } return 0; } //-------------------------------------------------------------------- //DESC:入口函数 //-------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, WINDOW_CLASS, NULL }; if (!RegisterClassEx(&wcex)) { MessageBox(NULL, (L"Call to RegisterClassEx failed!"), (L"Win32 Guided Tour"), NULL); return 1; } // Create the application`s window class HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, GetDesktopWindow(), NULL, hInstance, NULL ); if (!hWnd) { MessageBox(NULL, (L"Call to CreateWindow failed!"), (L"Win32 Guided Tour"), NULL); return 1; } g_Wnd = hWnd; //Initalize Direct3D if(InitializeD3D(hWnd,WINDOWSMODE)) { if(InitializeObjects())//加载模型 { //show the window ShowWindow(hWnd,SW_SHOWDEFAULT); UpdateWindow(hWnd); // Main message loop: MSG msg; ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { RenderScene(); } } } } // Unregister our window. UnregisterClass(WINDOW_CLASS, wcex.hInstance); return 0 ; }