Advertisement
Guest User

Untitled

a guest
Jan 17th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.14 KB | None | 0 0
  1. #include <windows.h>
  2. #include <d3d11.h>
  3. #include <d3dcompiler.h>
  4. #include <DirectXMath.h>
  5. #include <stdio.h>
  6. #include <WICTextureLoader.h>
  7. #include "keyprocessor.h"
  8.  
  9. //[1] Add the assimp libraries
  10. #include <assimp/Importer.hpp>
  11. #include <assimp/postprocess.h>
  12. #include <assimp/scene.h>
  13.  
  14.  
  15. using namespace DirectX;
  16.  
  17. #pragma comment(lib, "d3d11.lib")
  18. #pragma comment(lib, "d3dcompiler.lib")
  19. #pragma comment(lib, "DirectXTK.lib")
  20.  
  21. //[2] Add the assimp library
  22. #pragma comment(lib, "assimp-vc140-mt.lib")
  23.  
  24. // Window class name
  25. static wchar_t szAppClassName[] = L"AssImpEx";
  26.  
  27. // Forward definition of Windows procedure, necessary as Windows Procedure is defined last and
  28. // C++ requires identifiers are declared before use
  29. LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  30.  
  31. // DirectX objects
  32. ID3D11Device *d3dDevice;
  33. ID3D11DeviceContext *d3dContext;
  34. IDXGISwapChain *swapChain;
  35. ID3D11RenderTargetView *backBuffer;
  36.  
  37. // Depth buffer texture and object
  38. ID3D11Texture2D* depthStencilBuffer;
  39. ID3D11DepthStencilView* depthStencilView;
  40.  
  41.  
  42.  
  43. // Terrain Vertex Template
  44. struct Vertex {
  45. XMFLOAT3 pos;
  46. XMFLOAT2 texCoord;
  47.  
  48.  
  49.  
  50. Vertex(XMFLOAT3 xyz, XMFLOAT2 uv) {
  51. pos = xyz;
  52.  
  53. texCoord = uv;
  54. }
  55. Vertex() {
  56. pos = XMFLOAT3(0.0f, 0.0f, 0.0f);
  57. texCoord = XMFLOAT2(0.0f, 0.0f);
  58. }
  59. };
  60.  
  61. //Model Vertex Template
  62. struct Vertex1 {
  63. XMFLOAT3 pos;
  64. XMFLOAT2 texCoord;
  65.  
  66. Vertex1() {
  67.  
  68. }
  69.  
  70. Vertex1(float x, float y, float z, float u, float v) {
  71. pos.x = x;
  72. pos.y = y;
  73. pos.z = z;
  74.  
  75. texCoord.x = u;
  76. texCoord.y = v;
  77. }
  78. };
  79.  
  80. struct ConstantBuffer
  81. {
  82. XMMATRIX mWorld;
  83. XMMATRIX mView;
  84. XMMATRIX mProjection;
  85. };
  86.  
  87. //[3] Dwarf vertex buffer
  88. ID3D11Buffer *dwarfVertexBuffer = NULL;
  89.  
  90.  
  91.  
  92. //[3c] Car vertex buffer
  93. ID3D11Buffer *carVertexBuffer = NULL;
  94.  
  95.  
  96. ID3D11Buffer *terrainVertexBuffer = NULL;
  97. ID3D11Buffer *terrainIndexBuffer = NULL;
  98.  
  99. int NumIndices;
  100.  
  101. ID3D11ShaderResourceView *terrainTex;
  102.  
  103.  
  104. ID3D11Buffer *constantBuffer = NULL;
  105. ID3D11VertexShader *vertexShader = NULL;
  106. ID3D11PixelShader *pixelShader = NULL;
  107. ID3D11InputLayout *vertexLayout = NULL;
  108.  
  109. //[4] Define the dwarf texture object variables
  110. ID3D11ShaderResourceView *dwarfTex;
  111. ID3D11ShaderResourceView *axeTex;
  112.  
  113.  
  114. //[4c] Define the car texture object variable
  115. ID3D11ShaderResourceView *carTex;
  116.  
  117.  
  118. ID3D11SamplerState *sampler;
  119.  
  120. // MVP Matrices
  121. XMMATRIX matWorld;
  122. XMMATRIX matView;
  123. XMMATRIX matProjection;
  124.  
  125. //Camera position
  126. float camXPos = 0.0f;
  127. float camYPos = 10.0f;
  128. float camZPos = 10.0f;
  129.  
  130. XMVECTOR camTarget = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
  131. XMVECTOR camUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  132.  
  133. //Camera rotation
  134. float camRotX = 0.0f;
  135. float camRotY = 0.0f;
  136.  
  137. int curMouseXPos, curMouseYPos;
  138.  
  139. int clientMidX, clientMidY;
  140.  
  141. int winMidX, winMidY;
  142. int winLeft, winTop;
  143.  
  144. float rotFactorY = 0.0f;
  145.  
  146. const float MOVE_STEP = 10.0f;
  147. const float ROTATE_STEP = (XM_PI / 6);
  148.  
  149. // To determine mouse movement need to know how far the mouse has moved
  150. int mouseXPos;
  151. int mouseYPos;
  152.  
  153. // Rotation angles for each axis
  154. float RotationY = 0.0f;
  155. float RotationX = 0.0f;
  156. float RotFactorX = 0.01f;
  157. float RotFactorY = 0.01f;
  158.  
  159. float scale = 1.0f;
  160.  
  161. bool Rotating = false;
  162.  
  163. //Position Variables
  164. float playerX = 0.0f;
  165. float playerY = 0.0f;
  166. float playerZ = 0.0f;
  167.  
  168. //Rotation Variables
  169. float playerYaw = 0.0f;
  170. float playerPitch = 0.0f;
  171. float playerRoll = 0.0f;
  172.  
  173.  
  174. const float MOVE_DIST = 5.0f;
  175. const float ROTATION = XM_PI / 45;
  176.  
  177. DWORD frameTime;
  178.  
  179.  
  180. //[5] Define a variable to store the number of vertices in each dwarf mesh
  181. int *MeshVertices;
  182.  
  183. //[5c] Define a variable to store the number of vertices in the car mesh
  184. int *CarMeshVertices;
  185.  
  186. // Initialise DirectX in the application
  187. BOOL InitialiseDirectX(HWND hMainWnd, HINSTANCE hCurInstance) {
  188. RECT rectDimensions;
  189. GetClientRect(hMainWnd, &rectDimensions);
  190.  
  191. // CREATE MOUSE CURSOR VARIABLES FOR USE IN CAMERA //
  192. LONG width = rectDimensions.right - rectDimensions.left;
  193. LONG height = rectDimensions.bottom - rectDimensions.top;
  194.  
  195. RECT rectWindow;
  196. GetWindowRect(hMainWnd, &rectWindow);
  197.  
  198. winTop = rectWindow.top;
  199. winLeft = rectWindow.left;
  200.  
  201. winMidX = (rectWindow.right - rectWindow.left) / 2;
  202. winMidY = (rectWindow.bottom - rectWindow.top) / 2;
  203.  
  204. clientMidX = width / 2;
  205. clientMidY = (height / 2) - 12;
  206.  
  207. curMouseXPos = clientMidX;
  208. curMouseYPos = clientMidY;
  209.  
  210. SetCursorPos(winLeft + winMidX, winTop + winMidY);
  211.  
  212. rotFactorY = XM_PIDIV2 / width;
  213.  
  214. // Define the feature levels the program
  215. D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1 };
  216.  
  217. int numFeatureLevels = sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL);
  218.  
  219. // Setup the DXGI_SWAP_CHAIN_DESC structure for describing the type of swap chain to be used
  220. DXGI_SWAP_CHAIN_DESC swapChainDesc;
  221. ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
  222. swapChainDesc.BufferCount = 1;
  223. swapChainDesc.BufferDesc.Width = width;
  224. swapChainDesc.BufferDesc.Height = height;
  225. swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  226. swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
  227. swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
  228. swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  229. swapChainDesc.OutputWindow = hMainWnd;
  230. swapChainDesc.Windowed = true;
  231. swapChainDesc.SampleDesc.Count = 1;
  232. swapChainDesc.SampleDesc.Quality = 0;
  233.  
  234. int creationFlags = 0;
  235.  
  236. HRESULT result;
  237.  
  238. // Create the device and swap chain for DirectX 11
  239. result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE,
  240. NULL, NULL, NULL, NULL, D3D11_SDK_VERSION,
  241. &swapChainDesc, &swapChain, &d3dDevice, NULL, &d3dContext);
  242.  
  243. // Check result
  244. if (result != S_OK) {
  245. MessageBox(hMainWnd, TEXT("Failed to initialise DX11!"), szAppClassName, NULL);
  246.  
  247. return false;
  248. }
  249.  
  250. // Create a texture to be used as the back buffer (off screen)
  251. ID3D11Texture2D *backBufferTexture;
  252.  
  253. result = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *) &backBufferTexture);
  254.  
  255. if(result != S_OK) {
  256. MessageBox(hMainWnd, L"Failed to get back buffer!", szAppClassName, NULL);
  257.  
  258. return false;
  259. }
  260.  
  261. result = d3dDevice->CreateRenderTargetView(backBufferTexture, 0, &backBuffer);
  262.  
  263. if(backBufferTexture != NULL) {
  264. backBufferTexture->Release();
  265. }
  266.  
  267. if(result != S_OK) {
  268. MessageBox(hMainWnd, L"Failed to get render target!", szAppClassName, NULL);
  269.  
  270. return false;
  271. }
  272.  
  273. //Define Depth/Stencil Buffer
  274. D3D11_TEXTURE2D_DESC depthStencilDesc;
  275. ZeroMemory(&depthStencilDesc, sizeof(D3D11_TEXTURE2D_DESC));
  276.  
  277. // DepthStencil buffer has same dimensions as back buffer which is the same as the client window
  278. depthStencilDesc.Width = width;
  279. depthStencilDesc.Height = height;
  280. depthStencilDesc.MipLevels = 1;
  281. depthStencilDesc.ArraySize = 1;
  282. // Major difference is depth buffer does not store colour information but depth information
  283. depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
  284. depthStencilDesc.SampleDesc.Count = 1;
  285. depthStencilDesc.SampleDesc.Quality = 0;
  286. // As it's a texture need to define DirectX usage, would be useful to use D3D11_USAGE_DYNAMIC flag and caputre
  287. // state of depth buffer to examine the values stored.
  288. depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
  289. depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
  290. depthStencilDesc.CPUAccessFlags = 0;
  291. depthStencilDesc.MiscFlags = 0;
  292.  
  293. // Create the texture for the depthstencil buffer
  294. d3dDevice->CreateTexture2D(&depthStencilDesc, NULL, &depthStencilBuffer);
  295. // Create the depthstencil object based on the texture created precious
  296. d3dDevice->CreateDepthStencilView(depthStencilBuffer, NULL, &depthStencilView);
  297.  
  298. // Bind the back buffer and the depthstencil buffer to the OM stage
  299. d3dContext->OMSetRenderTargets( 1, &backBuffer, depthStencilView );
  300.  
  301. D3D11_VIEWPORT viewport;
  302. viewport.Width = static_cast<float>(width);
  303. viewport.Height = static_cast<float>(height);
  304. viewport.MinDepth = 0.0f;
  305. viewport.MaxDepth = 1.0f;
  306. viewport.TopLeftX = 0.0f;
  307. viewport.TopLeftY = 0.0f;
  308.  
  309. d3dContext->RSSetViewports(1, &viewport);
  310.  
  311.  
  312.  
  313. XMVECTOR camPos = XMVectorSet(camXPos, camYPos, camZPos, 0.0f);
  314. matView = XMMatrixLookAtLH(camPos, camTarget, camUp);
  315.  
  316. matProjection = XMMatrixPerspectiveFovLH( XM_PIDIV4, width / (FLOAT)height,
  317. 1.0f, 100.0f);
  318.  
  319.  
  320. // Initialize the view matrix
  321. XMVECTOR Eye = XMVectorSet( 0.0f, 3.0f, -10.0f, 0.0f );
  322. XMVECTOR At = XMVectorSet( 0.0f, 3.0f, 0.0f, 0.0f );
  323. XMVECTOR Up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
  324. matView = XMMatrixLookAtLH( Eye, At, Up );
  325.  
  326. // Initialize the projection matrix
  327. matProjection = XMMatrixPerspectiveFovLH( XM_PIDIV4, width / (FLOAT)height, 0.01f, 100.0f );
  328.  
  329. return true;
  330. }
  331.  
  332.  
  333.  
  334.  
  335.  
  336. // CREATE ALL SHADERS //
  337.  
  338. bool CreateShaders(HWND hMainWnd) {
  339.  
  340. ID3DBlob *pVSBlob = NULL;
  341. HRESULT hr = D3DReadFileToBlob(L".\\VertexShader.cso", &pVSBlob);
  342. if (hr != S_OK)
  343. {
  344. MessageBox(hMainWnd, L"Problem loading vertex shader. Check shader file (VertexShader.cso) is in the project directory (sub folder of main solution directory) and shader is valid", szAppClassName, MB_OK);
  345.  
  346. return false;
  347. }
  348.  
  349. // Create the vertex shader in DirectX
  350. hr = d3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &vertexShader );
  351. // Check creating vertex shader was successful
  352. if( hr != S_OK )
  353. {
  354. pVSBlob->Release();
  355.  
  356. MessageBox( hMainWnd, L"The vertex shader object cannot be created", szAppClassName, MB_OK );
  357.  
  358. return false;
  359. }
  360.  
  361. // Need to tell DirectX how vertices are structured in terms of colour format and order of data, that is individual vertices
  362. // The POSITION is called the semantic name, basically a meaningful identifier used internally to map vertex elements to shader
  363. // parameters. Semantic name text must obey the rules of C identifiers as shader language uses C syntax
  364. D3D11_INPUT_ELEMENT_DESC layout[] =
  365. {
  366. { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  367. { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  368. };
  369.  
  370. UINT numElements = 2;
  371.  
  372. // Create the input layout for input assembler based on description and the vertex shader to be used
  373. hr = d3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &vertexLayout );
  374. // Check layout was created successfully
  375. pVSBlob->Release();
  376. if( hr != S_OK ) {
  377. MessageBox( hMainWnd, L"Problems creating input layout", szAppClassName, MB_OK );
  378.  
  379. return false;
  380. }
  381.  
  382. // Set the input layout for input assembler
  383. d3dContext->IASetInputLayout( vertexLayout );
  384.  
  385. // Compile the pixel shader
  386. ID3DBlob* pPSBlob = NULL;
  387. hr = D3DReadFileToBlob( L".\\PixelShader.cso", &pPSBlob);
  388. // Check pixel shader was loaded successfully
  389. if( hr != S_OK )
  390. {
  391. // If program has got this far then the problem is more likely to be in shader file, e.g. mistyped name, or wrong shader version
  392. MessageBox( hMainWnd, L"Problem loading pixel shader. Check shader file (PixelShader.cso) is in the project directory (sub folder of main solution directory) and shader is valid", szAppClassName, MB_OK );
  393.  
  394. return false;
  395. }
  396.  
  397. // Create the pixel shader in DirectX
  398. hr = d3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &pixelShader );
  399. pPSBlob->Release();
  400. // Check creating pixel shader was successful
  401. if( hr != S_OK ) {
  402. MessageBox( hMainWnd, L"The pixel shader object cannot be created", szAppClassName, MB_OK );
  403.  
  404. return false;
  405. }
  406. // TEXTURES //
  407.  
  408. //Load
  409. hr = CreateWICTextureFromFile(d3dDevice, d3dContext, L".\\terrain-texture2.jpg", 0, &terrainTex, 0);
  410.  
  411. //[6] Load dwarf texture
  412. hr = CreateWICTextureFromFile(d3dDevice, d3dContext, L".\\dwarf.jpg", NULL, &dwarfTex);
  413. if (hr != S_OK) {
  414. MessageBox(hMainWnd, TEXT("Unable to load dwarf texture"), szAppClassName, MB_OK);
  415.  
  416. return false;
  417. }
  418.  
  419.  
  420. //[7] Load axe texture
  421. hr = CreateWICTextureFromFile(d3dDevice, d3dContext, L".\\axe.jpg", NULL, &axeTex);
  422. if (hr != S_OK) {
  423. MessageBox(hMainWnd, TEXT("Unable to load dwarf texture"), szAppClassName, MB_OK);
  424.  
  425. return false;
  426. }
  427.  
  428. //[6c] Load car texture
  429. hr = CreateWICTextureFromFile(d3dDevice, d3dContext, L".\\Alien Slime.png", NULL, &carTex);
  430. if (hr != S_OK) {
  431. MessageBox(hMainWnd, TEXT("Unable to load car texture"), szAppClassName, MB_OK);
  432.  
  433. return false;
  434. }
  435.  
  436. D3D11_SAMPLER_DESC sampDesc;
  437. ZeroMemory(&sampDesc, sizeof(sampDesc));
  438. sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
  439. sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
  440. sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
  441. sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
  442. sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  443. sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
  444.  
  445. hr = d3dDevice->CreateSamplerState(&sampDesc, &sampler);
  446. if(hr != S_OK) {
  447. MessageBox( hMainWnd, TEXT("Unable to create sampler"), szAppClassName, MB_OK );
  448.  
  449. return false;
  450. }
  451.  
  452. // If we've got this far then have valid shaders.
  453. // Return a successful result
  454. return true;
  455. }
  456.  
  457. // CUSTOM HEIGHTMAP //
  458.  
  459. void LoadHeightMap(const char *filename, float MaxHeight, Vertex **mesh) {
  460. // This example expects a texture file of 256 pixels width and height
  461. // More flexible version would obtain the width and height from
  462. // file and create terrain from this data as terrain vertices
  463. // map onto pixel data
  464. // Also presumes height map is 24 bit texture file
  465. const int Size = 256;
  466.  
  467. FILE *file_ptr = fopen(filename, "rb");
  468.  
  469. if (file_ptr == NULL) {
  470. return;
  471. }
  472.  
  473. // Read the file's header information
  474. // so we can create a buffer to hold the pixel colour data
  475. BITMAPFILEHEADER bmHeader;
  476. BITMAPINFOHEADER bmInfo;
  477.  
  478. fread(&bmHeader, sizeof(BITMAPFILEHEADER), 1, file_ptr);
  479.  
  480. fread(&bmInfo, sizeof(BITMAPINFOHEADER), 1, file_ptr);
  481.  
  482. // Move file pointer to start of pixel colour data
  483. fseek(file_ptr, bmHeader.bfOffBits, SEEK_SET);
  484.  
  485. // Work out number of bytes per pixel for array
  486. int NumBytesPerPixel = bmInfo.biBitCount / 8;
  487.  
  488. // Calculate maximum colour value up 2^24 colour
  489. float MaxColourVal = (float)pow(2.0f, min(24.0f, (float)bmInfo.biBitCount));
  490.  
  491. // Create array for pixel data
  492. unsigned char *pixel_data = new unsigned char[Size * Size * NumBytesPerPixel];
  493.  
  494. // Read pixel data from file into memory
  495. fread(pixel_data, sizeof(unsigned char), Size * Size * NumBytesPerPixel, file_ptr);
  496.  
  497. // Release the file
  498. fclose(file_ptr);
  499.  
  500. //[13] Modify each vertex's y component based on the pixel value in proportion to max colour value
  501. // in the corresponding pixel
  502. int idx = 0;
  503. Vertex *vertArray = *mesh;
  504. for (int row = 0; row < Size; row++) {
  505. for (int col = 0; col < Size; col++) {
  506. int pixel_val = pixel_data[idx * NumBytesPerPixel]
  507. + (pixel_data[(idx * NumBytesPerPixel) + 1] << 8)
  508. + (pixel_data[(idx * NumBytesPerPixel) + 2] << 16);
  509.  
  510. vertArray[idx].pos.y = MaxHeight * (pixel_val / MaxColourVal);
  511.  
  512. idx++;
  513.  
  514. }
  515. }
  516.  
  517.  
  518. // Release pixel data as don't need it any more
  519. delete[] pixel_data;
  520. }
  521. // CREATE TERRAIN MESH //
  522. void CreateTerrainMesh(int NumVertices, Vertex **mesh, int *TotalNumVert, int **indices, int *NumIndices)
  523. {
  524.  
  525. *NumIndices = (NumVertices - 1) * (NumVertices - 1) * 6;
  526. *indices = new int[*NumIndices];
  527.  
  528. int *p = *indices;
  529.  
  530. p[0] = 0;
  531. p[1] = NumVertices;
  532. p[2] = NumVertices + 1;
  533. p[3] = NumVertices + 1;
  534. p[4] = 1;
  535. p[5] = 0;
  536.  
  537. int NextRow = (NumVertices - 1) * 6;
  538. for (int idx = 6; idx < *NumIndices; idx++) {
  539. if (idx % NextRow == 0) {
  540. p[idx] = (idx / NextRow) *NumVertices;
  541. p[idx + 1] = p[idx] + NumVertices;
  542. p[idx + 2] = p[idx + 1] + 1;
  543. p[idx + 3] = p[idx + 2];
  544. p[idx + 4] = p[idx] + 1;
  545. p[idx + 5] = p[idx];
  546.  
  547. idx += 5;
  548. }
  549. else {
  550. p[idx] = p[idx - 6] + 1;
  551. }
  552.  
  553. }
  554.  
  555.  
  556. *TotalNumVert = NumVertices * NumVertices;
  557. *mesh = new Vertex[*TotalNumVert];
  558.  
  559. float step = 2.0f / NumVertices;
  560.  
  561. float xPos = -1.0f;
  562. float zPos = -1.0f;
  563.  
  564. float uvStep = 1.0f / NumVertices;
  565.  
  566. float u = 0.0f;
  567. float v = 0.0f;
  568.  
  569. int idx = 0;
  570. Vertex *vertArray = *mesh;
  571.  
  572. for (int row = 0; row < NumVertices; row++) {
  573. for (int col = 0; col < NumVertices; col++) {
  574.  
  575. vertArray[idx] = Vertex(XMFLOAT3(xPos, 0.0f, zPos), XMFLOAT2(u, v));
  576.  
  577. xPos += step;
  578. u += uvStep;
  579. idx++;
  580.  
  581. }
  582.  
  583. u = 0.0f;
  584. v += uvStep;
  585. xPos = -1.0f;
  586. zPos += step;
  587. }
  588.  
  589. }
  590.  
  591.  
  592. // LOAD DWARF MODEL //
  593. bool LoadDwarfModel() {
  594. //[8] Create importer object
  595. Assimp::Importer imp;
  596.  
  597.  
  598. //[9] Load model into scene object
  599. const aiScene *pScene = imp.ReadFile(".\\dwarf.x",
  600. aiProcessPreset_TargetRealtime_Fast | aiProcess_ConvertToLeftHanded);
  601. if (!pScene) {
  602. return false;
  603. }
  604.  
  605.  
  606. if (!pScene) {
  607. return false;
  608. }
  609.  
  610. //[10] Create an array to store the individual number of vertices in each mesh
  611. MeshVertices = new int[pScene->mNumMeshes];
  612.  
  613.  
  614. //[11] Calculate the total number of vertices from all meshes
  615. int TotalNumVertices = 0;
  616. for (int MeshIdx = 0; MeshIdx < pScene->mNumMeshes; MeshIdx++) {
  617. const aiMesh *mesh = pScene->mMeshes[MeshIdx];
  618.  
  619. MeshVertices[MeshIdx] = mesh->mNumFaces * 3;
  620.  
  621. TotalNumVertices += mesh->mNumFaces * 3;
  622. }
  623.  
  624.  
  625. //[12] Create an array to store all vertices
  626. Vertex1 *shape = new Vertex1[TotalNumVertices];
  627.  
  628.  
  629.  
  630. //[13] Convert the assimp vertices to ones for DirectX
  631. int vertCount = 0;
  632. for (int MeshIdx = 0; MeshIdx < pScene->mNumMeshes; MeshIdx++) {
  633. const aiMesh *mesh = pScene->mMeshes[MeshIdx];
  634.  
  635. for (int faceIdx = 0; faceIdx < mesh->mNumFaces; faceIdx++) {
  636. const aiFace& face = mesh->mFaces[faceIdx];
  637.  
  638. for (int vertIdx = 0; vertIdx < 3; vertIdx++) {
  639. const aiVector3D *pos = &mesh->mVertices[face.mIndices[vertIdx]];
  640. const aiVector3D *tex = &mesh->mTextureCoords[0][face.mIndices[vertIdx]];
  641.  
  642. shape[vertCount] = Vertex1(pos->x, pos->y, pos->z, tex->x, tex->y);
  643. vertCount++;
  644. }
  645. }
  646.  
  647. }
  648.  
  649.  
  650.  
  651. //[14] Define the vertex buffer
  652. D3D11_BUFFER_DESC bd;
  653. ZeroMemory(&bd, sizeof(bd));
  654. bd.Usage = D3D11_USAGE_DEFAULT;
  655. bd.ByteWidth = sizeof(Vertex1) * TotalNumVertices;
  656. bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  657. bd.CPUAccessFlags = 0;
  658.  
  659.  
  660. // Define the source of vertex data in RAM
  661. D3D11_SUBRESOURCE_DATA InitData;
  662. ZeroMemory(&InitData, sizeof(InitData));
  663. InitData.pSysMem = shape;
  664. HRESULT hr = d3dDevice->CreateBuffer(&bd, &InitData, &dwarfVertexBuffer);
  665.  
  666. if (hr != S_OK) {
  667. return false;
  668. }
  669.  
  670.  
  671. //[15] Release memory allocated to shape
  672. delete[] shape;
  673.  
  674.  
  675. // Got this far so model loaded okay
  676. return true;
  677. }
  678.  
  679. bool LoadCarModel() {
  680. //[8] Create importer object
  681. Assimp::Importer imp1;
  682.  
  683.  
  684. //[9] Load model into scene object
  685. const aiScene *pScene = imp1.ReadFile(".\\Alien Slime.blend",
  686. aiProcessPreset_TargetRealtime_Fast | aiProcess_ConvertToLeftHanded);
  687. if (!pScene) {
  688. return false;
  689. }
  690.  
  691.  
  692. if (!pScene) {
  693. return false;
  694. }
  695.  
  696. //[10] Create an array to store the individual number of vertices in each mesh
  697. CarMeshVertices = new int[pScene->mNumMeshes];
  698.  
  699.  
  700. //[11] Calculate the total number of vertices from all meshes
  701. int TotalNumVertices = 0;
  702. for (int MeshIdx = 0; MeshIdx < pScene->mNumMeshes; MeshIdx++) {
  703. const aiMesh *mesh = pScene->mMeshes[MeshIdx];
  704.  
  705. CarMeshVertices[MeshIdx] = mesh->mNumFaces * 3;
  706.  
  707. TotalNumVertices += mesh->mNumFaces * 3;
  708. }
  709.  
  710.  
  711. //[12] Create an array to store all vertices
  712. Vertex1 *shape1 = new Vertex1[TotalNumVertices];
  713.  
  714.  
  715.  
  716. //[13] Convert the assimp vertices to ones for DirectX
  717. int vertCount = 0;
  718. for (int MeshIdx = 0; MeshIdx < pScene->mNumMeshes; MeshIdx++) {
  719. const aiMesh *mesh = pScene->mMeshes[MeshIdx];
  720.  
  721. for (int faceIdx = 0; faceIdx < mesh->mNumFaces; faceIdx++) {
  722. const aiFace& face = mesh->mFaces[faceIdx];
  723.  
  724. for (int vertIdx = 0; vertIdx < 3; vertIdx++) {
  725. const aiVector3D *pos = &mesh->mVertices[face.mIndices[vertIdx]];
  726. const aiVector3D *tex = &mesh->mTextureCoords[0][face.mIndices[vertIdx]];
  727.  
  728. shape1[vertCount] = Vertex1(pos->x, pos->y, pos->z, tex->x, tex->y);
  729. vertCount++;
  730. }
  731. }
  732.  
  733. }
  734.  
  735.  
  736.  
  737. //[14] Define the vertex buffer
  738. D3D11_BUFFER_DESC bd;
  739. ZeroMemory(&bd, sizeof(bd));
  740. bd.Usage = D3D11_USAGE_DEFAULT;
  741. bd.ByteWidth = sizeof(Vertex1) * TotalNumVertices;
  742. bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  743. bd.CPUAccessFlags = 0;
  744.  
  745.  
  746. // Define the source of vertex data in RAM
  747. D3D11_SUBRESOURCE_DATA InitData;
  748. ZeroMemory(&InitData, sizeof(InitData));
  749. InitData.pSysMem = shape1;
  750. HRESULT hr = d3dDevice->CreateBuffer(&bd, &InitData, &carVertexBuffer);
  751.  
  752. if (hr != S_OK) {
  753. return false;
  754. }
  755.  
  756.  
  757. //[15] Release memory allocated to shape
  758. delete[] shape1;
  759.  
  760.  
  761. // Got this far so model loaded okay
  762. return true;
  763. }
  764.  
  765. bool CreateMeshes(HWND hMainWnd) {
  766. // LOAD DWARF MODEL //
  767. if (!LoadDwarfModel()) {
  768. MessageBox(hMainWnd, L"Failed to load and create dwarf model", szAppClassName, NULL);
  769.  
  770. return false;
  771. }
  772. // LOAD CAR MODEL //
  773. if (!LoadCarModel()) {
  774. MessageBox(hMainWnd, L"Failed to load and create car model", szAppClassName, NULL);
  775.  
  776. return false;
  777. }
  778.  
  779. // TERRAIN //
  780. Vertex *terrainVertices;
  781. int *terrainIndices;
  782. int NumVert;
  783.  
  784. CreateTerrainMesh(256, &terrainVertices, &NumVert, &terrainIndices, &NumIndices);
  785. LoadHeightMap(".\\terrain-heightmap 24bit.bmp", 2.0f, &terrainVertices);
  786.  
  787. D3D11_BUFFER_DESC bdt;
  788. ZeroMemory(&bdt, sizeof(bdt));
  789. bdt.Usage = D3D11_USAGE_IMMUTABLE;
  790. bdt.ByteWidth = sizeof(Vertex) * NumVert;
  791. bdt.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  792. bdt.CPUAccessFlags = 0;
  793. D3D11_SUBRESOURCE_DATA InitData;
  794. ZeroMemory(&InitData, sizeof(InitData) );
  795. InitData.pSysMem = terrainVertices; HRESULT hrt = d3dDevice->CreateBuffer(&bdt, &InitData, &terrainVertexBuffer);
  796.  
  797. ZeroMemory(&bdt, sizeof(bdt));
  798. bdt.Usage = D3D11_USAGE_IMMUTABLE;
  799. bdt.ByteWidth = sizeof(int) * NumIndices;
  800. bdt.BindFlags = D3D11_BIND_INDEX_BUFFER;
  801. bdt.CPUAccessFlags = 0;
  802.  
  803. ZeroMemory(&InitData, sizeof(InitData));
  804.  
  805. InitData.pSysMem = terrainIndices;
  806.  
  807. hrt = d3dDevice->CreateBuffer(&bdt, &InitData, &terrainIndexBuffer);
  808.  
  809.  
  810. delete[] terrainVertices;
  811. delete[] terrainIndices;
  812.  
  813. // Create the constant buffer
  814. D3D11_BUFFER_DESC bd;
  815. ZeroMemory(&bd, sizeof(D3D11_BUFFER_DESC));
  816. bd.Usage = D3D11_USAGE_DEFAULT;
  817. bd.ByteWidth = sizeof(ConstantBuffer);
  818. bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
  819. bd.CPUAccessFlags = 0;
  820. HRESULT hr = d3dDevice->CreateBuffer( &bd, NULL, &constantBuffer );
  821. if( hr != S_OK ) {
  822. MessageBox(hMainWnd, L"Failed to create constant buffer", szAppClassName, NULL);
  823.  
  824. return false;
  825. }
  826.  
  827. // If we've got this far then have vertice structure in DirectX.
  828. // Return a successful result
  829. return true;
  830. }
  831.  
  832.  
  833. void Update() {
  834. // MOUSE & KEYBOARD CONTROLS //
  835. DWORD now = GetTickCount();
  836. DWORD diff = now - frameTime;
  837.  
  838. const float move_step = 10.0f;
  839.  
  840. float forwards_backwards = 0.0f;
  841. float left_right = 0.0f;
  842.  
  843. if (IsKeyDown('W')) {
  844. forwards_backwards = move_step * (diff / 1000.0f);
  845. }
  846.  
  847. if (IsKeyDown('S')) {
  848. forwards_backwards = -move_step * (diff / 1000.0f);
  849. }
  850.  
  851. int deltaX = clientMidX - curMouseXPos;
  852.  
  853. camRotY -= deltaX * rotFactorY;
  854.  
  855. SetCursorPos(winLeft + winMidX, winTop + winMidY);
  856.  
  857. XMMATRIX camMove = XMMatrixTranslation(0.0f, 0.0f, forwards_backwards) *
  858. XMMatrixRotationRollPitchYaw(camRotX, camRotY, 0.0f);
  859.  
  860. XMVECTOR scale, rot, trans;
  861. XMMatrixDecompose(&scale, &rot, &trans, camMove);
  862.  
  863. camXPos += XMVectorGetX(trans);
  864. camYPos += XMVectorGetY(trans);
  865. camZPos += XMVectorGetZ(trans);
  866.  
  867. XMVECTOR camPos = XMVectorSet(camXPos, camYPos, camZPos, 0.0f);
  868.  
  869. XMMATRIX camDist = XMMatrixTranslation(0.0f, 0.0f, 10.0f) *
  870. XMMatrixRotationRollPitchYaw(camRotX, camRotY, 0.0f);
  871.  
  872. XMMatrixDecompose(&scale, &rot, &trans, camDist);
  873.  
  874. camTarget = XMVectorSet(camXPos + XMVectorGetX(trans),
  875. camYPos + XMVectorGetY(trans),
  876. camZPos + XMVectorGetZ(trans), 0.0f);
  877.  
  878. matView = XMMatrixLookAtLH(camPos, camTarget, camUp);
  879.  
  880. frameTime = now;
  881. }
  882.  
  883. // Renders a frame, what does this function do?
  884. void Draw() {
  885. if(d3dContext == NULL) {
  886. return;
  887. }
  888.  
  889.  
  890. //Player model
  891. matWorld = XMMatrixIdentity() * XMMatrixScaling(0.3f, 0.3f, 0.3f) *
  892. XMMatrixRotationRollPitchYaw(playerPitch, playerYaw, playerRoll) *
  893. XMMatrixTranslation(playerX, playerY, playerZ);
  894.  
  895.  
  896. matWorld = XMMatrixScaling(0.1f, 0.1f, 0.1f) * XMMatrixRotationY(-RotationY) * XMMatrixTranslation(0.0f, 0.0f, 20.0f);
  897.  
  898. ConstantBuffer cb;
  899. cb.mWorld = XMMatrixTranspose( matWorld );
  900. cb.mView = XMMatrixTranspose( matView );
  901. cb.mProjection = XMMatrixTranspose( matProjection );
  902. d3dContext->UpdateSubresource( constantBuffer, 0, NULL, &cb, 0, 0 );
  903.  
  904. float colour[] = {0.392156f, 0.584313f, 0.929411f, 1.0f};
  905.  
  906. d3dContext->ClearRenderTargetView(backBuffer, colour);
  907. // Clear the depth of depthstencil buffer to 1.0f for new frame
  908. d3dContext->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
  909.  
  910. // Render a triangle. Not directly from vertices but from applying the shaders
  911. d3dContext->VSSetShader( vertexShader, NULL, 0 );
  912. d3dContext->VSSetConstantBuffers( 0, 1, &constantBuffer );
  913. d3dContext->PSSetShader( pixelShader, NULL, 0 );
  914.  
  915. //[16] Select vertex buffer with all of the mesh vertices
  916. UINT stride = sizeof(Vertex);
  917. UINT offset = 0;
  918. d3dContext->IASetVertexBuffers(0, 1, &dwarfVertexBuffer, &stride, &offset);
  919.  
  920.  
  921.  
  922. // Also tell input assembler how the vertices are to be treated.
  923. d3dContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
  924.  
  925. // Select the sampler
  926. d3dContext->PSSetSamplers(0, 1, &sampler);
  927.  
  928.  
  929. // TERRAIN //
  930.  
  931. //Scale terrain based on matrix scaling values
  932. matWorld = XMMatrixScaling(50.0f, 5.0f, 100.0f) *XMMatrixIdentity();
  933.  
  934. cb.mWorld = XMMatrixTranspose(matWorld);
  935. d3dContext->UpdateSubresource(constantBuffer, 0, NULL, &cb, 0, 0);
  936.  
  937. UINT stridet = sizeof(Vertex);
  938. UINT offsett = 0;
  939. d3dContext->IASetVertexBuffers(0, 1, &terrainVertexBuffer, &stridet, &offsett);
  940. //Set Terrain Index buffer
  941. d3dContext->IASetIndexBuffer(terrainIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
  942.  
  943. d3dContext->PSSetShaderResources(1, 1, &terrainTex);
  944.  
  945. d3dContext->DrawIndexed(NumIndices, 0, 0);
  946.  
  947.  
  948. ////[17] Select the axe texture first
  949. d3dContext->PSSetShaderResources(1, 1, &axeTex);
  950.  
  951.  
  952. ////[18] Draw the axe mesh
  953. d3dContext->Draw(MeshVertices[0], 1);
  954.  
  955.  
  956. ////[19] Select the dwarf texture
  957. d3dContext->PSSetShaderResources(1, 1, &dwarfTex);
  958.  
  959.  
  960. ////[20] Draw the dwarf mesh
  961. d3dContext->Draw(MeshVertices[1], MeshVertices[0]);
  962.  
  963.  
  964. //[16c] Select car vertex buffer into pipeline
  965. d3dContext->IASetVertexBuffers(0, 1, &carVertexBuffer, &stride, &offset);
  966.  
  967.  
  968. //[17c] Select car texture into pipeline
  969. d3dContext->PSSetShaderResources(1, 1, &carTex);
  970.  
  971.  
  972. //[18c] Draw car
  973. d3dContext->Draw(CarMeshVertices[0], CarMeshVertices[0]);
  974.  
  975. // Display frame immediately
  976. swapChain->Present(0,0);
  977. }
  978.  
  979. // Release the resources allocated to application as a result of
  980. // using DirectX
  981. void ShutdownDirectX() {
  982. if(dwarfTex) {
  983. dwarfTex->Release();
  984. }
  985.  
  986. if (axeTex) {
  987. axeTex->Release();
  988. }
  989.  
  990. if(dwarfVertexBuffer != NULL)
  991. dwarfVertexBuffer->Release();
  992.  
  993. if (carTex) {
  994. carTex->Release();
  995. }
  996.  
  997. if (carVertexBuffer != NULL)
  998. carVertexBuffer->Release();
  999.  
  1000. // Add source code to release car buffer and texture
  1001.  
  1002. if (sampler) {
  1003. sampler->Release();
  1004. }
  1005.  
  1006.  
  1007. if(vertexShader != NULL)
  1008. vertexShader->Release();
  1009.  
  1010. if(pixelShader != NULL)
  1011. pixelShader->Release();
  1012.  
  1013. if(vertexLayout != NULL)
  1014. vertexLayout->Release();
  1015.  
  1016. if(backBuffer) {
  1017. backBuffer->Release();
  1018. }
  1019.  
  1020. if(depthStencilView) {
  1021. depthStencilView->Release();
  1022. }
  1023.  
  1024. if(depthStencilBuffer) {
  1025. depthStencilBuffer->Release();
  1026. }
  1027.  
  1028. if(swapChain) {
  1029. swapChain->Release();
  1030. }
  1031.  
  1032. if(d3dContext) {
  1033. d3dContext->Release();
  1034. }
  1035.  
  1036. if(d3dDevice) {
  1037. d3dDevice->Release();
  1038.  
  1039. backBuffer = 0;
  1040. swapChain = 0;
  1041. d3dContext = 0;
  1042. d3dDevice = 0;
  1043. }
  1044. }
  1045.  
  1046. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLineArgs, int nInitialWinShowState) {
  1047. HWND hMainWnd;
  1048. MSG msg = {0};
  1049. // Find out what a WNDCLASS is and what it is used for
  1050. WNDCLASS wndclass;
  1051. wchar_t fps[ 64 ];
  1052. ZeroMemory(fps, 64);
  1053.  
  1054. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  1055. wndclass.lpfnWndProc = WinProc;
  1056. wndclass.cbClsExtra = 0;
  1057. wndclass.cbWndExtra = 0;
  1058. wndclass.hInstance = hInstance;
  1059. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  1060. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  1061. wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  1062. wndclass.lpszMenuName = NULL;
  1063. wndclass.lpszClassName = szAppClassName;
  1064.  
  1065. // Find out why we have to register the class
  1066. if(!RegisterClass(&wndclass)) {
  1067. MessageBox(NULL, L"Unable to register class for application", szAppClassName, 0);
  1068.  
  1069. return 0;
  1070. }
  1071.  
  1072. // Find out what CreateWindows does
  1073. hMainWnd = CreateWindow(szAppClassName,
  1074. L"Basic Windows Application",
  1075. WS_OVERLAPPEDWINDOW,
  1076. CW_USEDEFAULT,
  1077. CW_USEDEFAULT,
  1078. CW_USEDEFAULT,
  1079. CW_USEDEFAULT,
  1080. NULL,
  1081. NULL,
  1082. hInstance,
  1083. NULL);
  1084.  
  1085. if(!hMainWnd) {
  1086. MessageBox(NULL, L"Unable able to create the application's main window", szAppClassName, 0);
  1087.  
  1088. return 0;
  1089. }
  1090.  
  1091. ShowWindow(hMainWnd, nInitialWinShowState);
  1092.  
  1093. if(!InitialiseDirectX(hMainWnd, hInstance)) {
  1094. MessageBox(NULL, L"Failed to initialise DirectX", szAppClassName, 0);
  1095.  
  1096. return 0;
  1097. }
  1098.  
  1099. // Create shaders
  1100. if(!CreateShaders(hMainWnd)) {
  1101. // Exit program if an error occurred
  1102. return 0;
  1103. }
  1104.  
  1105. // Create the vertices of the triangle in DirectX
  1106. if(!CreateMeshes(hMainWnd)) {
  1107. // Exit program if an error occurred
  1108. return 0;
  1109. }
  1110.  
  1111. // Slightly different message loop
  1112. DWORD current = GetTickCount();
  1113. int count = 0;
  1114.  
  1115.  
  1116. InitialiseKeyboardHandler();
  1117.  
  1118.  
  1119.  
  1120. while(msg.message != WM_QUIT) {
  1121. if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
  1122. TranslateMessage(&msg);
  1123. DispatchMessage(&msg);
  1124. } else {
  1125. Update();
  1126.  
  1127. Draw();
  1128.  
  1129. count++;
  1130.  
  1131. DWORD now = GetTickCount();
  1132. if(now - current > 1000) {
  1133. wsprintf(fps, L"FPS = %d", count);
  1134.  
  1135. SetWindowText(hMainWnd, fps);
  1136.  
  1137. count = 0;
  1138.  
  1139. current = now;
  1140. }
  1141.  
  1142. }
  1143. }
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149. ShutdownDirectX();
  1150.  
  1151. return 0;
  1152. }
  1153.  
  1154. // Windows message procedure, this responds to user and system generated events
  1155. LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  1156. int curMouseXPos, curMouseYPos;
  1157. int zDelta;
  1158.  
  1159. curMouseXPos = (short) LOWORD(lParam);
  1160. curMouseYPos = (short) HIWORD(lParam);
  1161.  
  1162. switch(uMsg) {
  1163. // When the user closes the window by pressing the close button
  1164. // Tell the application to terminate by breaking the windows message loop
  1165.  
  1166.  
  1167.  
  1168. case WM_KEYDOWN:
  1169. ProcessKeyDown(wParam);
  1170. return 0;
  1171.  
  1172. case WM_KEYUP:
  1173. ProcessKeyUp(wParam);
  1174. return 0;
  1175.  
  1176. case WM_MOUSEMOVE:
  1177. curMouseXPos = LOWORD(lParam);
  1178. curMouseYPos = HIWORD(lParam);
  1179.  
  1180. return 0;
  1181.  
  1182. case WM_LBUTTONDOWN:
  1183. SetCapture(hWnd);
  1184. mouseXPos = curMouseXPos;
  1185. mouseYPos = curMouseYPos;
  1186.  
  1187. Rotating = true;
  1188. break;
  1189.  
  1190. case WM_LBUTTONUP:
  1191. ReleaseCapture();
  1192. Rotating = false;
  1193. break;
  1194.  
  1195. case WM_CLOSE:
  1196. PostQuitMessage(0);
  1197. return 0;
  1198. }
  1199.  
  1200. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  1201. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement