Advertisement
Guest User

terrain.cpp

a guest
Jan 6th, 2014
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.23 KB | None | 0 0
  1. #include "stdafx.h"
  2.  
  3.  
  4. Terrain::Terrain()
  5. {
  6.     mVB = nullptr;
  7.     mIB = nullptr;
  8.     mLayer0 = nullptr;
  9.     mLayer1 = nullptr;
  10.     mLayer2 = nullptr;
  11.     mLayer3 = nullptr;
  12.     mLayer4 = nullptr;
  13.     mBlendMap = nullptr;
  14. }
  15.  
  16. Terrain::~Terrain()
  17. {
  18.     ReleaseCOM(mVB);
  19.     ReleaseCOM(mIB);
  20.  
  21. }
  22.  
  23. float Terrain::width()const
  24. {
  25.     return (mInfo.NumCols-1)*mInfo.CellSpacing;
  26. }
  27.  
  28. float Terrain::depth()const
  29. {
  30.     return (mInfo.NumRows-1)*mInfo.CellSpacing;
  31. }
  32.  
  33. float Terrain::getHeight(float x, float z)const
  34. {
  35.     // Transform from terrain local space to "cell" space.
  36.     float c = (x + 0.5f*width()) /  mInfo.CellSpacing;
  37.     float d = (z - 0.5f*depth()) / -mInfo.CellSpacing;
  38.  
  39.     // Get the row and column we are in.
  40.     int row = (int)floorf(d);
  41.     int col = (int)floorf(c);
  42.  
  43.     // Grab the heights of the cell we are in.
  44.     // A*--*B
  45.     //  | /|
  46.     //  |/ |
  47.     // C*--*D
  48.     float A = mHeightmap[row*mInfo.NumCols + col];
  49.     float B = mHeightmap[row*mInfo.NumCols + col + 1];
  50.     float C = mHeightmap[(row+1)*mInfo.NumCols + col];
  51.     float D = mHeightmap[(row+1)*mInfo.NumCols + col + 1];
  52.  
  53.     // Where we are relative to the cell.
  54.     float s = c - (float)col;
  55.     float t = d - (float)row;
  56.  
  57.     // If upper triangle ABC.
  58.     if( s + t <= 1.0f)
  59.     {
  60.         float uy = B - A;
  61.         float vy = C - A;
  62.         return A + s*uy + t*vy;
  63.     }
  64.     else // lower triangle DCB.
  65.     {
  66.         float uy = C - D;
  67.         float vy = B - D;
  68.         return D + (1.0f-s)*uy + (1.0f-t)*vy;
  69.     }
  70. }
  71.  
  72. void Terrain::BuildFX()
  73. {
  74.     std::ifstream fin("Resources\\Shaders\\Terrain.fxo", std::ios::binary);
  75.  
  76.     fin.seekg(0, std::ios_base::end);
  77.     int size = (int)fin.tellg();
  78.     fin.seekg(0, std::ios_base::beg);
  79.     std::vector<char> compiledShader(size);
  80.  
  81.     fin.read(&compiledShader[0], size);
  82.     fin.close();
  83.    
  84.     HR(D3DX11CreateEffectFromMemory(&compiledShader[0], size,
  85.         0, pDevice, &mFX));
  86. }
  87.  
  88. void Terrain::Init(const InitInfo& initInfo)
  89. {
  90.     BuildFX();
  91.  
  92.     mTech          = mFX->GetTechniqueByName("TerrainTech");
  93.     mfxWVPVar      = mFX->GetVariableByName("gWVP")->AsMatrix();
  94.     mfxWorldVar    = mFX->GetVariableByName("gWorld")->AsMatrix();
  95.     mfxDirToSunVar = mFX->GetVariableByName("gDirToSunW")->AsVector();
  96.     mfxLayer0Var   = mFX->GetVariableByName("gLayer0")->AsShaderResource();
  97.     mfxLayer1Var   = mFX->GetVariableByName("gLayer1")->AsShaderResource();
  98.     mfxLayer2Var   = mFX->GetVariableByName("gLayer2")->AsShaderResource();
  99.     mfxLayer3Var   = mFX->GetVariableByName("gLayer3")->AsShaderResource();
  100.     mfxLayer4Var   = mFX->GetVariableByName("gLayer4")->AsShaderResource();
  101.     mfxBlendMapVar = mFX->GetVariableByName("gBlendMap")->AsShaderResource();
  102.  
  103.     mInfo = initInfo;
  104.  
  105.     mNumVertices = mInfo.NumRows*mInfo.NumCols;
  106.     mNumFaces    = (mInfo.NumRows-1)*(mInfo.NumCols-1)*2;
  107.  
  108.     loadHeightMap();
  109.     Smooth();
  110.  
  111.     BuildVertexBuffer();
  112.     BuildIndexBuffer();
  113.  
  114.  
  115.     HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName0.c_str(), 0, 0, &mLayer0, 0));
  116.     HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName1.c_str(), 0, 0, &mLayer1, 0));
  117.     HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName2.c_str(), 0, 0, &mLayer2, 0));
  118.     HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName3.c_str(), 0, 0, &mLayer3, 0));
  119.     HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName4.c_str(), 0, 0, &mLayer4, 0));
  120.     HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.BlendMapFileName.c_str(), 0, 0, &mBlendMap, 0));
  121. }
  122.  
  123. void Terrain::SetDirectionToSun(const XMFLOAT3& v)
  124. {
  125.     XMVECTOR temp = XMVectorSet(v.x, v.y, v.z, 0.0f);
  126.     mfxDirToSunVar->SetFloatVector((float*)&temp);
  127. }
  128.  
  129. void Terrain::draw(CXMMATRIX world, Camera& cam)
  130. {
  131.     pDeviceContext->IASetInputLayout(InputLayouts::Basic32);
  132.  
  133.     UINT stride = sizeof(Vertex::Basic32);
  134.     UINT offset = 0;
  135.     pDeviceContext->IASetVertexBuffers(0, 1, &mVB, &stride, &offset);
  136.     pDeviceContext->IASetIndexBuffer(mIB, DXGI_FORMAT_R32_UINT, 0);
  137.  
  138.     XMMATRIX view = cam.View();
  139.     XMMATRIX proj = cam.Proj();
  140.  
  141.     XMMATRIX WVP = world*view*proj;
  142.  
  143.  
  144.     mfxWVPVar->SetMatrix((float*)&WVP);
  145.     mfxWorldVar->SetMatrix((float*)&world);
  146.  
  147.     mfxLayer0Var->SetResource(mLayer0);
  148.     mfxLayer1Var->SetResource(mLayer1);
  149.     mfxLayer2Var->SetResource(mLayer2);
  150.     mfxLayer3Var->SetResource(mLayer3);
  151.     mfxLayer4Var->SetResource(mLayer4);
  152.     mfxBlendMapVar->SetResource(mBlendMap);
  153.  
  154.     D3DX11_TECHNIQUE_DESC techDesc;
  155.     mTech->GetDesc(&techDesc);
  156.  
  157.     for(UINT i = 0; i < techDesc.Passes; ++i)
  158.     {
  159.         ID3DX11EffectPass* pass = mTech->GetPassByIndex(i);
  160.         pass->Apply(0, pDeviceContext);
  161.  
  162.         pDeviceContext->DrawIndexed(mNumFaces * 3, 0, 0);
  163.     }  
  164. }
  165.  
  166. void Terrain::loadHeightMap()
  167. {
  168.     // A height for each vertex
  169.     std::vector<unsigned char> in( mInfo.NumRows * mInfo.NumCols );
  170.  
  171.     // Open the file.
  172.     std::ifstream inFile;
  173.     inFile.open(mInfo.HeightmapFileName.c_str(), std::ios_base::binary);
  174.  
  175.     if(inFile)
  176.     {
  177.         // Read the RAW bytes.
  178.         inFile.read((char*)&in[0], (std::streamsize)in.size());
  179.  
  180.         // Done with file.
  181.         inFile.close();
  182.     }
  183.  
  184.     // Copy the array data into a float array, and scale and offset the heights.
  185.     mHeightmap.resize(mInfo.NumRows * mInfo.NumCols, 0);
  186.     for(UINT i = 0; i < mInfo.NumRows * mInfo.NumCols; ++i)
  187.     {
  188.         mHeightmap[i] = (float)in[i] * mInfo.HeightScale + mInfo.HeightOffset;
  189.     }
  190. }
  191.  
  192.  
  193. void Terrain::Smooth()
  194. {
  195.     std::vector<float> dest( mHeightmap.size() );
  196.  
  197.     for(UINT i = 0; i < mInfo.NumRows; ++i)
  198.     {
  199.         for(UINT j = 0; j < mInfo.NumCols; ++j)
  200.         {
  201.             dest[i*mInfo.NumCols+j] = average(i,j);
  202.         }
  203.     }
  204.  
  205.     // Replace the old heightmap with the filtered one.
  206.     mHeightmap = dest;
  207. }
  208.  
  209. bool Terrain::inBounds(UINT i, UINT j)
  210. {
  211.     // True if ij are valid indices; false otherwise.
  212.     return
  213.         i >= 0 && i < mInfo.NumRows &&
  214.         j >= 0 && j < mInfo.NumCols;
  215. }
  216.  
  217. float Terrain::average(UINT i, UINT j)
  218. {
  219.     // Function computes the average height of the ij element.
  220.     // It averages itself with its eight neighbor pixels.  Note
  221.     // that if a pixel is missing neighbor, we just don't include it
  222.     // in the average--that is, edge pixels don't have a neighbor pixel.
  223.     //
  224.     // ----------
  225.     // | 1| 2| 3|
  226.     // ----------
  227.     // |4 |ij| 6|
  228.     // ----------
  229.     // | 7| 8| 9|
  230.     // ----------
  231.  
  232.     float avg = 0.0f;
  233.     float num = 0.0f;
  234.  
  235.     for(UINT m = i-1; m <= i+1; ++m)
  236.     {
  237.         for(UINT n = j-1; n <= j+1; ++n)
  238.         {
  239.             if( inBounds(m,n) )
  240.             {
  241.                 avg += mHeightmap[m*mInfo.NumCols + n];
  242.                 num += 1.0f;
  243.             }
  244.         }
  245.     }
  246.  
  247.     return avg / num;
  248. }
  249.    
  250.  
  251. void Terrain::BuildVertexBuffer()
  252. {
  253.     std::vector<Vertex::Basic32> vertices(mNumVertices);
  254.  
  255.     float halfWidth = (mInfo.NumCols-1)*mInfo.CellSpacing*0.5f;
  256.     float halfDepth = (mInfo.NumRows-1)*mInfo.CellSpacing*0.5f;
  257.  
  258.     float du = 1.0f / (mInfo.NumCols-1);
  259.     float dv = 1.0f / (mInfo.NumRows-1);
  260.     for(UINT i = 0; i < mInfo.NumRows; ++i)
  261.     {
  262.         float z = halfDepth - i*mInfo.CellSpacing;
  263.         for(UINT j = 0; j < mInfo.NumCols; ++j)
  264.         {
  265.             float x = -halfWidth + j*mInfo.CellSpacing;
  266.  
  267.             float y = mHeightmap[i*mInfo.NumCols+j];
  268.             vertices[i*mInfo.NumCols+j].Pos    = XMFLOAT3(x, y, z);
  269.             vertices[i*mInfo.NumCols+j].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
  270.  
  271.             // Stretch texture over grid.
  272.             vertices[i*mInfo.NumCols+j].Tex.x = j*du;
  273.             vertices[i*mInfo.NumCols+j].Tex.y = i*dv;
  274.         }
  275.     }
  276.  
  277.     // Estimate normals for interior nodes using central difference.
  278.     float invTwoDX = 1.0f / (2.0f*mInfo.CellSpacing);
  279.     float invTwoDZ = 1.0f / (2.0f*mInfo.CellSpacing);
  280.     for(UINT i = 2; i < mInfo.NumRows-1; ++i)
  281.     {
  282.         for(UINT j = 2; j < mInfo.NumCols-1; ++j)
  283.         {
  284.             float t = mHeightmap[(i-1)*mInfo.NumCols + j];
  285.             float b = mHeightmap[(i+1)*mInfo.NumCols + j];
  286.             float l = mHeightmap[i*mInfo.NumCols + j - 1];
  287.             float r = mHeightmap[i*mInfo.NumCols + j + 1];
  288.  
  289.             XMFLOAT3 tanZ(0.0f, (t-b)*invTwoDZ, 1.0f);
  290.             XMFLOAT3 tanX(1.0f, (r-l)*invTwoDX, 0.0f);
  291.  
  292.             //D3DXVECTOR3 N;
  293.             XMVECTOR N;
  294.             N = XMVector3Cross(XMLoadFloat3(&tanZ), XMLoadFloat3(&tanX));
  295.  
  296.             //D3DXVec3Cross(&N, &tanZ, &tanX);
  297.             N = XMVector3Normalize(N);
  298.             //D3DXVec3Normalize(&N, &N);
  299.  
  300.             //vertices[i*mInfo.NumCols+j].normal = N;
  301.             XMStoreFloat3(&vertices[i * mInfo.NumCols + j].Normal, N);
  302.  
  303.         }
  304.     }
  305.  
  306.     D3D11_BUFFER_DESC vbd;
  307.     vbd.Usage = D3D11_USAGE_IMMUTABLE;
  308.     vbd.ByteWidth = sizeof(Vertex::Basic32) * mNumVertices;
  309.     vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  310.     vbd.CPUAccessFlags = 0;
  311.     vbd.MiscFlags = 0;
  312.     D3D11_SUBRESOURCE_DATA vinitData;
  313.     vinitData.pSysMem = &vertices[0];
  314.     HR(pDevice->CreateBuffer(&vbd, &vinitData, &mVB));
  315. }
  316.  
  317.  
  318. void Terrain::BuildIndexBuffer()
  319. {
  320.     std::vector<DWORD> indices(mNumFaces*3); // 3 indices per face
  321.  
  322.     // Iterate over each quad and compute indices.
  323.     int k = 0;
  324.     for(UINT i = 0; i < mInfo.NumRows-1; ++i)
  325.     {
  326.         for(UINT j = 0; j < mInfo.NumCols-1; ++j)
  327.         {
  328.             indices[k]   = i*mInfo.NumCols+j;
  329.             indices[k+1] = i*mInfo.NumCols+j+1;
  330.             indices[k+2] = (i+1)*mInfo.NumCols+j;
  331.  
  332.             indices[k+3] = (i+1)*mInfo.NumCols+j;
  333.             indices[k+4] = i*mInfo.NumCols+j+1;
  334.             indices[k+5] = (i+1)*mInfo.NumCols+j+1;
  335.  
  336.             k += 6; // next quad
  337.         }
  338.     }
  339.  
  340.     D3D11_BUFFER_DESC ibd;
  341.     ibd.Usage = D3D11_USAGE_IMMUTABLE;
  342.     ibd.ByteWidth = sizeof(DWORD) * mNumFaces * 3;
  343.     ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
  344.     ibd.CPUAccessFlags = 0;
  345.     ibd.MiscFlags = 0;
  346.     D3D11_SUBRESOURCE_DATA iinitData;
  347.     iinitData.pSysMem = &indices[0];
  348.     HR(pDevice->CreateBuffer(&ibd, &iinitData, &mIB));
  349. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement