Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdafx.h"
- Terrain::Terrain()
- {
- mVB = nullptr;
- mIB = nullptr;
- mLayer0 = nullptr;
- mLayer1 = nullptr;
- mLayer2 = nullptr;
- mLayer3 = nullptr;
- mLayer4 = nullptr;
- mBlendMap = nullptr;
- }
- Terrain::~Terrain()
- {
- ReleaseCOM(mVB);
- ReleaseCOM(mIB);
- }
- float Terrain::width()const
- {
- return (mInfo.NumCols-1)*mInfo.CellSpacing;
- }
- float Terrain::depth()const
- {
- return (mInfo.NumRows-1)*mInfo.CellSpacing;
- }
- float Terrain::getHeight(float x, float z)const
- {
- // Transform from terrain local space to "cell" space.
- float c = (x + 0.5f*width()) / mInfo.CellSpacing;
- float d = (z - 0.5f*depth()) / -mInfo.CellSpacing;
- // Get the row and column we are in.
- int row = (int)floorf(d);
- int col = (int)floorf(c);
- // Grab the heights of the cell we are in.
- // A*--*B
- // | /|
- // |/ |
- // C*--*D
- float A = mHeightmap[row*mInfo.NumCols + col];
- float B = mHeightmap[row*mInfo.NumCols + col + 1];
- float C = mHeightmap[(row+1)*mInfo.NumCols + col];
- float D = mHeightmap[(row+1)*mInfo.NumCols + col + 1];
- // Where we are relative to the cell.
- float s = c - (float)col;
- float t = d - (float)row;
- // If upper triangle ABC.
- if( s + t <= 1.0f)
- {
- float uy = B - A;
- float vy = C - A;
- return A + s*uy + t*vy;
- }
- else // lower triangle DCB.
- {
- float uy = C - D;
- float vy = B - D;
- return D + (1.0f-s)*uy + (1.0f-t)*vy;
- }
- }
- void Terrain::BuildFX()
- {
- std::ifstream fin("Resources\\Shaders\\Terrain.fxo", std::ios::binary);
- fin.seekg(0, std::ios_base::end);
- int size = (int)fin.tellg();
- fin.seekg(0, std::ios_base::beg);
- std::vector<char> compiledShader(size);
- fin.read(&compiledShader[0], size);
- fin.close();
- HR(D3DX11CreateEffectFromMemory(&compiledShader[0], size,
- 0, pDevice, &mFX));
- }
- void Terrain::Init(const InitInfo& initInfo)
- {
- BuildFX();
- mTech = mFX->GetTechniqueByName("TerrainTech");
- mfxWVPVar = mFX->GetVariableByName("gWVP")->AsMatrix();
- mfxWorldVar = mFX->GetVariableByName("gWorld")->AsMatrix();
- mfxDirToSunVar = mFX->GetVariableByName("gDirToSunW")->AsVector();
- mfxLayer0Var = mFX->GetVariableByName("gLayer0")->AsShaderResource();
- mfxLayer1Var = mFX->GetVariableByName("gLayer1")->AsShaderResource();
- mfxLayer2Var = mFX->GetVariableByName("gLayer2")->AsShaderResource();
- mfxLayer3Var = mFX->GetVariableByName("gLayer3")->AsShaderResource();
- mfxLayer4Var = mFX->GetVariableByName("gLayer4")->AsShaderResource();
- mfxBlendMapVar = mFX->GetVariableByName("gBlendMap")->AsShaderResource();
- mInfo = initInfo;
- mNumVertices = mInfo.NumRows*mInfo.NumCols;
- mNumFaces = (mInfo.NumRows-1)*(mInfo.NumCols-1)*2;
- loadHeightMap();
- Smooth();
- BuildVertexBuffer();
- BuildIndexBuffer();
- HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName0.c_str(), 0, 0, &mLayer0, 0));
- HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName1.c_str(), 0, 0, &mLayer1, 0));
- HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName2.c_str(), 0, 0, &mLayer2, 0));
- HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName3.c_str(), 0, 0, &mLayer3, 0));
- HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.LayerMapFileName4.c_str(), 0, 0, &mLayer4, 0));
- HR(D3DX11CreateShaderResourceViewFromFile(pDevice, initInfo.BlendMapFileName.c_str(), 0, 0, &mBlendMap, 0));
- }
- void Terrain::SetDirectionToSun(const XMFLOAT3& v)
- {
- XMVECTOR temp = XMVectorSet(v.x, v.y, v.z, 0.0f);
- mfxDirToSunVar->SetFloatVector((float*)&temp);
- }
- void Terrain::draw(CXMMATRIX world, Camera& cam)
- {
- pDeviceContext->IASetInputLayout(InputLayouts::Basic32);
- UINT stride = sizeof(Vertex::Basic32);
- UINT offset = 0;
- pDeviceContext->IASetVertexBuffers(0, 1, &mVB, &stride, &offset);
- pDeviceContext->IASetIndexBuffer(mIB, DXGI_FORMAT_R32_UINT, 0);
- XMMATRIX view = cam.View();
- XMMATRIX proj = cam.Proj();
- XMMATRIX WVP = world*view*proj;
- mfxWVPVar->SetMatrix((float*)&WVP);
- mfxWorldVar->SetMatrix((float*)&world);
- mfxLayer0Var->SetResource(mLayer0);
- mfxLayer1Var->SetResource(mLayer1);
- mfxLayer2Var->SetResource(mLayer2);
- mfxLayer3Var->SetResource(mLayer3);
- mfxLayer4Var->SetResource(mLayer4);
- mfxBlendMapVar->SetResource(mBlendMap);
- D3DX11_TECHNIQUE_DESC techDesc;
- mTech->GetDesc(&techDesc);
- for(UINT i = 0; i < techDesc.Passes; ++i)
- {
- ID3DX11EffectPass* pass = mTech->GetPassByIndex(i);
- pass->Apply(0, pDeviceContext);
- pDeviceContext->DrawIndexed(mNumFaces * 3, 0, 0);
- }
- }
- void Terrain::loadHeightMap()
- {
- // A height for each vertex
- std::vector<unsigned char> in( mInfo.NumRows * mInfo.NumCols );
- // Open the file.
- std::ifstream inFile;
- inFile.open(mInfo.HeightmapFileName.c_str(), std::ios_base::binary);
- if(inFile)
- {
- // Read the RAW bytes.
- inFile.read((char*)&in[0], (std::streamsize)in.size());
- // Done with file.
- inFile.close();
- }
- // Copy the array data into a float array, and scale and offset the heights.
- mHeightmap.resize(mInfo.NumRows * mInfo.NumCols, 0);
- for(UINT i = 0; i < mInfo.NumRows * mInfo.NumCols; ++i)
- {
- mHeightmap[i] = (float)in[i] * mInfo.HeightScale + mInfo.HeightOffset;
- }
- }
- void Terrain::Smooth()
- {
- std::vector<float> dest( mHeightmap.size() );
- for(UINT i = 0; i < mInfo.NumRows; ++i)
- {
- for(UINT j = 0; j < mInfo.NumCols; ++j)
- {
- dest[i*mInfo.NumCols+j] = average(i,j);
- }
- }
- // Replace the old heightmap with the filtered one.
- mHeightmap = dest;
- }
- bool Terrain::inBounds(UINT i, UINT j)
- {
- // True if ij are valid indices; false otherwise.
- return
- i >= 0 && i < mInfo.NumRows &&
- j >= 0 && j < mInfo.NumCols;
- }
- float Terrain::average(UINT i, UINT j)
- {
- // Function computes the average height of the ij element.
- // It averages itself with its eight neighbor pixels. Note
- // that if a pixel is missing neighbor, we just don't include it
- // in the average--that is, edge pixels don't have a neighbor pixel.
- //
- // ----------
- // | 1| 2| 3|
- // ----------
- // |4 |ij| 6|
- // ----------
- // | 7| 8| 9|
- // ----------
- float avg = 0.0f;
- float num = 0.0f;
- for(UINT m = i-1; m <= i+1; ++m)
- {
- for(UINT n = j-1; n <= j+1; ++n)
- {
- if( inBounds(m,n) )
- {
- avg += mHeightmap[m*mInfo.NumCols + n];
- num += 1.0f;
- }
- }
- }
- return avg / num;
- }
- void Terrain::BuildVertexBuffer()
- {
- std::vector<Vertex::Basic32> vertices(mNumVertices);
- float halfWidth = (mInfo.NumCols-1)*mInfo.CellSpacing*0.5f;
- float halfDepth = (mInfo.NumRows-1)*mInfo.CellSpacing*0.5f;
- float du = 1.0f / (mInfo.NumCols-1);
- float dv = 1.0f / (mInfo.NumRows-1);
- for(UINT i = 0; i < mInfo.NumRows; ++i)
- {
- float z = halfDepth - i*mInfo.CellSpacing;
- for(UINT j = 0; j < mInfo.NumCols; ++j)
- {
- float x = -halfWidth + j*mInfo.CellSpacing;
- float y = mHeightmap[i*mInfo.NumCols+j];
- vertices[i*mInfo.NumCols+j].Pos = XMFLOAT3(x, y, z);
- vertices[i*mInfo.NumCols+j].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
- // Stretch texture over grid.
- vertices[i*mInfo.NumCols+j].Tex.x = j*du;
- vertices[i*mInfo.NumCols+j].Tex.y = i*dv;
- }
- }
- // Estimate normals for interior nodes using central difference.
- float invTwoDX = 1.0f / (2.0f*mInfo.CellSpacing);
- float invTwoDZ = 1.0f / (2.0f*mInfo.CellSpacing);
- for(UINT i = 2; i < mInfo.NumRows-1; ++i)
- {
- for(UINT j = 2; j < mInfo.NumCols-1; ++j)
- {
- float t = mHeightmap[(i-1)*mInfo.NumCols + j];
- float b = mHeightmap[(i+1)*mInfo.NumCols + j];
- float l = mHeightmap[i*mInfo.NumCols + j - 1];
- float r = mHeightmap[i*mInfo.NumCols + j + 1];
- XMFLOAT3 tanZ(0.0f, (t-b)*invTwoDZ, 1.0f);
- XMFLOAT3 tanX(1.0f, (r-l)*invTwoDX, 0.0f);
- //D3DXVECTOR3 N;
- XMVECTOR N;
- N = XMVector3Cross(XMLoadFloat3(&tanZ), XMLoadFloat3(&tanX));
- //D3DXVec3Cross(&N, &tanZ, &tanX);
- N = XMVector3Normalize(N);
- //D3DXVec3Normalize(&N, &N);
- //vertices[i*mInfo.NumCols+j].normal = N;
- XMStoreFloat3(&vertices[i * mInfo.NumCols + j].Normal, N);
- }
- }
- D3D11_BUFFER_DESC vbd;
- vbd.Usage = D3D11_USAGE_IMMUTABLE;
- vbd.ByteWidth = sizeof(Vertex::Basic32) * mNumVertices;
- vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- vbd.CPUAccessFlags = 0;
- vbd.MiscFlags = 0;
- D3D11_SUBRESOURCE_DATA vinitData;
- vinitData.pSysMem = &vertices[0];
- HR(pDevice->CreateBuffer(&vbd, &vinitData, &mVB));
- }
- void Terrain::BuildIndexBuffer()
- {
- std::vector<DWORD> indices(mNumFaces*3); // 3 indices per face
- // Iterate over each quad and compute indices.
- int k = 0;
- for(UINT i = 0; i < mInfo.NumRows-1; ++i)
- {
- for(UINT j = 0; j < mInfo.NumCols-1; ++j)
- {
- indices[k] = i*mInfo.NumCols+j;
- indices[k+1] = i*mInfo.NumCols+j+1;
- indices[k+2] = (i+1)*mInfo.NumCols+j;
- indices[k+3] = (i+1)*mInfo.NumCols+j;
- indices[k+4] = i*mInfo.NumCols+j+1;
- indices[k+5] = (i+1)*mInfo.NumCols+j+1;
- k += 6; // next quad
- }
- }
- D3D11_BUFFER_DESC ibd;
- ibd.Usage = D3D11_USAGE_IMMUTABLE;
- ibd.ByteWidth = sizeof(DWORD) * mNumFaces * 3;
- ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
- ibd.CPUAccessFlags = 0;
- ibd.MiscFlags = 0;
- D3D11_SUBRESOURCE_DATA iinitData;
- iinitData.pSysMem = &indices[0];
- HR(pDevice->CreateBuffer(&ibd, &iinitData, &mIB));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement