Added Comments
Added ability to hold shift and skip the terrain generation when loading Added ability for the perlin terrain to save a raw image of the terrain to use as a cache
This commit is contained in:
@ -4,9 +4,11 @@
|
||||
|
||||
TerrainNode::TerrainNode(wstring name, wstring seed, float waterHeight, int widthX, int widthZ, int cellSizeX, int cellSizeZ) : SceneNode(name)
|
||||
{
|
||||
// Get the seed string and hash it
|
||||
_seedString = seed;
|
||||
_seedHash = std::hash<wstring>{}(_seedString);
|
||||
_seedHash = (unsigned int)std::hash<wstring>{}(_seedString);
|
||||
|
||||
// Set the random seed number
|
||||
srand(_seedHash);
|
||||
|
||||
_widthX = widthX;
|
||||
@ -83,9 +85,9 @@ void TerrainNode::GenerateTerrainData()
|
||||
float bv = 1.0f / (float)(_gridRows - 1u);
|
||||
|
||||
int currentVertexCount = 0;
|
||||
for (int z = 0; z < _gridRows; z++)
|
||||
for (int z = 0; z < (int)_gridRows; z++)
|
||||
{
|
||||
for (int x = 0; x < _gridCols; x++)
|
||||
for (int x = 0; x < (int)_gridCols; x++)
|
||||
{
|
||||
int currentIndex = (z * _gridCols) + x;
|
||||
int offsetIndexX = 1;
|
||||
@ -165,9 +167,9 @@ void TerrainNode::GenerateTerrainData()
|
||||
void TerrainNode::GenerateTerrainNormals()
|
||||
{
|
||||
int currentNormalIndex = 0;
|
||||
for (int z = 0; z < _gridRows; z++)
|
||||
for (int z = 0; z < (int)_gridRows; z++)
|
||||
{
|
||||
for (int x = 0; x < _gridCols; x++)
|
||||
for (int x = 0; x < (int)_gridCols; x++)
|
||||
{
|
||||
XMVECTOR v1 = XMVectorSet(_terrainVerts[currentNormalIndex + 1].Position.x - _terrainVerts[currentNormalIndex].Position.x,
|
||||
_terrainVerts[currentNormalIndex + 1].Position.y - _terrainVerts[currentNormalIndex].Position.y,
|
||||
@ -185,6 +187,7 @@ void TerrainNode::GenerateTerrainNormals()
|
||||
XMStoreFloat3(&_terrainVerts[currentNormalIndex + 2].Normal, XMVectorAdd(XMLoadFloat3(&_terrainVerts[currentNormalIndex + 2].Normal), polygonNormal));
|
||||
XMStoreFloat3(&_terrainVerts[currentNormalIndex + 3].Normal, XMVectorAdd(XMLoadFloat3(&_terrainVerts[currentNormalIndex + 3].Normal), polygonNormal));
|
||||
|
||||
// Process all the connected normals
|
||||
AddNormalToVertex(z - 1, x - 1, 3, polygonNormal);
|
||||
AddNormalToVertex(z - 1, x, 2, polygonNormal);
|
||||
AddNormalToVertex(z - 1, x, 3, polygonNormal);
|
||||
@ -218,6 +221,7 @@ void TerrainNode::AddNormalToVertex(int row, int col, int vertexIndex, XMVECTOR
|
||||
|
||||
int finalIndex = vertexIndex + ((rowIndexOffset + colIndexOffset) * 4);
|
||||
|
||||
// Check if the index is not around the edges
|
||||
if (row >= 0 && row < (int)_gridRows && col >= 0 && col < (int)_gridCols)
|
||||
{
|
||||
XMStoreFloat3(&_terrainVerts[finalIndex].Normal, XMVectorAdd(XMLoadFloat3(&_terrainVerts[finalIndex].Normal), normal));
|
||||
@ -498,13 +502,15 @@ void TerrainNode::LoadTerrainTextures()
|
||||
));
|
||||
}
|
||||
|
||||
// Method for populating the terrain with random clutter described in the structs
|
||||
void TerrainNode::PopulateTerrain(SceneGraphPointer currentSceneGraph, vector<TerrainPopNode>& nodesForPop, int xStep, int zStep, float heightLower, float heightUpper, float slopeLower, float slopeUpper)
|
||||
{
|
||||
for (int z = 0; z < _gridRows; z += zStep)
|
||||
// Step through the z and x with the given spacing
|
||||
for (int z = 0; z < (int)_gridRows; z += zStep)
|
||||
{
|
||||
for (int x = 0; x < _gridCols; x += xStep)
|
||||
for (int x = 0; x < (int)_gridCols; x += xStep)
|
||||
{
|
||||
int currentIndex = ((z * _gridCols) + x) * 4;
|
||||
int currentIndex = ((z * (int)_gridCols) + x) * 4;
|
||||
|
||||
float totalHeights = 0.0f;
|
||||
float totalSlope = 0.0f;
|
||||
@ -516,12 +522,15 @@ void TerrainNode::PopulateTerrain(SceneGraphPointer currentSceneGraph, vector<Te
|
||||
|
||||
float heightValue = totalHeights / 4.0f;
|
||||
|
||||
// If the height value is within the given range
|
||||
if (heightValue >= heightLower && heightValue <= heightUpper)
|
||||
{
|
||||
float avgSlope = totalSlope / 4.0f;
|
||||
|
||||
// If the slope value is within the given range
|
||||
if (avgSlope >= slopeLower && avgSlope <= slopeUpper)
|
||||
{
|
||||
// The Height level and slope values are in range, create a mesh node with the provided details
|
||||
int nodeIndex = 0;
|
||||
if (nodesForPop.size() > 1)
|
||||
{
|
||||
@ -529,12 +538,13 @@ void TerrainNode::PopulateTerrain(SceneGraphPointer currentSceneGraph, vector<Te
|
||||
}
|
||||
|
||||
float scale = (rand() % 100 * 0.01f) * nodesForPop[nodeIndex].scaleFactor;
|
||||
float yRotation = rand() % 360;
|
||||
float yRotation = (float)(rand() % 360);
|
||||
|
||||
float xPos = x * _cellSizeX + _terrainStartX;
|
||||
float yPos = heightValue;
|
||||
float zPos = (-z + 1) * _cellSizeZ + _terrainStartZ;
|
||||
|
||||
// Made a unique name to stop conflicts
|
||||
wstring nodeName = L"_" + to_wstring(z) + L"_" + to_wstring(x);
|
||||
shared_ptr<MeshNode> newNode = make_shared<MeshNode>(nodesForPop[nodeIndex].nodeBaseName + nodeName, nodesForPop[nodeIndex].modelName);
|
||||
newNode->SetWorldTransform(XMMatrixRotationAxis(XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f), yRotation * XM_PI / 180.0f) * XMMatrixScaling(scale, scale, scale) * XMMatrixTranslation(xPos, yPos, zPos));
|
||||
@ -547,11 +557,13 @@ void TerrainNode::PopulateTerrain(SceneGraphPointer currentSceneGraph, vector<Te
|
||||
|
||||
void TerrainNode::GenerateBlendMap()
|
||||
{
|
||||
// Set up the color gradients for each type of texture
|
||||
RGBA snowTops = RGBA{ 0u, 0u, 0u, 255u };
|
||||
RGBA grassLand = RGBA{ 0u, 0u, 0u, 0u };
|
||||
RGBA lightDirt = RGBA{ 50u, 0u, 255u, 0u };
|
||||
RGBA darkDirt = RGBA{ 255u, 50u, 50u, 0u };
|
||||
|
||||
// Create a vector of these gradients, multiple grass because i want it to cover more area, i need to come up with a better way if i have time
|
||||
vector<RGBA> colorSteps = {darkDirt, lightDirt, grassLand, grassLand, grassLand, snowTops};
|
||||
|
||||
float waterOffset = _waterHeight - 50.0f;
|
||||
@ -560,6 +572,7 @@ void TerrainNode::GenerateBlendMap()
|
||||
waterOffset = 0.0f;
|
||||
}
|
||||
|
||||
// Set up the gradient
|
||||
ColorGradient terrainBlendGradient = ColorGradient(waterOffset, 820.0f, colorSteps);
|
||||
|
||||
// Note that _numberOfRows and _numberOfColumns need to be setup
|
||||
@ -593,6 +606,7 @@ void TerrainNode::GenerateBlendMap()
|
||||
float totalHeights = 0.0f;
|
||||
float totalSlope = 0.0f;
|
||||
|
||||
// Calculate the average height and slope values
|
||||
for (int si = 0; si < 4; si++)
|
||||
{
|
||||
totalHeights += _terrainVerts[currentIndex + si].Position.y;
|
||||
@ -602,6 +616,7 @@ void TerrainNode::GenerateBlendMap()
|
||||
float avgHeight = totalHeights / 4.0f;
|
||||
float avgSlope = totalSlope / 4.0f;
|
||||
|
||||
// Get the RGB value from the gradient at the given height value
|
||||
RGBA currentBlend = terrainBlendGradient.GetRGBAValue(avgHeight);
|
||||
r = (BYTE)currentBlend.red;
|
||||
g = (BYTE)currentBlend.green;
|
||||
@ -612,7 +627,7 @@ void TerrainNode::GenerateBlendMap()
|
||||
{
|
||||
if (avgSlope < 0.6f)
|
||||
{
|
||||
g = (BYTE)SharedMethods::Clamp<int>(avgHeight - 450.0f, 0, 150);
|
||||
g = (BYTE)SharedMethods::Clamp<int>((int)(avgHeight - 450.0f), 0, 150);
|
||||
}
|
||||
}
|
||||
|
||||
@ -667,13 +682,14 @@ void TerrainNode::BuildExtraMaps()
|
||||
));
|
||||
}
|
||||
|
||||
// Method for getting the height value at a given point, can also check if we are colliding with water or not
|
||||
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;
|
||||
|
||||
@ -695,6 +711,7 @@ float TerrainNode::GetHeightAtPoint(float x, float z, bool waterCollide)
|
||||
XMFLOAT4 normal;
|
||||
XMStoreFloat4(&normal, XMVector3Normalize(XMVector3Cross(v1, v2)));
|
||||
|
||||
// Get the normal value for the vert we landed on
|
||||
float result = _terrainVerts[currentIndex].Position.y + (normal.x * dx + normal.z * dz) / -normal.y;
|
||||
if (waterCollide)
|
||||
{
|
||||
@ -707,6 +724,7 @@ float TerrainNode::GetHeightAtPoint(float x, float z, bool waterCollide)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Method for checking if we are within the X Boundary
|
||||
bool TerrainNode::CheckXBoundary(float x)
|
||||
{
|
||||
if (!(x > _terrainStartX && x < _terrainEndX))
|
||||
@ -717,6 +735,7 @@ bool TerrainNode::CheckXBoundary(float x)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method for checking if we are withing the Z Boundary
|
||||
bool TerrainNode::CheckZBoundary(float z)
|
||||
{
|
||||
if (!(z < _terrainStartZ && z > _terrainEndZ))
|
||||
|
Reference in New Issue
Block a user