Added follow cam
Added "Controlled" mesh classes Added Global Lighting Class Added Gamepad controls Split terrain nodes into Height and Perlin classes Fixed Splitmesh node stuff
This commit is contained in:
@ -2,9 +2,8 @@
|
||||
|
||||
#define WORLD_HEIGHT 1024
|
||||
|
||||
TerrainNode::TerrainNode(wstring name, wstring heightMap, wstring seed, float waterHeight, wstring waterNormalMap, int widthX, int widthZ, int cellSizeX, int cellSizeZ) : SceneNode(name)
|
||||
{
|
||||
_heightMap = heightMap;
|
||||
TerrainNode::TerrainNode(wstring name, wstring seed, float waterHeight, int widthX, int widthZ, int cellSizeX, int cellSizeZ) : SceneNode(name)
|
||||
{
|
||||
_seedString = seed;
|
||||
_seedHash = std::hash<wstring>{}(_seedString);
|
||||
|
||||
@ -20,11 +19,10 @@ TerrainNode::TerrainNode(wstring name, wstring heightMap, wstring seed, float wa
|
||||
_cellSizeZ = cellSizeZ;
|
||||
|
||||
_waterHeight = waterHeight;
|
||||
_waterNormalMapName = waterNormalMap;
|
||||
|
||||
_polygonsCount = (_gridCols * _gridRows) * 2;
|
||||
_vertexCount = _polygonsCount * 2;
|
||||
_indiciesCount = _polygonsCount * 3;
|
||||
_indicesCount = _polygonsCount * 3;
|
||||
}
|
||||
|
||||
void TerrainNode::SetAmbientLight(XMFLOAT4 ambientLight)
|
||||
@ -43,38 +41,18 @@ void TerrainNode::SetDirectionalLight(FXMVECTOR lightVector, XMFLOAT4 lightColor
|
||||
XMStoreFloat4(&_directionalLightVector, lightVector);
|
||||
}
|
||||
|
||||
void TerrainNode::SetCameraPosition(XMFLOAT4 cameraPosition)
|
||||
{
|
||||
_cameraPosition = cameraPosition;
|
||||
}
|
||||
|
||||
bool TerrainNode::Initialise()
|
||||
{
|
||||
_device = DirectXFramework::GetDXFramework()->GetDevice();
|
||||
_deviceContext = DirectXFramework::GetDXFramework()->GetDeviceContext();
|
||||
|
||||
if (_device.Get() == nullptr || _deviceContext.Get() == nullptr)
|
||||
if (_device.Get() == nullptr || _deviceContext.Get() == nullptr || _initError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_heightMap.length() > 0)
|
||||
{
|
||||
if (LoadHeightMap(_heightMap))
|
||||
{
|
||||
_usedHeightMap = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_usedHeightMap = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_usedHeightMap = false;
|
||||
}
|
||||
|
||||
GenerateTerrainData();
|
||||
GenerateTerrainNormals();
|
||||
LoadTerrainTextures();
|
||||
GenerateBlendMap();
|
||||
BuildExtraMaps();
|
||||
@ -89,7 +67,7 @@ bool TerrainNode::Initialise()
|
||||
}
|
||||
|
||||
void TerrainNode::GenerateTerrainData()
|
||||
{
|
||||
{
|
||||
float totalWidth = (float)(_gridCols * _cellSizeX);
|
||||
float totalDepth = (float)(_gridRows * _cellSizeZ);
|
||||
|
||||
@ -121,16 +99,16 @@ void TerrainNode::GenerateTerrainData()
|
||||
offsetIndexZ = 0;
|
||||
}
|
||||
|
||||
float rUA = 0.0f;
|
||||
float rVA = rUA; // 0.0f;
|
||||
float rUB = 1.0f;
|
||||
float rVB = rUB;
|
||||
// Generate pairs of random UV's
|
||||
float rUA = SharedMethods::GenerateRandomUV(0.0f, 0.25f);
|
||||
float rVA = SharedMethods::GenerateRandomUV(0.0f, 0.25f); //rUA; // 0.0f;
|
||||
float rUB = SharedMethods::GenerateRandomUV(0.75f, 1.0f);
|
||||
float rVB = SharedMethods::GenerateRandomUV(0.75f, 1.0f); //rUB;
|
||||
|
||||
|
||||
/*int tumbleAmount = rand() % 10;
|
||||
// Rotate the UV's around a bit to add some more variance
|
||||
int tumbleAmount = rand() % 10;
|
||||
|
||||
float prevUV = 0.0f;
|
||||
bool firstTumble = true;
|
||||
for (int ti = 0; ti < tumbleAmount; ti++)
|
||||
{
|
||||
prevUV = rVB;
|
||||
@ -138,11 +116,11 @@ void TerrainNode::GenerateTerrainData()
|
||||
rUB = rVA;
|
||||
rVA = rUA;
|
||||
rUA = prevUV;
|
||||
}*/
|
||||
}
|
||||
|
||||
// TL
|
||||
TerrainVertex vertex{};
|
||||
vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex), (-z + 1) * _cellSizeZ + centerDepth);
|
||||
vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightValueAt(currentIndex), (-z + 1) * _cellSizeZ + centerDepth);
|
||||
vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(rUA, rVA);
|
||||
vertex.BlendMapTexCoord = XMFLOAT2((bu * x), (bv * z));
|
||||
@ -150,7 +128,7 @@ void TerrainNode::GenerateTerrainData()
|
||||
|
||||
// TR
|
||||
vertex = TerrainVertex();
|
||||
vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexX), (-z + 1) * _cellSizeZ + centerDepth);
|
||||
vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightValueAt(currentIndex + offsetIndexX), (-z + 1) * _cellSizeZ + centerDepth);
|
||||
vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(rUB, rVA);
|
||||
vertex.BlendMapTexCoord = XMFLOAT2((bu * (x + 1)), (bv * z));
|
||||
@ -158,7 +136,7 @@ void TerrainNode::GenerateTerrainData()
|
||||
|
||||
// BL
|
||||
vertex = TerrainVertex();
|
||||
vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexZ), -z * _cellSizeZ + centerDepth);
|
||||
vertex.Position = XMFLOAT3(x * _cellSizeX + centerWidth, GetHeightValueAt(currentIndex + offsetIndexZ), -z * _cellSizeZ + centerDepth);
|
||||
vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(rUA, rVB);
|
||||
vertex.BlendMapTexCoord = XMFLOAT2((bu * x), (bv * (z + 1)));
|
||||
@ -166,7 +144,7 @@ void TerrainNode::GenerateTerrainData()
|
||||
|
||||
// BR
|
||||
vertex = TerrainVertex();
|
||||
vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightMapValueAt(currentIndex + offsetIndexZ + offsetIndexX), -z * _cellSizeZ + centerDepth);
|
||||
vertex.Position = XMFLOAT3((x + 1) * _cellSizeX + centerWidth, GetHeightValueAt(currentIndex + offsetIndexZ + offsetIndexX), -z * _cellSizeZ + centerDepth);
|
||||
vertex.Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);
|
||||
vertex.TexCoord = XMFLOAT2(rUB, rVB);
|
||||
vertex.BlendMapTexCoord = XMFLOAT2((bu * (x + 1)), (bv * (z + 1)));
|
||||
@ -182,7 +160,10 @@ void TerrainNode::GenerateTerrainData()
|
||||
currentVertexCount += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainNode::GenerateTerrainNormals()
|
||||
{
|
||||
int currentNormalIndex = 0;
|
||||
for (int z = 0; z < _gridRows; z++)
|
||||
{
|
||||
@ -243,6 +224,13 @@ void TerrainNode::AddNormalToVertex(int row, int col, int vertexIndex, XMVECTOR
|
||||
}
|
||||
}
|
||||
|
||||
float TerrainNode::GetHeightValueAt(int index)
|
||||
{
|
||||
float result = _heightValues[index] * WORLD_HEIGHT; // +(rand() % 10);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TerrainNode::GenerateBuffers()
|
||||
{
|
||||
// Setup the structure that specifies how big the vertex
|
||||
@ -267,7 +255,7 @@ void TerrainNode::GenerateBuffers()
|
||||
// buffer should be
|
||||
D3D11_BUFFER_DESC indexBufferDescriptor;
|
||||
indexBufferDescriptor.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
indexBufferDescriptor.ByteWidth = sizeof(UINT) * _indiciesCount;
|
||||
indexBufferDescriptor.ByteWidth = sizeof(UINT) * _indicesCount;
|
||||
indexBufferDescriptor.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
indexBufferDescriptor.CPUAccessFlags = 0;
|
||||
indexBufferDescriptor.MiscFlags = 0;
|
||||
@ -302,13 +290,13 @@ void TerrainNode::Render()
|
||||
XMStoreFloat4(&cBuffer.cameraPosition, DirectXFramework::GetDXFramework()->GetCamera()->GetCameraPosition());
|
||||
|
||||
cBuffer.waterHeight = _waterHeight;
|
||||
cBuffer.waterShininess = 15.0f;
|
||||
cBuffer.waterShininess = 10.0f;
|
||||
cBuffer.waterColor = _waterColor;
|
||||
|
||||
_deviceContext->PSSetShaderResources(0, 1, _blendMapResourceView.GetAddressOf());
|
||||
_deviceContext->PSSetShaderResources(1, 1, _texturesResourceView.GetAddressOf());
|
||||
_deviceContext->PSSetShaderResources(2, 1, _waterNormalMap.GetAddressOf());
|
||||
_deviceContext->PSSetShaderResources(3, 1, _rngNoiseMap.GetAddressOf());
|
||||
_deviceContext->PSSetShaderResources(3, 1, _snowTest.GetAddressOf());
|
||||
|
||||
_deviceContext->VSSetShader(_vertexShader.Get(), 0, 0);
|
||||
_deviceContext->PSSetShader(_pixelShader.Get(), 0, 0);
|
||||
@ -320,7 +308,7 @@ void TerrainNode::Render()
|
||||
_deviceContext->IASetIndexBuffer(_indexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
|
||||
cBuffer.diffuseCoefficient = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.0f);
|
||||
cBuffer.specularCoefficient = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
cBuffer.shininess = 10.0f;
|
||||
cBuffer.shininess = 5.0f;
|
||||
cBuffer.opacity = 1.0f;
|
||||
|
||||
// Update the constant buffer
|
||||
@ -330,7 +318,7 @@ void TerrainNode::Render()
|
||||
_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
//_deviceContext->RSSetState(_wireframeRasteriserState.Get());
|
||||
_deviceContext->DrawIndexed(_indiciesCount, 0, 0);
|
||||
_deviceContext->DrawIndexed(_indicesCount, 0, 0);
|
||||
}
|
||||
|
||||
void TerrainNode::Shutdown(void)
|
||||
@ -425,41 +413,6 @@ void TerrainNode::BuildRendererStates()
|
||||
ThrowIfFailed(_device->CreateRasterizerState(&rasteriserDesc, _wireframeRasteriserState.GetAddressOf()));
|
||||
}
|
||||
|
||||
bool TerrainNode::LoadHeightMap(wstring heightMapFilename)
|
||||
{
|
||||
unsigned int mapSize = _gridCols * _gridRows;
|
||||
USHORT* rawFileValues = new USHORT[mapSize];
|
||||
|
||||
std::ifstream inputHeightMap;
|
||||
inputHeightMap.open(heightMapFilename.c_str(), std::ios_base::binary);
|
||||
if (!inputHeightMap)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inputHeightMap.read((char*)rawFileValues, mapSize * 2);
|
||||
inputHeightMap.close();
|
||||
|
||||
// Normalise BYTE values to the range 0.0f - 1.0f;
|
||||
for (unsigned int i = 0; i < mapSize; i++)
|
||||
{
|
||||
_heightValues.push_back((float)rawFileValues[i] / 65536);
|
||||
}
|
||||
delete[] rawFileValues;
|
||||
return true;
|
||||
}
|
||||
|
||||
float TerrainNode::GetHeightMapValueAt(int index)
|
||||
{
|
||||
float result = 0;
|
||||
if (_usedHeightMap)
|
||||
{
|
||||
result = _heightValues[index] * WORLD_HEIGHT; // +(rand() % 10);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TerrainNode::LoadTerrainTextures()
|
||||
{
|
||||
// Change the paths below as appropriate for your use
|
||||
@ -535,18 +488,26 @@ void TerrainNode::LoadTerrainTextures()
|
||||
viewDescription.Texture2DArray.ArraySize = 5;
|
||||
|
||||
ThrowIfFailed(_device->CreateShaderResourceView(textureArray.Get(), &viewDescription, _texturesResourceView.GetAddressOf()));
|
||||
|
||||
// Cheeky load in the snow hack to solve that weird issue
|
||||
wstring snowTestName = L"Textures\\snow.dds";
|
||||
ThrowIfFailed(CreateDDSTextureFromFile(_device.Get(),
|
||||
snowTestName.c_str(),
|
||||
nullptr,
|
||||
_snowTest.GetAddressOf()
|
||||
));
|
||||
}
|
||||
|
||||
void TerrainNode::GenerateBlendMap()
|
||||
{
|
||||
RGBA snowTops = RGBA{ 0u, 0u, 0u, 255u };
|
||||
RGBA grassLand = RGBA{ 0u, 0u, 50u, 0u };
|
||||
RGBA grassLand = RGBA{ 0u, 0u, 0u, 0u };
|
||||
RGBA lightDirt = RGBA{ 50u, 0u, 255u, 0u };
|
||||
RGBA darkDirt = RGBA{ 255u, 0u, 0u, 0u };
|
||||
RGBA darkDirt = RGBA{ 255u, 50u, 50u, 0u };
|
||||
|
||||
vector<RGBA> colorSteps = {darkDirt, lightDirt, grassLand, grassLand, grassLand, snowTops};
|
||||
|
||||
ColorGradient terrainBlendGradient = ColorGradient(30.0f, 650.0f, colorSteps);
|
||||
ColorGradient terrainBlendGradient = ColorGradient(80.0f, 620.0f, colorSteps);
|
||||
|
||||
// Note that _numberOfRows and _numberOfColumns need to be setup
|
||||
// to the number of rows and columns in your grid in order for this
|
||||
@ -563,7 +524,10 @@ void TerrainNode::GenerateBlendMap()
|
||||
{
|
||||
for (DWORD j = 0; j < _gridCols; j++)
|
||||
{
|
||||
|
||||
r = 0u;
|
||||
g = 0u;
|
||||
b = 0u;
|
||||
a = 0u;
|
||||
// Calculate the appropriate blend colour for the
|
||||
// current location in the blend map. This has been
|
||||
// left as an exercise for you. You need to calculate
|
||||
@ -588,10 +552,10 @@ void TerrainNode::GenerateBlendMap()
|
||||
float avgHeight = totalHeights / 4.0f;
|
||||
|
||||
RGBA currentBlend = terrainBlendGradient.GetRGBAValue(avgHeight);
|
||||
r = currentBlend.red;
|
||||
g = currentBlend.green;
|
||||
b = currentBlend.blue;
|
||||
a = currentBlend.alpha;
|
||||
r = (BYTE)currentBlend.red;
|
||||
g = (BYTE)currentBlend.green;
|
||||
b = (BYTE)currentBlend.blue;
|
||||
a = (BYTE)currentBlend.alpha;
|
||||
|
||||
DWORD mapValue = (a << 24) + (b << 16) + (g << 8) + r;
|
||||
*blendMapPtr++ = mapValue;
|
||||
@ -635,17 +599,71 @@ void TerrainNode::BuildExtraMaps()
|
||||
// Initialise method (and make the corresponding call to
|
||||
// CoUninitialize in the Shutdown method). Otherwise,
|
||||
// the following call will throw an exception
|
||||
wstring waterNormalMapName = L"Textures\\waterNormals.bmp";
|
||||
ThrowIfFailed(CreateWICTextureFromFile(_device.Get(),
|
||||
_deviceContext.Get(),
|
||||
_waterNormalMapName.c_str(),
|
||||
waterNormalMapName.c_str(),
|
||||
nullptr,
|
||||
_waterNormalMap.GetAddressOf()
|
||||
));
|
||||
}
|
||||
|
||||
ThrowIfFailed(CreateWICTextureFromFile(_device.Get(),
|
||||
_deviceContext.Get(),
|
||||
L"Textures\\noiseMap.png",
|
||||
nullptr,
|
||||
_rngNoiseMap.GetAddressOf()
|
||||
));
|
||||
float TerrainNode::GetHeightAtPoint(float x, float z, bool waterCollide)
|
||||
{
|
||||
int cellX = (int)((x - _terrainStartX) / _cellSizeX);
|
||||
int cellZ = (int)((_terrainStartZ - z) / _cellSizeZ);
|
||||
|
||||
int currentIndex = (cellZ * _gridCols * 4) + (cellX * 4);
|
||||
|
||||
float dx = x - _terrainVerts[currentIndex].Position.x;
|
||||
float dz = z - _terrainVerts[currentIndex].Position.z;
|
||||
|
||||
int currentNormalIndex = ((cellZ * _gridCols) + cellX) * 6;
|
||||
if (dx < dz)
|
||||
{
|
||||
currentNormalIndex += 3;
|
||||
}
|
||||
|
||||
XMVECTOR v1 = XMVectorSet(_terrainVerts[_indices[currentNormalIndex + 1]].Position.x - _terrainVerts[_indices[currentNormalIndex]].Position.x,
|
||||
_terrainVerts[_indices[currentNormalIndex + 1]].Position.y - _terrainVerts[_indices[currentNormalIndex]].Position.y,
|
||||
_terrainVerts[_indices[currentNormalIndex + 1]].Position.z - _terrainVerts[_indices[currentNormalIndex]].Position.z,
|
||||
0.0f);
|
||||
XMVECTOR v2 = XMVectorSet(_terrainVerts[_indices[currentNormalIndex + 2]].Position.x - _terrainVerts[_indices[currentNormalIndex]].Position.x,
|
||||
_terrainVerts[_indices[currentNormalIndex + 2]].Position.y - _terrainVerts[_indices[currentNormalIndex]].Position.y,
|
||||
_terrainVerts[_indices[currentNormalIndex + 2]].Position.z - _terrainVerts[_indices[currentNormalIndex]].Position.z,
|
||||
0.0f);
|
||||
|
||||
XMFLOAT4 normal;
|
||||
XMStoreFloat4(&normal, XMVector3Normalize(XMVector3Cross(v1, v2)));
|
||||
|
||||
float result = _terrainVerts[currentIndex].Position.y + (normal.x * dx + normal.z * dz) / -normal.y;
|
||||
if (waterCollide)
|
||||
{
|
||||
if (result <= _waterHeight)
|
||||
{
|
||||
result = _waterHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TerrainNode::CheckXBoundary(float x)
|
||||
{
|
||||
if (!(x > _terrainStartX && x < _terrainEndX))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TerrainNode::CheckZBoundary(float z)
|
||||
{
|
||||
if (!(z < _terrainStartZ && z > _terrainEndZ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
Reference in New Issue
Block a user