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

DirextX编程

开发平台:

Visual C++

  1. // camera.cpp : 定义应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include "camera.h"
  5. #include "D3DEnvClass.h"
  6. #include "zfxCamera.h"
  7. #define MAX_LOADSTRING 100
  8. // 自定义顶点结构体
  9. typedef struct tagCUSTOMVERTEX{
  10. D3DXVECTOR3 position; // The position of the vertex.
  11. D3DCOLOR    color;    // The color
  12. }CUSTOMVERTEX;
  13. // 自定义顶点格式
  14. #define D3DFVF_CUSTOMVERTEX  D3DFVF_XYZ|D3DFVF_DIFFUSE
  15. // 全局变量:
  16. HINSTANCE hInst; // 当前实例
  17. TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
  18. TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
  19. // 全局变量,D3D环境对象
  20. CZFXD3DEnv g_d3dEnv;
  21. CZFXCamera g_camera;
  22. IDirect3DVertexBuffer9* g_pVB1;          //Vertex Buffer, 圆柱体的侧面
  23. IDirect3DVertexBuffer9* g_pVB2;          //Vertex Buffer, 圆柱体的上表面
  24. IDirect3DVertexBuffer9* g_pVB3;          //Vertex Buffer, 圆柱体的上表面
  25. IDirect3DVertexBuffer9* g_pVB4;          //Vertex Buffer, 大地
  26. // 创建圆柱体顶点缓冲
  27. BOOL CreateVertexBuf1( IDirect3DVertexBuffer9* & g_pVB);
  28. BOOL CreateVertexBuf2( IDirect3DVertexBuffer9* & g_pVB);
  29. BOOL CreateVertexBuf3( IDirect3DVertexBuffer9* & g_pVB);
  30. // 创建大地顶点缓冲
  31. BOOL CreateVertexBuf4( IDirect3DVertexBuffer9* & g_pVB);
  32. // 初始化和更新摄像机
  33. void InitCamera();
  34. void UpdateCamera();
  35. // 此代码模块中包含的函数的前向声明:
  36. ATOM MyRegisterClass(HINSTANCE hInstance);
  37. BOOL InitInstance(HINSTANCE, int);
  38. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  39. LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
  40. int APIENTRY _tWinMain(HINSTANCE hInstance,
  41.                      HINSTANCE hPrevInstance,
  42.                      LPTSTR    lpCmdLine,
  43.                      int       nCmdShow)
  44. {
  45.   // TODO: 在此放置代码。
  46. MSG msg;
  47. HACCEL hAccelTable;
  48. // 初始化全局字符串
  49. LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
  50. LoadString(hInstance, IDC_CAMERA, szWindowClass, MAX_LOADSTRING);
  51. MyRegisterClass(hInstance);
  52. // 执行应用程序初始化:
  53. if (!InitInstance (hInstance, nCmdShow)) 
  54. {
  55. return FALSE;
  56. }
  57. hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_CAMERA);
  58. // 主消息循环:
  59. while (GetMessage(&msg, NULL, 0, 0)) 
  60. {
  61. if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
  62. {
  63. TranslateMessage(&msg);
  64. DispatchMessage(&msg);
  65. }
  66. }
  67. return (int) msg.wParam;
  68. }
  69. //
  70. //  函数: MyRegisterClass()
  71. //
  72. //  目的: 注册窗口类。
  73. //
  74. //  注释: 
  75. //
  76. //    仅当希望在已添加到 Windows 95 的
  77. //    “RegisterClassEx”函数之前此代码与 Win32 系统兼容时,
  78. //    才需要此函数及其用法。调用此函数
  79. //    十分重要,这样应用程序就可以获得关联的
  80. //   “格式正确的”小图标。
  81. //
  82. ATOM MyRegisterClass(HINSTANCE hInstance)
  83. {
  84. WNDCLASSEX wcex;
  85. wcex.cbSize = sizeof(WNDCLASSEX); 
  86. wcex.style = CS_HREDRAW | CS_VREDRAW;
  87. wcex.lpfnWndProc = (WNDPROC)WndProc;
  88. wcex.cbClsExtra = 0;
  89. wcex.cbWndExtra = 0;
  90. wcex.hInstance = hInstance;
  91. wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_CAMERA);
  92. wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  93. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  94. wcex.lpszMenuName = (LPCTSTR)IDC_CAMERA;
  95. wcex.lpszClassName = szWindowClass;
  96. wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
  97. return RegisterClassEx(&wcex);
  98. }
  99. //
  100. //   函数: InitInstance(HANDLE, int)
  101. //
  102. //   目的: 保存实例句柄并创建主窗口
  103. //
  104. //   注释: 
  105. //
  106. //        在此函数中,我们在全局变量中保存实例句柄并
  107. //        创建和显示主程序窗口。
  108. //
  109. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  110. {
  111.    HWND hWnd;
  112.    hInst = hInstance; // 将实例句柄存储在全局变量中
  113.    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  114.       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
  115.    if (!hWnd)
  116.    {
  117.       return FALSE;
  118.    }
  119.    // Direct3D初始化
  120.    if(FAILED(g_d3dEnv.InitD3D(TRUE, hWnd)))
  121.    return FALSE;
  122.    // 初始化摄像机
  123.    InitCamera();
  124.    // 创建顶点缓冲
  125.    if( !CreateVertexBuf1(g_pVB1))
  126. {
  127. MessageBox(NULL, "Create Vertex Buffer Failed", "Textures.exe", MB_OK);
  128. return FALSE;
  129. }
  130. if( !CreateVertexBuf2(g_pVB2))
  131. {
  132. MessageBox(NULL, "Create Vertex Buffer Failed", "Textures.exe", MB_OK);
  133. return FALSE;
  134. }
  135. if( !CreateVertexBuf3(g_pVB3))
  136. {
  137. MessageBox(NULL, "Create Vertex Buffer Failed", "Textures.exe", MB_OK);
  138. return FALSE;
  139. }
  140. if( !CreateVertexBuf4(g_pVB4))
  141. {
  142. MessageBox(NULL, "Create Vertex Buffer Failed", "Textures.exe", MB_OK);
  143. return FALSE;
  144. }
  145.    ShowWindow(hWnd, nCmdShow);
  146.    UpdateWindow(hWnd);
  147.    return TRUE;
  148. }
  149. //
  150. //  函数: WndProc(HWND, unsigned, WORD, LONG)
  151. //
  152. //  目的: 处理主窗口的消息。
  153. //
  154. //  WM_COMMAND - 处理应用程序菜单
  155. //  WM_PAINT - 绘制主窗口
  156. //  WM_DESTROY - 发送退出消息并返回
  157. //
  158. //
  159. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  160. {
  161. int wmId, wmEvent;
  162. // PAINTSTRUCT ps;
  163. // HDC hdc;
  164. // 定义圆柱体的旋转角,每渲染一帧旋转角自加1度
  165. static float angle = 0.0f;
  166. D3DXMATRIX mat_view, mat_proj;
  167. D3DXMATRIX mat_earth;
  168. D3DXMATRIX mat_cylinder;
  169. switch (message) 
  170. {
  171. case WM_COMMAND:
  172. wmId    = LOWORD(wParam); 
  173. wmEvent = HIWORD(wParam); 
  174. // 分析菜单选择:
  175. switch (wmId)
  176. {
  177. case IDM_ABOUT:
  178. DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
  179. break;
  180. case IDM_EXIT:
  181. DestroyWindow(hWnd);
  182. break;
  183. default:
  184. return DefWindowProc(hWnd, message, wParam, lParam);
  185. }
  186. break;
  187. case WM_PAINT:
  188. //hdc = BeginPaint(hWnd, &ps);
  189. // TODO: 在此添加任意绘图代码...
  190. //EndPaint(hWnd, &ps);
  191. // 确信设备未丢失,如果丢失,函数会完成重置设备功能
  192. g_d3dEnv.MakeSureNotLost();
  193. // 清除屏幕及深度缓存
  194. g_d3dEnv.m_pd3dDevice->Clear(  0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 1.0f, 0 );
  195. g_d3dEnv.m_pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0,0,0,0), 1.0f, 0 );
  196. // 开始渲染
  197. g_d3dEnv.m_pd3dDevice->BeginScene();
  198. // 在此渲染你要呈现的场景
  199. //.............................................................................
  200. // 更新摄像机状态
  201. UpdateCamera();
  202. // 设置摄像机的视口矩阵和投影矩阵
  203. g_d3dEnv.m_pd3dDevice->SetTransform( D3DTS_VIEW, g_camera.GetViewMatrix(&mat_view));
  204. g_d3dEnv.m_pd3dDevice->SetTransform( D3DTS_PROJECTION, g_camera.GetProjMatrix(&mat_proj));
  205. // 设置渲染状态
  206. g_d3dEnv.m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
  207. g_d3dEnv.m_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);  // 实体模式
  208. g_d3dEnv.m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  209. g_d3dEnv.m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  210. // 输出顶点流
  211. // 绘制大地
  212. // 设置大地的世界矩阵,它始终是不动的,设为单位矩阵
  213. D3DXMatrixIdentity( &mat_earth );
  214. g_d3dEnv.m_pd3dDevice->SetTransform( D3DTS_WORLD, &mat_earth );
  215. g_d3dEnv.m_pd3dDevice->SetStreamSource(0, g_pVB4, 0, sizeof(CUSTOMVERTEX));
  216. g_d3dEnv.m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
  217. g_d3dEnv.m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
  218. // 绘制圆柱体
  219. g_d3dEnv.m_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); // 线框模式
  220. // 设置圆柱体的世界矩阵
  221. D3DXMatrixIdentity( &mat_cylinder );
  222. D3DXMatrixRotationY( &mat_cylinder, angle+=D3DX_PI/180 ); // 每渲染一帧旋转角自加1度
  223. g_d3dEnv.m_pd3dDevice->SetTransform( D3DTS_WORLD, &mat_cylinder );
  224. g_d3dEnv.m_pd3dDevice->SetStreamSource(0, g_pVB1, 0, sizeof(CUSTOMVERTEX));
  225. g_d3dEnv.m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
  226. g_d3dEnv.m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 98);
  227. g_d3dEnv.m_pd3dDevice->SetStreamSource(0, g_pVB2, 0, sizeof(CUSTOMVERTEX));
  228. g_d3dEnv.m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
  229. g_d3dEnv.m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 49);
  230. g_d3dEnv.m_pd3dDevice->SetStreamSource(0, g_pVB3, 0, sizeof(CUSTOMVERTEX));
  231. g_d3dEnv.m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
  232. g_d3dEnv.m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 49);
  233. //.............................................................................
  234. g_d3dEnv.m_pd3dDevice->EndScene();
  235. // 将后台缓冲的数据搬到屏幕
  236. g_d3dEnv.m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
  237. break;
  238. case WM_DESTROY:
  239. PostQuitMessage(0);
  240. // 释放D3D接口资源
  241. g_pVB1->Release();
  242. g_pVB2->Release();
  243. g_pVB3->Release();
  244. g_pVB4->Release();
  245. g_d3dEnv.Release();
  246. break;
  247. default:
  248. return DefWindowProc(hWnd, message, wParam, lParam);
  249. }
  250. return 0;
  251. }
  252. //100 Vertices created.........
  253. BOOL CreateVertexBuf1(IDirect3DVertexBuffer9* & g_pVB)
  254. {
  255. CUSTOMVERTEX pVertices[100];
  256. ZeroMemory( pVertices, 100*sizeof( CUSTOMVERTEX ) );
  257. for(int i=0;i<50;i++)
  258. {
  259. FLOAT alpha = (2*D3DX_PI*i)/49;
  260. pVertices[2*i].position   =  D3DXVECTOR3( sinf(alpha), 1.0f, cosf(alpha));
  261. pVertices[2*i].color      =  0x88ffffff;
  262. pVertices[2*i+1].position =  D3DXVECTOR3( sinf(alpha),-1.0f, cosf(alpha));
  263. pVertices[2*i+1].color      =  0x88ffffff;
  264. }
  265. if( FAILED(g_d3dEnv.m_pd3dDevice->CreateVertexBuffer( 100*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX
  266. , D3DPOOL_DEFAULT, &g_pVB, NULL)))
  267. return FALSE;
  268. void* pData;
  269. g_pVB->Lock(0, 100*sizeof(CUSTOMVERTEX), (void**)&pData, 0);
  270. memcpy(pData, pVertices, 100*sizeof(CUSTOMVERTEX));
  271. g_pVB->Unlock();
  272. return TRUE;
  273. }
  274. BOOL CreateVertexBuf2(IDirect3DVertexBuffer9* & g_pVB)
  275. {
  276. CUSTOMVERTEX pVertices[51];
  277. ZeroMemory( pVertices, 51*sizeof( CUSTOMVERTEX ) );
  278. pVertices[0].position = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);
  279. pVertices[0].color    = 0x88ffffff;
  280. for(int i=0;i<50;i++)
  281. {
  282. FLOAT alpha = (2*D3DX_PI*i)/49;
  283. pVertices[i+1].position   =  D3DXVECTOR3( sinf(alpha), 1.0f, cosf(alpha));
  284. pVertices[i+1].color      =  0x88ffffff;
  285. }
  286. if( FAILED(g_d3dEnv.m_pd3dDevice->CreateVertexBuffer( 51*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX
  287. , D3DPOOL_DEFAULT, &g_pVB, NULL)))
  288. return FALSE;
  289. void* pData;
  290. g_pVB->Lock(0, 51*sizeof(CUSTOMVERTEX), (void**)&pData, 0);
  291. memcpy(pData, pVertices, 51*sizeof(CUSTOMVERTEX));
  292. g_pVB->Unlock();
  293. return TRUE;
  294. }
  295. BOOL CreateVertexBuf3(IDirect3DVertexBuffer9* & g_pVB)
  296. {
  297. CUSTOMVERTEX pVertices[51];
  298. ZeroMemory( pVertices, 51*sizeof( CUSTOMVERTEX ) );
  299. pVertices[0].position = D3DXVECTOR3( 0.0f, -1.0f, 0.0f);
  300. pVertices[0].color    = 0x88ffffff;
  301. for(int i=0;i<50;i++)
  302. {
  303. FLOAT alpha = (2*D3DX_PI*i)/49;
  304. pVertices[i+1].position   =  D3DXVECTOR3( sinf(alpha), -1.0f, cosf(alpha));
  305. pVertices[i+1].color      =  0x88ffffff;
  306. }
  307. if( FAILED(g_d3dEnv.m_pd3dDevice->CreateVertexBuffer( 51*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX
  308. , D3DPOOL_DEFAULT, &g_pVB, NULL)))
  309. return FALSE;
  310. void* pData;
  311. g_pVB->Lock(0, 51*sizeof(CUSTOMVERTEX), (void**)&pData, 0);
  312. memcpy(pData, pVertices, 51*sizeof(CUSTOMVERTEX));
  313. g_pVB->Unlock();
  314. return TRUE;
  315. }
  316. void InitCamera()
  317. {
  318. g_camera.SetPosX(0);
  319. g_camera.SetPosY(6.0f);
  320. g_camera.SetPosZ(-10.0f);
  321. g_camera.Pitch(-D3DX_PI*30/180);
  322. g_camera.SetProjProp(1.0f, 50.0f, D3DX_PI/3, 1);
  323. }
  324. void UpdateCamera()
  325. {
  326. static int i = 0;
  327. static bool bForward = true;
  328. // 每80帧改变一次视点移动方向
  329. if(i>=80)
  330. {
  331. i = 0;
  332. bForward = !bForward;
  333. }
  334. // 向前移动视点
  335. if(bForward)
  336. g_camera.Walk(0, 0.1f);
  337. else
  338. // 向后移动视点
  339. g_camera.Walk(0, -0.1f);
  340. i++;
  341. }
  342. // 创建大地顶点缓冲
  343. BOOL CreateVertexBuf4(IDirect3DVertexBuffer9* & g_pVB)
  344. {
  345. CUSTOMVERTEX pVertices[4];
  346. ZeroMemory( pVertices, 4*sizeof(CUSTOMVERTEX));
  347. pVertices[0].position = D3DXVECTOR3(-20.0f, -2.0f, -20.0f);
  348. pVertices[0].color    = 0x881111aa;
  349. pVertices[1].position = D3DXVECTOR3(-20.0f, -2.0f, 20.0f);
  350. pVertices[1].color    = 0x881111aa;
  351. pVertices[2].position = D3DXVECTOR3(20.0f, -2.0f, -20.0f);
  352. pVertices[2].color    = 0x881111aa;
  353. pVertices[3].position = D3DXVECTOR3(20.0f, -2.0f, 20.0f);
  354. pVertices[3].color    = 0x881111aa;
  355. if( FAILED(g_d3dEnv.m_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX
  356. , D3DPOOL_DEFAULT, &g_pVB, NULL)))
  357. return FALSE;
  358. void* pData;
  359. g_pVB->Lock(0, 4*sizeof(CUSTOMVERTEX), (void**)&pData, 0);
  360. memcpy(pData, pVertices, 4*sizeof(CUSTOMVERTEX));
  361. g_pVB->Unlock();
  362. return TRUE;
  363. }
  364. // “关于”框的消息处理程序。
  365. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  366. {
  367. switch (message)
  368. {
  369. case WM_INITDIALOG:
  370. return TRUE;
  371. case WM_COMMAND:
  372. if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
  373. {
  374. EndDialog(hDlg, LOWORD(wParam));
  375. return TRUE;
  376. }
  377. break;
  378. }
  379. return FALSE;
  380. }