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:
iDunnoDev
2022-05-09 17:50:22 +01:00
committed by iDunnoDev
parent bc906064e5
commit f6bba67897
58 changed files with 1743 additions and 351 deletions

View File

@ -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;
}