ZFXDream.cpp
上传用户:junlon
上传日期:2022-01-05
资源大小:39075k
文件大小:19k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. // ZFXDream.cpp : 定义应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include "d3dUtility.h"
  5. #include "particle.h"
  6. #include "ZFXDream.h"
  7. #include "zfxCamera.h"
  8. #include "zfxFrustum.h"
  9. #include "zfxLODTerrain.h"
  10. #include "zfxMeshX.h"
  11. #include "zfxBillBoard.h"
  12. #include "Vfw.h"    // Video capture head file
  13. #define MAX_LOADSTRING 100
  14. #define FULL_SCREEN
  15. #define WALKLENTGH 5.0f
  16. #define AVI_CAPTURE
  17. // 全局变量:
  18. HINSTANCE hInst; // 当前实例
  19. HWND g_hWnd;
  20. TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
  21. TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
  22. HWND hWnd_Avi;
  23. D3DFILLMODE g_fillMode = D3DFILL_SOLID;
  24. BOOL g_bFog = TRUE;
  25. LPDIRECT3D9 g_pD3D = NULL;
  26. CZFXCamera g_camera;                   // camera
  27. LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
  28. LPDIRECTINPUT8    g_pDI = NULL;       // The DirectInput object
  29. LPDIRECTINPUTDEVICE8 g_pKeyboard = NULL; // The keyboard device
  30. LPDIRECTINPUTDEVICE8 g_pMouse = NULL;    // The mouse device
  31. LPD3DXFONT g_pFont = NULL;
  32. BOOL g_bKey_F = FALSE; // F键松开后,值变为FALSE,防止一次按下键后程序响应多次
  33. BOOL g_bKey_Q = FALSE; // F键松开后,值变为FALSE,防止一次按下键后程序响应多次
  34. CZFXLODTerrain* g_pLODTerrain = NULL;
  35. CZFXMesh* g_pSkyBoxMesh = NULL;
  36. CZFXMesh* g_pSu27 = NULL;
  37. ////// 雨雪粒子系统。。。/////////////////////////////
  38. #define SNOW_OR_RAIN
  39. //#define RENDER_SNOW
  40. using namespace ParticleSystem;
  41. #ifdef RENDER_SNOW
  42. typedef CSnowSystem CPSystem;
  43. #define NUMPERBATCH 200
  44. #define NUMTOTAL    5000
  45. #else
  46. typedef CRainSystem CPSystem;
  47. #define NUMPERBATCH 100
  48. #define NUMTOTAL    3000
  49. #endif
  50. CPSystem* g_pPSystem = NULL;     //Paticle system
  51. ////////////////////////////////////////////////////
  52. ////////BillBoard for Trees..........////////////////
  53. #define TREE_NUM_TOTAL 32
  54. #define TREEMGR_NUM_TOTAL 4
  55. CZFXBillBoardMgr* g_pTreeMgrArray; //
  56. CZFXBillBoard* g_pTreeArray;
  57. ////////////////////////////////////////////////////
  58. BOOL InitD3D(HWND hWnd);
  59. BOOL InitDInput(HWND hWnd);
  60. BOOL InitDXFont();
  61. BOOL InitTerrain();
  62. BOOL InitPSystem();
  63. BOOL InitTrees();
  64. void OnRender();
  65. void RenderFPS();
  66. void UpdatePSystem();
  67. void GetDirectInput(HWND hWnd);
  68. // 此代码模块中包含的函数的前向声明:
  69. ATOM MyRegisterClass(HINSTANCE hInstance);
  70. BOOL InitInstance(HINSTANCE, int);
  71. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  72. LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
  73. int APIENTRY _tWinMain(HINSTANCE hInstance,
  74.    HINSTANCE hPrevInstance,
  75.    LPTSTR    lpCmdLine,
  76.    int       nCmdShow)
  77. {
  78. // TODO: 在此放置代码。
  79. MSG msg;
  80. HACCEL hAccelTable;
  81. // 初始化全局字符串
  82. LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
  83. LoadString(hInstance, IDC_ZFXDREAM, szWindowClass, MAX_LOADSTRING);
  84. MyRegisterClass(hInstance);
  85. // 执行应用程序初始化:
  86. if (!InitInstance (hInstance, nCmdShow)) 
  87. {
  88. return FALSE;
  89. }
  90. hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_ZFXDREAM);
  91. // 主消息循环:
  92. while (GetMessage(&msg, NULL, 0, 0)) 
  93. {
  94. if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  95. {
  96. GetDirectInput(msg.hwnd);
  97. TranslateMessage(&msg);
  98. DispatchMessage(&msg);
  99. }
  100. }
  101. return (int) msg.wParam;
  102. }
  103. //
  104. //  函数: MyRegisterClass()
  105. //
  106. //  目的: 注册窗口类。
  107. //
  108. //  注释: 
  109. //
  110. //    仅当希望在已添加到 Windows 95 的
  111. //    “RegisterClassEx”函数之前此代码与 Win32 系统兼容时,
  112. //    才需要此函数及其用法。调用此函数
  113. //    十分重要,这样应用程序就可以获得关联的
  114. //   “格式正确的”小图标。
  115. //
  116. ATOM MyRegisterClass(HINSTANCE hInstance)
  117. {
  118. WNDCLASSEX wcex;
  119. wcex.cbSize = sizeof(WNDCLASSEX); 
  120. wcex.style = CS_HREDRAW | CS_VREDRAW;
  121. wcex.lpfnWndProc = (WNDPROC)WndProc;
  122. wcex.cbClsExtra = 0;
  123. wcex.cbWndExtra = 0;
  124. wcex.hInstance = hInstance;
  125. wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_ZFXDREAM);
  126. wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  127. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  128. wcex.lpszMenuName = (LPCTSTR)IDC_ZFXDREAM;
  129. wcex.lpszClassName = szWindowClass;
  130. wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
  131. return RegisterClassEx(&wcex);
  132. }
  133. //
  134. //   函数: InitInstance(HANDLE, int)
  135. //
  136. //   目的: 保存实例句柄并创建主窗口
  137. //
  138. //   注释: 
  139. //
  140. //        在此函数中,我们在全局变量中保存实例句柄并
  141. //        创建和显示主程序窗口。
  142. //
  143. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  144. {
  145. HWND hWnd;
  146. hInst = hInstance; // 将实例句柄存储在全局变量中
  147. hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  148. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
  149. if (!hWnd)
  150. {
  151. return FALSE;
  152. }
  153. g_hWnd = hWnd;
  154. #ifdef AVI_CAPTURE
  155. hWnd_Avi = capCreateCaptureWindow("My Own Capture Window", WS_CHILD | WS_VISIBLE, 
  156. 0, 0, 160, 120, hWnd, 1376);
  157. capDriverConnect(hWnd_Avi, 0/*capture index*/);
  158. capFileSetCaptureFile(hWnd_Avi, "capture.avi");
  159. #endif
  160. if(FALSE == InitD3D(hWnd))
  161. return FALSE;
  162. if(FALSE == InitDInput(hWnd))
  163. return FALSE;
  164. if(FALSE == InitDXFont())
  165. return FALSE;
  166. if(FALSE == InitTerrain())
  167. return FALSE;
  168. if(FALSE == InitPSystem())
  169. return FALSE;
  170. if(FALSE == InitTrees())
  171. return FALSE;
  172. //SetTimer(hWnd, 0, 50, NULL);
  173. ShowWindow(hWnd, SW_MAXIMIZE);
  174. UpdateWindow(hWnd);
  175. #ifdef AVI_CAPTURE
  176. SetTimer(hWnd, 0, 2000, NULL);
  177. capCaptureSequence(hWnd_Avi);
  178. #endif
  179. return TRUE;
  180. }
  181. //
  182. //  函数: WndProc(HWND, unsigned, WORD, LONG)
  183. //
  184. //  目的: 处理主窗口的消息。
  185. //
  186. //  WM_COMMAND - 处理应用程序菜单
  187. //  WM_PAINT - 绘制主窗口
  188. //  WM_DESTROY - 发送退出消息并返回
  189. //
  190. //
  191. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  192. {
  193. int wmId, wmEvent;
  194. /*PAINTSTRUCT ps;
  195. HDC hdc;*/
  196. switch (message) 
  197. {
  198. case WM_COMMAND:
  199. wmId    = LOWORD(wParam); 
  200. wmEvent = HIWORD(wParam); 
  201. // 分析菜单选择:
  202. switch (wmId)
  203. {
  204. case IDM_ABOUT:
  205. DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
  206. break;
  207. case IDM_EXIT:
  208. DestroyWindow(hWnd);
  209. break;
  210. default:
  211. return DefWindowProc(hWnd, message, wParam, lParam);
  212. }
  213. break;
  214. case WM_PAINT:
  215. /*hdc = BeginPaint(hWnd, &ps);*/
  216. // TODO: 在此添加任意绘图代码...
  217. OnRender();
  218. //GetDirectInput(hWnd);
  219. //EndPaint(hWnd, &ps);
  220. break;
  221. case WM_TIMER:
  222. #ifdef AVI_CAPTURE
  223. capCaptureStop(hWnd_Avi);
  224. capDriverDisconnect(hWnd_Avi); 
  225. KillTimer(hWnd, 0);
  226. #endif
  227. break;
  228. case WM_DESTROY:
  229. PostQuitMessage(0);
  230. break;
  231. case WM_CLOSE:
  232. //delete g_pLODTerrain;
  233. //if(g_pPSystem != NULL)
  234. // delete g_pPSystem;
  235. SAFE_DELETE(g_pPSystem);
  236. SAFE_DELETE(g_pLODTerrain);
  237. SAFE_DELETE(g_pSkyBoxMesh);
  238. SAFE_DELETE(g_pSu27);
  239. delete [] g_pTreeMgrArray;
  240. delete [] g_pTreeArray;
  241. SAFE_RELEASE(g_pMouse);
  242. SAFE_RELEASE(g_pKeyboard);
  243. SAFE_RELEASE(g_pDI);
  244. SAFE_RELEASE(g_pFont);
  245. SAFE_RELEASE(g_pd3dDevice);
  246. DefWindowProc(hWnd, message, wParam, lParam);
  247. break;
  248. default:
  249. return DefWindowProc(hWnd, message, wParam, lParam);
  250. }
  251. return 0;
  252. }
  253. BOOL InitD3D(HWND hWnd)
  254. {
  255. // Create D3D device
  256. if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION )))
  257. return FALSE;
  258. D3DDISPLAYMODE d3ddm;
  259. if( FAILED( g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddm )))
  260. return FALSE;//得到当前的显示模式
  261. D3DPRESENT_PARAMETERS d3dpp;
  262. ZeroMemory( &d3dpp, sizeof(d3dpp));
  263. #ifdef FULL_SCREEN
  264. d3dpp.Windowed = FALSE;
  265. d3dpp.hDeviceWindow = hWnd;
  266. d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
  267. d3dpp.BackBufferCount = 1; //有一个后台缓存
  268. d3dpp.BackBufferWidth = d3ddm.Width;//屏幕宽度为800像素
  269. d3dpp.BackBufferHeight = d3ddm.Height;//屏幕长度为600像素
  270. d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  271. #else
  272. d3dpp.Windowed = TRUE;
  273. d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  274. #endif
  275. d3dpp.BackBufferFormat = d3ddm.Format;
  276. d3dpp.EnableAutoDepthStencil = TRUE;
  277. d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  278. if( FAILED( g_pD3D -> CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
  279. D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice)))
  280. return FALSE;
  281. // Init Meshs/////////////////////////////////////////////////////////////////////
  282. // 天空体初始化
  283. g_pSkyBoxMesh = new CZFXMesh();
  284. if(FAILED(g_pSkyBoxMesh->LoadMeshFromFile(g_pd3dDevice, "mesh\skybox.x", true)))
  285. {
  286. MessageBoxW(hWnd, L"加载天空体失败", L"Initialization Failed", MB_OK);
  287. g_pSkyBoxMesh = NULL;
  288. }
  289. // 飞机模型初始化
  290. g_pSu27 = new CZFXMesh();
  291. if(FAILED(g_pSu27->LoadMeshFromFile(g_pd3dDevice, "mesh\su27.x", true)))
  292. {
  293. MessageBoxW(hWnd, L"加载飞机模型失败", L"Initialization Failed", MB_OK);
  294. g_pSu27 = NULL;
  295. }
  296. return TRUE;
  297. }
  298. BOOL InitDInput(HWND hWnd)
  299. {
  300. // Create DirectInput device
  301. // Keyboard Input device
  302. HRESULT hr;
  303. if( FAILED( hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&g_pDI, NULL )))
  304. return FALSE;
  305. if( FAILED( hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pKeyboard, NULL )))
  306. return FALSE;
  307. if( FAILED( hr = g_pKeyboard->SetDataFormat(&c_dfDIKeyboard)))
  308. return FALSE;
  309. if( FAILED( hr = g_pKeyboard->SetCooperativeLevel( hWnd, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE )))
  310. return FALSE;
  311. g_pKeyboard->Acquire();
  312. // Mouse Input device
  313. if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL )))
  314. return FALSE;
  315. if( FAILED( hr = g_pMouse->SetDataFormat(&c_dfDIMouse2)))
  316. return FALSE;
  317. if( FAILED( hr = g_pMouse->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND )))
  318. return FALSE;
  319. g_pMouse->Acquire();
  320. return TRUE;
  321. // End create DInput device
  322. }
  323. BOOL InitDXFont()
  324. {
  325. //创建字体
  326. D3DXFONT_DESC fontDesc;
  327. ZeroMemory( &fontDesc, sizeof(D3DXFONT_DESC) );
  328. fontDesc.Height = 15;
  329. fontDesc.Width = 8;
  330. fontDesc.Weight = 500;
  331. fontDesc.Italic = TRUE;
  332. strcpy( fontDesc.FaceName, "Times New Roman");
  333. if( SUCCEEDED( D3DXCreateFontIndirect( g_pd3dDevice, &fontDesc, &g_pFont )))
  334. return TRUE;
  335. else
  336. return FALSE;
  337. }
  338. BOOL InitTerrain()
  339. {
  340. // 加载地形数据
  341. try
  342. {
  343. g_pLODTerrain = new CZFXLODTerrain("map\perlin1025-1.map");
  344. }
  345. catch(...)
  346. {
  347. return FALSE;
  348. }
  349. g_pLODTerrain->LoadTextureFromFile( g_pd3dDevice, "texture\lowTexture.jpg", 
  350. "texture\highTexture.jpg" );
  351. g_pLODTerrain->InitQuadTree();
  352. g_pLODTerrain->SetDimesion( 3000.0f, 3000.0f, D3DXVECTOR2(0, 0) );
  353. if(SUCCEEDED(g_pLODTerrain->InitShader(g_pd3dDevice)))
  354. return TRUE;
  355. else
  356. return FALSE;
  357. }
  358. //粒子系统初始化
  359. BOOL InitPSystem()
  360. {
  361. BoundingBox boundingBox( D3DXVECTOR3(-1500.0f, 0.0f, -1500.0f), D3DXVECTOR3(1500.0f, 750.0f, 1500.0f) );
  362. //第一次只加入NUMPERBATCH个粒子,之后没渲染一帧增加NUMPERBATCH个,直至粒子数达到NUMTOTAL
  363. #ifdef RENDER_SNOW
  364. g_pPSystem = new CPSystem(&boundingBox, NUMPERBATCH, 5);
  365. LPCTSTR texFileName = "texture\snowball.bmp";//纹理图
  366. #else
  367. g_pPSystem = new CPSystem(&boundingBox, NUMPERBATCH, 20);
  368. LPCTSTR texFileName = "texture\raindrop.bmp";//纹理图
  369. #endif
  370. if(!g_pPSystem->init(g_pd3dDevice, texFileName))
  371. {
  372. return FALSE;
  373. }
  374. return TRUE;
  375. }
  376. BOOL InitTrees()
  377. {
  378. g_pTreeArray = new CZFXBillBoard[TREE_NUM_TOTAL];
  379. D3DXVECTOR3 posVec[TREE_NUM_TOTAL];
  380. FILE* pFile = fopen("zfx.ini", "r");
  381. if(NULL == pFile)
  382. {
  383. MessageBoxW(g_hWnd, L"Open zfx.ini Failed", L"Initialization Failure", MB_OK);
  384. return FALSE;
  385. }
  386. for(int i=0;i<TREE_NUM_TOTAL;i++)
  387. {
  388. fscanf(pFile, "%f, %f", &posVec[i].x, &posVec[i].z);
  389. }
  390. fclose(pFile);
  391. for(int i=0;i<TREE_NUM_TOTAL;i++)
  392. {
  393. posVec[i].y = g_pLODTerrain->GetTerrainElev(posVec[i].x, posVec[i].z);
  394. g_pTreeArray[i].CreateBoard(g_pd3dDevice, posVec[i], 100, 100);
  395. }
  396. g_pTreeMgrArray = new CZFXBillBoardMgr[TREEMGR_NUM_TOTAL];
  397. if(FAILED(g_pTreeMgrArray[0].LoadTextureFromFile(g_pd3dDevice, "texture\Tree1.dds")))
  398. {
  399. MessageBoxW(g_hWnd, L"加载树纹理失败", L"Initialization Failure", MB_OK);
  400. return FALSE;
  401. }
  402. if(FAILED(g_pTreeMgrArray[1].LoadTextureFromFile(g_pd3dDevice, "texture\Tree2.dds")))
  403. {
  404. MessageBoxW(g_hWnd, L"加载树纹理失败", L"Initialization Failure", MB_OK);
  405. return FALSE;
  406. }
  407. if(FAILED(g_pTreeMgrArray[2].LoadTextureFromFile(g_pd3dDevice, "texture\Tree3.dds")))
  408. {
  409. MessageBoxW(g_hWnd, L"加载树纹理失败", L"Initialization Failure", MB_OK);
  410. return FALSE;
  411. }
  412. if(FAILED(g_pTreeMgrArray[3].LoadTextureFromFile(g_pd3dDevice, "texture\Tree4.dds")))
  413. {
  414. MessageBoxW(g_hWnd, L"加载树纹理失败", L"Initialization Failure", MB_OK);
  415. return FALSE;
  416. }
  417. for(int i=0;i<TREE_NUM_TOTAL;i++)
  418. {
  419. int j = i%4;
  420. g_pTreeMgrArray[j].AddBillBoard(g_pTreeArray[i]);
  421. }
  422. return TRUE;
  423. }
  424. void OnRender()
  425. {
  426. // pre rendering
  427. // 设置世界矩阵
  428. D3DXMATRIX matWorld;
  429. D3DXMatrixIdentity(&matWorld);
  430. // 设置视口矩阵
  431. D3DXMATRIX matView;
  432. // 根据地形的X,Y坐标来获取地形的高度,再拔高10.0f,即相机的高度
  433. g_camera.SetPosY( g_pLODTerrain->GetTerrainElev( g_camera.GetPosX(), g_camera.GetPosZ()) + 50.0f/*200.0f*/);
  434. g_camera.GetViewMatrix( &matView );
  435. g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  436. // 设置投影矩阵
  437. D3DXMATRIX matProj;
  438. D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/2, 1.0f, 0.1f, 3500.0f );
  439. g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  440. // 设置填充模式
  441. g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, g_fillMode );
  442. // set render state
  443. g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  444. g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  445. // 创建地形
  446. g_pLODTerrain->CreateTerrain( g_pd3dDevice, &g_camera );
  447. g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0);
  448. if( SUCCEEDED(g_pd3dDevice->BeginScene()) )
  449. {
  450. // 渲染天空体
  451. if(g_pSkyBoxMesh != NULL)
  452. {
  453. D3DXMATRIX skyBoxMat;
  454. D3DXMatrixIdentity(&skyBoxMat);
  455. D3DXMatrixScaling(&skyBoxMat, 1.875f*2, 2, 1.875f*2);
  456. g_pd3dDevice->SetTransform(D3DTS_WORLD, &skyBoxMat);
  457. g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false );
  458. g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
  459. g_pSkyBoxMesh->OnRender(g_pd3dDevice);
  460. g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  461. }
  462. // 渲染飞机模型
  463. if(g_pSu27 != NULL)
  464. {
  465. D3DXMATRIX Su27Mat;
  466. D3DXMatrixIdentity(&Su27Mat);
  467. D3DXMatrixTranslation(&Su27Mat, 200, 300, 200);
  468. D3DXMATRIX matScale, matRot, matProduct;
  469. D3DXMatrixScaling(&matScale, 3, 3, 3);
  470. D3DXMatrixRotationX(&matRot, -1.57f);
  471. D3DXMatrixMultiply(&matProduct, &matScale, &matRot);
  472. D3DXMatrixMultiply(&Su27Mat, &matProduct, &Su27Mat);
  473. //g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0xffffffff);
  474. //D3DLIGHT9 Su27Light;
  475. //ZeroMemory(&Su27Light, sizeof(D3DLIGHT9));
  476. //Su27Light.Type = D3DLIGHT_DIRECTIONAL;
  477. //Su27Light.Diffuse.r = Su27Light.Diffuse.g = Su27Light.Diffuse.b = 0.3f;
  478. //Su27Light.Diffuse.a = 1.0f;
  479. //Su27Light.Direction = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
  480. ///*g_pd3dDevice->SetLight(0, &Su27Light);
  481. //g_pd3dDevice->LightEnable(0, TRUE);*/
  482. g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, true );
  483. g_pd3dDevice->SetTransform(D3DTS_WORLD, &Su27Mat);
  484. g_pSu27->OnRender(g_pd3dDevice);
  485. g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
  486. }
  487. // 渲染地形
  488. g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
  489. g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  490. g_pLODTerrain->RenderTerrain(g_pd3dDevice, g_bFog);
  491. // 渲染树
  492. for(int i=0;i<TREEMGR_NUM_TOTAL;i++)
  493. {
  494. g_pTreeMgrArray[i].UpdateBoardOrient(&g_camera);
  495. g_pTreeMgrArray[i].OnRender(g_pd3dDevice);
  496. }
  497. // 渲染粒子系统
  498. g_pPSystem->render();
  499. UpdatePSystem();
  500. // 写字
  501. RenderFPS();
  502. g_pd3dDevice->EndScene();
  503. }
  504. g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
  505. }
  506. void RenderFPS()
  507. {
  508. //用于渲染侦FPS
  509. static int tmLastTime = GetTickCount();
  510. int tmNow = GetTickCount();
  511. //用于计算渲染FPS
  512. static int nFrameCount = 0;
  513. static int nFPS = 0;
  514. if(tmNow - tmLastTime > 1000)
  515. {
  516. //计算FPS
  517. tmLastTime = tmNow;
  518. nFPS = nFrameCount;
  519. nFrameCount = 0;
  520. }
  521. nFrameCount ++;
  522. // 输出字符串(FPS = ?, Triangles = ?)
  523. char str[500];
  524. RECT rect;
  525. rect.left = rect.top = 10;
  526. rect.bottom = 46;
  527. rect.right = 260;
  528. sprintf(str, "Current FPS:%d  Triangles: %d  Current Paticle num: %d  View:x =%0.2f, y=%0.2f, z=%0.2f Please press F and Q to toggle Fog and WireFrame mode", 
  529. nFPS, g_pLODTerrain->GetTriangles(), g_pPSystem->getParticleNum(), g_camera.GetPosX(),
  530. g_camera.GetPosY(), g_camera.GetPosZ());
  531. g_pFont->DrawTextA(NULL, str, (int)strlen(str), &rect, DT_LEFT|DT_NOCLIP|DT_WORDBREAK, 0xffffff00);
  532. }
  533. // 更新粒子系统
  534. void UpdatePSystem()
  535. {
  536. #ifdef RENDER_SNOW
  537. g_pPSystem->update(0.3f);//每帧更新一个恒定值,0.3秒
  538. #else
  539. g_pPSystem->update(1.3f);//每帧更新一个恒定值,0.3秒
  540. #endif
  541. //如粒子数未超过总的粒子数--NUMTOTAL,新加入一批粒子
  542. //#ifndef RENDER_SNOW
  543. if( NUMTOTAL > g_pPSystem->getParticleNum() )
  544. {
  545. for(int i=0;i<NUMPERBATCH;i++)
  546. g_pPSystem->addParticle();
  547. }
  548. //#endif
  549. }
  550. void GetDirectInput(HWND hWnd)
  551. {
  552. // 获取鼠标输入
  553. int nMouseReAcquireTimes, nKeybdReAcquireTimes;
  554. nMouseReAcquireTimes = nKeybdReAcquireTimes = 0;
  555. DIMOUSESTATE2 dims2;
  556. HRESULT hr;
  557. if( g_pMouse == NULL )
  558. {
  559. MessageBox(hWnd, "Mouse device lost", "DirectInput exception", MB_OK);
  560. return;
  561. }
  562. while( FAILED( hr = g_pMouse->GetDeviceState(sizeof(DIMOUSESTATE2), &dims2)))
  563. {
  564. g_pMouse->Acquire();
  565. }
  566. g_camera.Yaw( dims2.lX * 0.005f );
  567. g_camera.Pitch( dims2.lY * -0.005f );
  568. // 获取键盘输入
  569. BYTE diks[256];   // DirectInput keyboard state buffer 
  570. if( g_pKeyboard == NULL )
  571. {
  572. MessageBox(hWnd, "Keyboard device lost", "DirectInput exception", MB_OK);
  573. return;
  574. }
  575. while( DI_OK != g_pKeyboard->GetDeviceState( sizeof(diks), diks ))
  576. {
  577. g_pKeyboard->Acquire();
  578. }
  579. // 按下ESC键,退出程序
  580. if( diks[DIK_ESCAPE] & 0x80 )
  581. SendMessage(hWnd, WM_CLOSE, 0, 0);
  582. // 按下 A 键,摄像机左移
  583. if( diks[DIK_A] | diks[DIK_LEFT] & 0x80 )
  584. g_camera.Walk( -WALKLENTGH, 0 );
  585. // 按下 D 键,摄像机右移
  586. if( diks[DIK_D] | diks[DIK_RIGHT] & 0x80 )
  587. g_camera.Walk( WALKLENTGH, 0 );
  588. // 按下 W 键,摄像机前移
  589. if( diks[DIK_W] | diks[DIK_UP] & 0x80 )
  590. g_camera.Walk( 0, WALKLENTGH );
  591. // 按下 S 键,摄像机后移
  592. if( diks[DIK_S] | diks[DIK_DOWN] & 0x80 )
  593. g_camera.Walk( 0, -WALKLENTGH );
  594. // 渲染模式切换
  595. if( diks[DIK_Q] & 0x80 && !g_bKey_Q)
  596. {
  597. g_bKey_Q = TRUE;
  598. if(g_fillMode == D3DFILL_SOLID)
  599. g_fillMode = D3DFILL_WIREFRAME;
  600. else
  601. g_fillMode = D3DFILL_SOLID;
  602. }
  603. if(!(diks[DIK_Q] & 0x80))
  604. {
  605. g_bKey_Q = FALSE;
  606. }
  607. // 启用雾化切换
  608. if( diks[DIK_F] &0x80  && !g_bKey_F)
  609. {
  610. g_bKey_F = TRUE;
  611. g_bFog = !g_bFog;
  612. }
  613. if(!(diks[DIK_F] &0x80))
  614. {
  615. g_bKey_F = FALSE;
  616. }
  617. // 更新窗口
  618. SendMessage(hWnd, WM_PAINT, 0, 0);
  619. }
  620. // “关于”框的消息处理程序。
  621. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  622. {
  623. switch (message)
  624. {
  625. case WM_INITDIALOG:
  626. return TRUE;
  627. case WM_COMMAND:
  628. if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
  629. {
  630. EndDialog(hDlg, LOWORD(wParam));
  631. return TRUE;
  632. }
  633. break;
  634. }
  635. return FALSE;
  636. }