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

DirextX编程

开发平台:

Visual C++

  1. #include "zfxd3dUtility.h"
  2. #include <stdio.h>
  3. // D3D对象接口
  4. IDirect3D9* g_pd3d;
  5. // D3D设备接口
  6. IDirect3DDevice9* g_pd3dDevice;
  7. // D3D模型接口
  8. ID3DXMesh* g_pMesh = NULL;
  9. IDirect3DTexture9** g_ppTex;
  10. D3DMATERIAL9* g_pMtrl;
  11. DWORD g_numXMtrl;
  12. // 顶点结构体
  13. typedef struct tagCUSTOMVERTEX{
  14. D3DXVECTOR3 position; // The position of the vertex.
  15.     D3DXVECTOR3 normal;   // The nomal Vector.
  16. FLOAT       tu, tv;   // The texture coordinates
  17. static const DWORD D3D_FVF;
  18. }CUSTOMVERTEX;
  19. const DWORD CUSTOMVERTEX::D3D_FVF = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1;
  20. // 字体
  21. ID3DXFont* g_pFont = NULL;
  22. bool Setup()
  23. {
  24. // 创建模型
  25. HRESULT hr = 0;
  26. hr = D3DXCreateMeshFVF(
  27. 196,  // NumFaces
  28. 202,  // NumVertices
  29. D3DXMESH_MANAGED,
  30. CUSTOMVERTEX::D3D_FVF,
  31. g_pd3dDevice,
  32. &g_pMesh);
  33. if(FAILED(hr))
  34. {
  35. ::MessageBox(0, L"D3DXCreateMeshFVF() - FAILED", 0, 0);
  36. return false;
  37. }
  38. //*******************************填充顶点数据**********************************************************************//
  39. CUSTOMVERTEX *vertices;
  40. g_pMesh->LockVertexBuffer(0, (void**)&vertices);
  41. // 侧面,100个顶点
  42. for(int i=0;i<50;i++)
  43. {
  44. FLOAT alpha = (2*D3DX_PI*i)/49;
  45. vertices[2*i].position   =  D3DXVECTOR3( sinf(alpha), 1.0f, cosf(alpha));
  46. vertices[2*i].normal     =  D3DXVECTOR3( sinf(alpha), 0.0f, cosf(alpha));
  47. vertices[2*i].tu         =  (FLOAT)i/49;
  48. vertices[2*i].tv         =  1.0f;
  49. vertices[2*i+1].position =  D3DXVECTOR3( sinf(alpha),-1.0f, cosf(alpha));
  50. vertices[2*i+1].normal   =  D3DXVECTOR3( sinf(alpha), 0.0f, cosf(alpha));
  51. vertices[2*i+1].tu       =  (FLOAT)i/49;
  52. vertices[2*i+1].tv       =  0.0f;
  53. }
  54. // 顶部,51个顶点
  55. vertices[100].position = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);
  56. vertices[100].normal   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);
  57. vertices[100].tu       = 0.5f;
  58. vertices[100].tv       = 0.5f;
  59. for(int i=101;i<151;i++)
  60. {
  61. FLOAT alpha = (2*D3DX_PI*i)/49;
  62. vertices[i].position   =  D3DXVECTOR3( sinf(alpha), 1.0f, cosf(alpha));
  63. vertices[i].normal     =  D3DXVECTOR3( 0.0f, 1.0f, 0.0f);
  64. vertices[i].tu         =  (sinf(alpha)+1)/2;
  65. vertices[i].tv         =  (cosf(alpha)+1)/2;
  66. }
  67. // 低部,51个顶点
  68. vertices[151].position = D3DXVECTOR3( 0.0f, -1.0f, 0.0f);
  69. vertices[151].normal   = D3DXVECTOR3( 0.0f, -1.0f, 0.0f);
  70. vertices[151].tu       = 0.5f;
  71. vertices[151].tv       = 0.5f;
  72. for(int i=152;i<202;i++)
  73. {
  74. FLOAT alpha = (2*D3DX_PI*i)/49;
  75. vertices[i].position   =  D3DXVECTOR3( sinf(alpha), -1.0f, cosf(alpha));
  76. vertices[i].normal     =  D3DXVECTOR3( 0.0f, -1.0f, 0.0f);
  77. vertices[i].tu         =  (sinf(alpha)+1)/2;
  78. vertices[i].tv         =  (cosf(alpha)+1)/2;
  79. }
  80. g_pMesh->UnlockVertexBuffer();
  81. //*******************************填充顶点数据**********************************************************************//
  82. //*******************************填充索引数据**********************************************************************//
  83. WORD* indices = 0;
  84. g_pMesh->LockIndexBuffer(0, (void**)&indices);
  85. // 侧面,98个三角形,填写索引顺序时一定要保证顶点顺序都是按照顺时针排列的
  86. for(int i=0;i<98;i++)
  87. {
  88. if(!(i%2))
  89. {
  90. indices[3*i] = i;
  91. indices[3*i+1] = i+1;
  92. indices[3*i+2] = i+2;
  93. }
  94. else
  95. {
  96. indices[3*i] = i+1;
  97. indices[3*i+1] = i;
  98. indices[3*i+2] = i+2;
  99. }
  100. }
  101. // 顶部,49个三角形
  102. for(int i=98;i<147;i++)
  103. {
  104. indices[3*i] = 100;
  105. indices[3*i+1] = i+3;
  106. indices[3*i+2] = i+4;
  107. }
  108. // 低部,49个三角形
  109. for(int i=147;i<196;i++)
  110. {
  111. indices[3*i] = 151;
  112. indices[3*i+1] = i+6;
  113. indices[3*i+2] = i+5;
  114. }
  115. g_pMesh->UnlockIndexBuffer();
  116. //*******************************填充索引数据**********************************************************************//
  117. //*******************************填充属性数据**********************************************************************//
  118. // 填充属性数据,分为3个子集
  119. DWORD* attributeBuffer = 0;
  120. g_pMesh->LockAttributeBuffer(0, &attributeBuffer);
  121. for(int i=0;i<98;i++)
  122. attributeBuffer[i] = 0;
  123. for(int i=98;i<147;i++)
  124. attributeBuffer[i] = 1;
  125. for(int i=147;i<196;i++)
  126. attributeBuffer[i] = 2;
  127. g_pMesh->UnlockAttributeBuffer();
  128. //*******************************填充属性数据**********************************************************************//
  129. // 产生邻接数据
  130. DWORD* pAdjacency = new DWORD[g_pMesh->GetNumFaces()*3];;
  131. g_pMesh->GenerateAdjacency(0.01f, pAdjacency);
  132. // 设置材质和纹理
  133. D3DXMATERIAL xMtrl[3];
  134. xMtrl[0].MatD3D = RED_MTRL;
  135. xMtrl[0].pTextureFilename = "sidetex.jpg";
  136. xMtrl[1].MatD3D = YELLOW_MTRL;
  137. xMtrl[1].pTextureFilename = "toptex.jpg";
  138. xMtrl[2].MatD3D = YELLOW_MTRL;
  139. xMtrl[2].pTextureFilename = "bottomtex.jpg";
  140. // 保存模型到文件中
  141. D3DXSaveMeshToX(L"cylinder.x", g_pMesh, pAdjacency, xMtrl, NULL, 3, D3DXF_FILEFORMAT_TEXT);
  142. delete [] pAdjacency;
  143. // 保存后释放g_pMesh对象
  144. SAFE_RELEASE(g_pMesh);
  145. //*******************************载入已存储的.X模型**********************************************************************//
  146. // 从.X文件中导入模型到g_pMesh对象中
  147. ID3DXBuffer* pMtrlBuffer;// 定义缓冲,记得一定要释放
  148. hr = D3DXLoadMeshFromX(L"cylinder.x", D3DXMESH_MANAGED, g_pd3dDevice, NULL, &pMtrlBuffer, NULL, &g_numXMtrl, &g_pMesh);
  149. if(FAILED(hr))
  150. {
  151. MessageBox(0, L"load mesh failed", 0, 0);
  152. return false;
  153. }
  154. D3DXMATERIAL* pMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
  155. g_pMtrl = new D3DMATERIAL9[g_numXMtrl];
  156. g_ppTex = new IDirect3DTexture9*[g_numXMtrl];
  157. for(DWORD i=0;i<g_numXMtrl;i++)
  158. {
  159. g_pMtrl[i] = pMtrls[i].MatD3D;
  160. g_pMtrl[i].Ambient = g_pMtrl[i].Diffuse;
  161. g_ppTex[i] = 0;
  162. hr = D3DXCreateTextureFromFileA(g_pd3dDevice, pMtrls[i].pTextureFilename, &g_ppTex[i]);
  163. if(FAILED(hr))
  164. g_ppTex[i] = 0;
  165. }
  166. // 释放缓冲区
  167. SAFE_RELEASE(pMtrlBuffer);
  168. //*******************************载入已存储的.X模型,完毕****************************************************************//
  169. // 设定渲染状态
  170. g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0xff444444);
  171. g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
  172. g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  173. // 设置投影矩阵
  174. D3DXMATRIX proj;
  175. D3DXMatrixPerspectiveFovLH(
  176. &proj,
  177. D3DX_PI * 0.25f, // 45 - degree
  178. 1,
  179. 1.0f,
  180. 100.0f);
  181. g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj);
  182. return true;
  183. }
  184. bool DrawTextX()
  185. {
  186. //用于渲染侦FPS
  187. static int tmLastTime = GetTickCount();
  188. int tmNow = GetTickCount();
  189. //用于计算渲染FPS
  190. static int nFrameCount = 0;
  191. static int nFPS = 0;
  192. if(tmNow - tmLastTime > 1000)
  193. {
  194. //计算FPS
  195. tmLastTime = tmNow;
  196. nFPS = nFrameCount;
  197. nFrameCount = 0;
  198. }
  199. nFrameCount ++;
  200. char str[500];
  201. RECT rect;
  202. rect.left = rect.top = 10;
  203. rect.bottom = rect.top + 30;
  204. rect.right = rect.left + 260;
  205. sprintf_s(str, 500, "Current FPS:%d,  please press Q to toggle WireFrame mode", nFPS);
  206. g_pFont->DrawTextA(NULL, str, (int)strlen(str), &rect, DT_LEFT|DT_NOCLIP|DT_WORDBREAK, 0xffffff00);
  207. return true;
  208. }
  209. bool Display()
  210. {
  211. // 获取两次进入函数入口的时间间隔
  212. static float lastTime = (float)timeGetTime();
  213. float curTime  = (float)timeGetTime();
  214. float timeDelta = (curTime - lastTime)*0.001f;
  215. lastTime = curTime;
  216. // 设定视口矩阵,你可以通过按下上下左右键改变视角
  217. static float angle  = (3.0f * D3DX_PI) / 2.0f;
  218. static float height = 5.0f;
  219. if( ::GetAsyncKeyState(VK_LEFT) & 0x8000f )
  220. angle -= 0.5f * timeDelta;
  221. if( ::GetAsyncKeyState(VK_RIGHT) & 0x8000f )
  222. angle += 0.5f * timeDelta;
  223. if( ::GetAsyncKeyState(VK_UP) & 0x8000f )
  224. height += 1.5f * timeDelta;
  225. if( ::GetAsyncKeyState(VK_DOWN) & 0x8000f )
  226. height -= 1.5f * timeDelta;
  227. D3DXVECTOR3 eyept( cosf(angle) * 10.0f, height, sinf(angle) * 10.0f );
  228. D3DXVECTOR3 lookAt(0.0f, 0.0f, 0.0f);
  229. D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
  230. D3DXMATRIX view_mat;
  231. D3DXMatrixLookAtLH(&view_mat, &eyept, &lookAt, &up);
  232. g_pd3dDevice->SetTransform(D3DTS_VIEW, &view_mat);
  233. // 绘制场景
  234. g_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  235. g_pd3dDevice->BeginScene();
  236. for(DWORD i=0; i<g_numXMtrl; i++)
  237. {
  238. // 设置相关的材质和世界矩阵,然后绘制物体
  239. g_pd3dDevice->SetMaterial(&g_pMtrl[i]);
  240. g_pd3dDevice->SetTexture(0, g_ppTex[i]);
  241. g_pMesh->DrawSubset(i);
  242. }
  243. // 在屏幕上写字
  244. if(g_pFont)
  245. DrawTextX(); 
  246. g_pd3dDevice->EndScene();
  247. g_pd3dDevice->Present(0, 0, 0, 0);
  248. return true;
  249. }
  250. bool CleanUp()
  251. {
  252. SAFE_RELEASE(g_pd3dDevice);
  253. SAFE_RELEASE(g_pd3d);
  254. SAFE_RELEASE(g_pMesh);
  255. SAFE_DELETE_ARRAY(g_pMtrl);
  256. for(DWORD i=0; i<g_numXMtrl; i++)
  257. {
  258. SAFE_RELEASE(g_ppTex[i]);
  259. }
  260. return true;
  261. }
  262. int WINAPI WinMain(HINSTANCE hInstance,
  263.    HINSTANCE prevInstance, 
  264.    PSTR cmdLine,
  265.    int showCmd)
  266. {
  267. // 应用程序初始化
  268. if(!InitD3DApp(hInstance, false/*true代表窗口模式*/, 
  269. D3DDEVTYPE_HAL, &g_pd3d, &g_pd3dDevice, L"CreateMeshX"/*窗口标题*/, 1024, 768))
  270. {
  271. MessageBoxW(0, L"应用程序初始化失败", 0, 0);
  272. return 0;
  273. }
  274. // 创建字体
  275. if(!InitDXFont(g_pd3dDevice, &g_pFont, L"Times New Roman"))
  276. g_pFont = NULL;
  277. Setup();
  278. // 进入消息循环
  279. MSG msg;
  280. ZeroMemory(&msg, sizeof(msg));
  281. while(msg.message != WM_QUIT)
  282. {
  283. if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  284. {
  285. TranslateMessage(&msg);
  286. DispatchMessage(&msg);
  287. }
  288. else
  289. {
  290. Display();
  291. }
  292. }
  293. CleanUp();
  294. return 0;
  295. }
  296. // 消息循环函数
  297. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  298. {
  299. static bool bWireFrame = false;
  300. switch( msg )
  301. {
  302. case WM_DESTROY:
  303. ::PostQuitMessage(0);
  304. break;
  305. case WM_KEYDOWN:
  306. if( wParam == VK_ESCAPE )
  307. ::DestroyWindow(hwnd);
  308. break;
  309. case WM_CHAR:
  310. if(wParam == 'q')
  311. bWireFrame = !bWireFrame;
  312. if(bWireFrame)
  313. g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
  314. else
  315. g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  316. break;
  317. }
  318. return ::DefWindowProc(hwnd, msg, wParam, lParam);
  319. }