Added better perlin terrain generation
Added function to scatter models onto the terrain
This commit is contained in:
+26
-26
@@ -15,7 +15,7 @@ void Graphics2::CreateSceneGraph()
|
|||||||
|
|
||||||
GetCamera()->SetCameraPosition(0.0f, 550.0f, -80.0f);
|
GetCamera()->SetCameraPosition(0.0f, 550.0f, -80.0f);
|
||||||
SceneGraphPointer sceneGraph = GetSceneGraph();
|
SceneGraphPointer sceneGraph = GetSceneGraph();
|
||||||
|
|
||||||
// This is where you add nodes to the scene graph
|
// This is where you add nodes to the scene graph
|
||||||
//shared_ptr<TexturedCubeNode> cube = make_shared<TexturedCubeNode>(L"Body", L"Textures\\woodbox.bmp");
|
//shared_ptr<TexturedCubeNode> cube = make_shared<TexturedCubeNode>(L"Body", L"Textures\\woodbox.bmp");
|
||||||
//cube->SetWorldTransform(XMMatrixScaling(5.0f, 8.0f, 2.5f) * XMMatrixTranslation(0, 23.0f, 0));
|
//cube->SetWorldTransform(XMMatrixScaling(5.0f, 8.0f, 2.5f) * XMMatrixTranslation(0, 23.0f, 0));
|
||||||
@@ -28,7 +28,7 @@ void Graphics2::CreateSceneGraph()
|
|||||||
sceneGraph->Add(skyDome);
|
sceneGraph->Add(skyDome);
|
||||||
|
|
||||||
//shared_ptr<HeightMapTerrainNode> terrainNode = make_shared<HeightMapTerrainNode>(L"MainTerrain", L"Textures\\Example_HeightMap.raw", L"RandomWords");
|
//shared_ptr<HeightMapTerrainNode> terrainNode = make_shared<HeightMapTerrainNode>(L"MainTerrain", L"Textures\\Example_HeightMap.raw", L"RandomWords");
|
||||||
shared_ptr<PerlinTerrainNode> terrainNode = make_shared<PerlinTerrainNode>(L"MainTerrain", L"LovelyCat", 10.0f, 20.0f, 1.0f, 1);
|
shared_ptr<PerlinTerrainNode> terrainNode = make_shared<PerlinTerrainNode>(L"MainTerrain", L"LovelyCat", 10.0f);
|
||||||
terrainNode->SetAmbientLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetAmbientLight());
|
terrainNode->SetAmbientLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetAmbientLight());
|
||||||
terrainNode->SetDirectionalLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightDirection(), DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightColor());
|
terrainNode->SetDirectionalLight(DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightDirection(), DirectXFramework::GetDXFramework()->GetGlobalLighting()->GetDirectionalLightColor());
|
||||||
terrainNode->SetWaterColor(XMFLOAT4(SharedMethods::RGBValueToIntensity(0x84), SharedMethods::RGBValueToIntensity(0xC1), SharedMethods::RGBValueToIntensity(0xF9), 1.0f));
|
terrainNode->SetWaterColor(XMFLOAT4(SharedMethods::RGBValueToIntensity(0x84), SharedMethods::RGBValueToIntensity(0xC1), SharedMethods::RGBValueToIntensity(0xF9), 1.0f));
|
||||||
@@ -36,26 +36,6 @@ void Graphics2::CreateSceneGraph()
|
|||||||
//terrainNode->SetWaterColor(XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f));
|
//terrainNode->SetWaterColor(XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f));
|
||||||
sceneGraph->Add(terrainNode);
|
sceneGraph->Add(terrainNode);
|
||||||
|
|
||||||
shared_ptr<SceneGraph> treeGroupA = make_shared<SceneGraph>(L"TreeGroupA");
|
|
||||||
|
|
||||||
shared_ptr<MeshNode> treeNode1 = make_shared<MeshNode>(L"Tree1", L"Models\\Tree\\Tree1.3ds");
|
|
||||||
treeNode1->SetWorldTransform(XMMatrixScaling(0.005f, 0.01f, 0.005f) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 1.0f, 0.0f), 0.1f * XM_PI) * XMMatrixTranslation(0.0f, 320.0f, 250.0f));
|
|
||||||
treeGroupA->Add(treeNode1);
|
|
||||||
|
|
||||||
shared_ptr<MeshNode> treeNode2 = make_shared<MeshNode>(L"Tree2", L"Models\\Tree\\Tree1.3ds");
|
|
||||||
treeNode2->SetWorldTransform(XMMatrixScaling(0.002f, 0.002f, 0.002f) * XMMatrixTranslation(-150.0f, 380.0f, 150.0f));
|
|
||||||
treeGroupA->Add(treeNode2);
|
|
||||||
|
|
||||||
shared_ptr<MeshNode> treeNode3 = make_shared<MeshNode>(L"Tree3", L"Models\\Tree\\Tree1.3ds");
|
|
||||||
treeNode3->SetWorldTransform(XMMatrixScaling(0.005f, 0.005f, 0.005f) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 1.0f, 0.0f), -0.1f * XM_PI) * XMMatrixTranslation(100.0f, 290.0f, 350.0f));
|
|
||||||
treeGroupA->Add(treeNode3);
|
|
||||||
|
|
||||||
shared_ptr<MeshNode> treeNode4 = make_shared<MeshNode>(L"Tree4", L"Models\\Tree\\Tree1.3ds");
|
|
||||||
treeNode4->SetWorldTransform(XMMatrixScaling(0.005f, 0.01f, 0.005f) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 1.0f, 0.0f), 0.1f * XM_PI) * XMMatrixTranslation(0.0f, 320.0f, 250.0f));
|
|
||||||
treeGroupA->Add(treeNode4);
|
|
||||||
|
|
||||||
sceneGraph->Add(treeGroupA);
|
|
||||||
|
|
||||||
shared_ptr<ControlledSplitMeshNode> plane1Node = make_shared<ControlledSplitMeshNode>(L"Plane1", L"Models\\Plane\\Bonanza.3DS");
|
shared_ptr<ControlledSplitMeshNode> plane1Node = make_shared<ControlledSplitMeshNode>(L"Plane1", L"Models\\Plane\\Bonanza.3DS");
|
||||||
plane1Node->SetStartOrientation(XMMatrixRotationAxis(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), XM_PI) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f), 0.5f * XM_PI));
|
plane1Node->SetStartOrientation(XMMatrixRotationAxis(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), XM_PI) * XMMatrixRotationAxis(XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f), 0.5f * XM_PI));
|
||||||
plane1Node->SetNodePosition(0.0f, 550.0f, -50.0f);
|
plane1Node->SetNodePosition(0.0f, 550.0f, -50.0f);
|
||||||
@@ -74,9 +54,30 @@ void Graphics2::CreateSceneGraph()
|
|||||||
|
|
||||||
void Graphics2::UpdateSceneGraph()
|
void Graphics2::UpdateSceneGraph()
|
||||||
{
|
{
|
||||||
GetCurrentControlInputs();
|
|
||||||
|
|
||||||
SceneGraphPointer sceneGraph = GetSceneGraph();
|
SceneGraphPointer sceneGraph = GetSceneGraph();
|
||||||
|
shared_ptr<TerrainNode> mainTerrain = dynamic_pointer_cast<TerrainNode>(sceneGraph->Find(L"MainTerrain"));
|
||||||
|
|
||||||
|
if (!_initDone && mainTerrain != nullptr)
|
||||||
|
{
|
||||||
|
vector<TerrainPopNode> rngSpawnList;
|
||||||
|
|
||||||
|
TerrainPopNode treeModelA = TerrainPopNode();
|
||||||
|
treeModelA.modelName = L"Models\\Tree\\Tree2.fbx";
|
||||||
|
treeModelA.nodeBaseName = L"treeA";
|
||||||
|
treeModelA.scaleFactor = 1.0f;
|
||||||
|
|
||||||
|
rngSpawnList.push_back(treeModelA);
|
||||||
|
|
||||||
|
shared_ptr<SceneGraph> treeGroupA = make_shared<SceneGraph>(L"TreeGroupA");
|
||||||
|
|
||||||
|
mainTerrain->PopulateTerrain(treeGroupA, rngSpawnList, 10, 10, 400.0f, 550.0f, 0.9f, 1.0f);
|
||||||
|
treeGroupA->Initialise();
|
||||||
|
sceneGraph->Add(treeGroupA);
|
||||||
|
|
||||||
|
_initDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetCurrentControlInputs();
|
||||||
XMVECTOR startCameraPos = GetCamera()->GetCameraPosition();
|
XMVECTOR startCameraPos = GetCamera()->GetCameraPosition();
|
||||||
|
|
||||||
if (_currentPlayerObject != nullptr)
|
if (_currentPlayerObject != nullptr)
|
||||||
@@ -189,8 +190,7 @@ void Graphics2::UpdateSceneGraph()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check the camera and our terrain boundaries
|
// Check the camera and our terrain boundaries
|
||||||
XMVECTOR currentCameraPos = GetCamera()->GetCameraPosition();
|
XMVECTOR currentCameraPos = GetCamera()->GetCameraPosition();
|
||||||
shared_ptr<TerrainNode> mainTerrain = dynamic_pointer_cast<TerrainNode>(sceneGraph->Find(L"MainTerrain"));
|
|
||||||
GetCamera()->Update();
|
GetCamera()->Update();
|
||||||
if (mainTerrain != nullptr)
|
if (mainTerrain != nullptr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public:
|
|||||||
void UpdateSceneGraph();
|
void UpdateSceneGraph();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool _initDone = false;
|
||||||
|
|
||||||
bool _boosting = false;
|
bool _boosting = false;
|
||||||
float _boostMultiplier = 1;
|
float _boostMultiplier = 1;
|
||||||
float _boostMin = 1;
|
float _boostMin = 1;
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
newmtl mat_0-default-grey.jpg
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.698039 0.698039 0.698039
|
||||||
|
Ks 0.000000 0.000000 0.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
Ns 9.84916
|
||||||
|
map_Kd default-grey.jpg
|
||||||
|
|
||||||
|
newmtl mat_1-boat_fishing02.jpg
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.698039 0.698039 0.698039
|
||||||
|
Ks 0.000000 0.000000 0.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
Ns 9.84916
|
||||||
|
map_Kd boat_fishing02.jpg
|
||||||
|
|
||||||
|
newmtl mat_2-default-grey.jpg
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.698039 0.698039 0.698039
|
||||||
|
Ks 0.000000 0.000000 0.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
Ns 9.84916
|
||||||
|
map_Kd default-grey.jpg
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 134 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 111 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,11 +1,8 @@
|
|||||||
#include "PerlinTerrainNode.h"
|
#include "PerlinTerrainNode.h"
|
||||||
|
|
||||||
PerlinTerrainNode::PerlinTerrainNode(wstring name, wstring seed, float offsetX, float offsetY, float chunkSize, int layers, int widthX, int widthZ, float waterHeight, int cellSizeX, int cellSizeZ) : TerrainNode(name, seed, waterHeight, widthX, widthZ, cellSizeX, cellSizeZ)
|
PerlinTerrainNode::PerlinTerrainNode(wstring name, wstring seed, float chunkSize, int widthX, int widthZ, float waterHeight, int cellSizeX, int cellSizeZ) : TerrainNode(name, seed, waterHeight, widthX, widthZ, cellSizeX, cellSizeZ)
|
||||||
{
|
{
|
||||||
_offsetX = offsetX;
|
|
||||||
_offsetY = offsetY;
|
|
||||||
_chunkSize = chunkSize;
|
_chunkSize = chunkSize;
|
||||||
_layers = layers;
|
|
||||||
|
|
||||||
GeneratePerlinValues();
|
GeneratePerlinValues();
|
||||||
if (!GeneratePerlinHeights())
|
if (!GeneratePerlinHeights())
|
||||||
@@ -14,44 +11,64 @@ PerlinTerrainNode::PerlinTerrainNode(wstring name, wstring seed, float offsetX,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PerlinTerrainNode::GeneratePerlinValues()
|
||||||
|
{
|
||||||
|
std::seed_seq seedGenerator(_seedString.begin(), _seedString.end());
|
||||||
|
std::mt19937 generator;
|
||||||
|
generator.seed(seedGenerator);
|
||||||
|
std::uniform_int_distribution<> dist(0, 511);
|
||||||
|
char bufferChar;
|
||||||
|
int newPosition;
|
||||||
|
|
||||||
|
_p.clear();
|
||||||
|
copy(_staticP.begin(), _staticP.end(), back_inserter(_p));
|
||||||
|
|
||||||
|
for (int i = 0; i < 512; i++)
|
||||||
|
{
|
||||||
|
newPosition = dist(generator);
|
||||||
|
bufferChar = _p[i];
|
||||||
|
_p[i] = _p[newPosition];
|
||||||
|
_p[newPosition] = bufferChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Method for filling the height values array for the terrain generation
|
// Method for filling the height values array for the terrain generation
|
||||||
bool PerlinTerrainNode::GeneratePerlinHeights()
|
bool PerlinTerrainNode::GeneratePerlinHeights()
|
||||||
{
|
{
|
||||||
for (int z = 0; z < _gridRows; z++)
|
for (int z = 0; z < _gridRows; z++)
|
||||||
{
|
{
|
||||||
float mapZ = ((float)z / (float)_gridRows) + 0.5f;
|
float mapZ = ((float)z / (float)_gridRows);
|
||||||
|
|
||||||
for (int x = 0; x < _gridCols; x++)
|
for (int x = 0; x < _gridCols; x++)
|
||||||
{
|
{
|
||||||
float mapX = ((float)x / (float)_gridCols) + 0.5f;
|
float mapX = ((float)x / (float)_gridCols);
|
||||||
|
|
||||||
float currentHeightValue = GetPerlinValueAt(_offsetX + mapX, _offsetY + mapZ, 8, 0.85f) - 0.25f;
|
//float currentHeightValue = GetPerlinValueAt(mapX, mapZ, 8, 0.85f) - 0.25f;
|
||||||
|
float currentHeightValue = 0.0f;
|
||||||
|
|
||||||
|
int octaves = 12;
|
||||||
|
float currentOctaveValue = 1.0f;
|
||||||
|
float stepOff = 1.0f;
|
||||||
|
float stepTotal = 0.0f;
|
||||||
|
// n covers the persistance, frequency and
|
||||||
|
for (int n = 1; n <= octaves; n++)
|
||||||
|
{
|
||||||
|
currentHeightValue += stepOff * GetNoiseValueAt(((float)x * currentOctaveValue) / ((float)_gridCols / _chunkSize), ((float)z * currentOctaveValue) / ((float)_gridRows / _chunkSize));
|
||||||
|
currentOctaveValue *= 2;
|
||||||
|
stepTotal += stepOff;
|
||||||
|
stepOff *= 0.5f;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//currentHeightValue = currentHeightValue / stepTotal; // *(currentHeightValue * 2.0f);
|
||||||
//currentHeightValue = currentHeightValue - floor(currentHeightValue);
|
//currentHeightValue = currentHeightValue - floor(currentHeightValue);
|
||||||
_heightValues.push_back(currentHeightValue);
|
_heightValues.push_back((currentHeightValue + 1.0f) * 0.5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method for generating the permutation array needed for perlin noise
|
|
||||||
void PerlinTerrainNode::GeneratePerlinValues()
|
|
||||||
{
|
|
||||||
// Set the permutation array length
|
|
||||||
p.resize(256);
|
|
||||||
|
|
||||||
// Fill the permutation array with 0 to 255
|
|
||||||
iota(p.begin(), p.end(), 0);
|
|
||||||
|
|
||||||
default_random_engine engine(_seedHash);
|
|
||||||
|
|
||||||
// Shuffle the array values using the seed value given
|
|
||||||
shuffle(p.begin(), p.end(), engine);
|
|
||||||
|
|
||||||
// Duplicate the permutation results so our array is 512
|
|
||||||
p.insert(p.end(), p.begin(), p.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
float PerlinTerrainNode::Fade(float t)
|
float PerlinTerrainNode::Fade(float t)
|
||||||
{
|
{
|
||||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||||
@@ -59,77 +76,56 @@ float PerlinTerrainNode::Fade(float t)
|
|||||||
|
|
||||||
float PerlinTerrainNode::Grad(int hash, float x, float y)
|
float PerlinTerrainNode::Grad(int hash, float x, float y)
|
||||||
{
|
{
|
||||||
// Fast Grad switch check converted from a java implimentation of perlin noise
|
int h = hash & 7;
|
||||||
switch (hash & 0xF)
|
float u = y;
|
||||||
|
float v = x;
|
||||||
|
if (h < 4)
|
||||||
{
|
{
|
||||||
case 0x0: return x;
|
u = x;
|
||||||
case 0x1: return x + y;
|
v = y;
|
||||||
case 0x2: return y;
|
|
||||||
case 0x3: return -x + y;
|
|
||||||
case 0x4: return -x;
|
|
||||||
case 0x5: return -x - y;
|
|
||||||
case 0x6: return -y;
|
|
||||||
case 0x7: return x - y;
|
|
||||||
case 0x8: return x;
|
|
||||||
case 0x9: return x + y;
|
|
||||||
case 0xA: return y;
|
|
||||||
case 0xB: return -x + y;
|
|
||||||
case 0xC: return -x;
|
|
||||||
case 0xD: return -x - y;
|
|
||||||
case 0xE: return -y;
|
|
||||||
case 0xF: return x - y;
|
|
||||||
|
|
||||||
default: return 0; // Never occurs
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
float outA = u;
|
||||||
// Method to calculate the perlin value at x/y with the given octaves and persistance values, also normalised
|
if ((h & 1))
|
||||||
float PerlinTerrainNode::GetPerlinValueAt(float x, float y, int octaves, float persistance)
|
|
||||||
{
|
|
||||||
float total = 0.0f;
|
|
||||||
float frequency = 1.0f;
|
|
||||||
float amplitude = 1.0f;
|
|
||||||
float maxValue = 0.0f;
|
|
||||||
|
|
||||||
for (int i = 0; i < octaves; i++)
|
|
||||||
{
|
{
|
||||||
total += (GetNoiseValueAt(x * frequency, y * frequency) * amplitude);
|
outA = -u;
|
||||||
maxValue += amplitude;
|
|
||||||
|
|
||||||
amplitude *= persistance;
|
|
||||||
frequency *= 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return total / maxValue;
|
float outB = 2.0f * v;
|
||||||
|
if ((h & 2))
|
||||||
|
{
|
||||||
|
outB = -2.0f * v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outA + outB;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to get the perlin noise value at x/y
|
// Method to get the perlin noise value at x/y
|
||||||
float PerlinTerrainNode::GetNoiseValueAt(float x, float y)
|
float PerlinTerrainNode::GetNoiseValueAt(float x, float y)
|
||||||
{
|
{
|
||||||
int x0 = (int)x & 255;
|
int ix0 = (int)floor(x);
|
||||||
int y0 = (int)y & 255;
|
int iy0 = (int)floor(y);
|
||||||
|
|
||||||
int x1 = x0 + 1;
|
float fx0 = x - (float)ix0;
|
||||||
int y1 = y0 + 1;
|
float fy0 = y - (float)iy0;
|
||||||
|
float fx1 = fx0 - 1.0f;
|
||||||
|
float fy1 = fy0 - 1.0f;
|
||||||
|
|
||||||
|
int ix1 = (ix0 + 1) & 0xff;
|
||||||
|
int iy1 = (iy0 + 1) & 0xff;
|
||||||
|
ix0 = ix0 & 0xff;
|
||||||
|
iy0 = iy0 & 0xff;
|
||||||
|
|
||||||
float dx = x - (float)x0;
|
float t = Fade(fy0);
|
||||||
float dy = y - (float)y0;
|
float s = Fade(fx0);
|
||||||
|
|
||||||
float u = Fade(dx);
|
float nx0 = Grad(_p[ix0 + _p[iy0]], fx0, fy0);
|
||||||
float v = Fade(dy);
|
float nx1 = Grad(_p[ix0 + _p[iy1]], fx0, fy1);
|
||||||
|
float n0 = SharedMethods::Lerp<float>(nx0, nx1, t);
|
||||||
|
|
||||||
int aa = p[p[x0] + y0];
|
nx0 = Grad(_p[ix1 + _p[iy0]], fx1, fy0);
|
||||||
int ab = p[p[x0] + y1];
|
nx1 = Grad(_p[ix1 + _p[iy1]], fx1, fy1);
|
||||||
int ba = p[p[x1] + y0];
|
float n1 = SharedMethods::Lerp<float>(nx0, nx1, t);
|
||||||
int bb = p[p[x1] + y1];
|
|
||||||
|
|
||||||
float na0 = Grad(aa, dx, dy);
|
return 0.507f * SharedMethods::Lerp(n0, n1, s);
|
||||||
float na1 = Grad(ba, dx - 1.0f, dy);
|
|
||||||
float nal = SharedMethods::Lerp(na0, na1, u);
|
|
||||||
|
|
||||||
float nb0 = Grad(ab, dx, dy - 1.0f);
|
|
||||||
float nb1 = Grad(bb, dx - 1.0f, dy - 1.0f);
|
|
||||||
float nbl = SharedMethods::Lerp(nb0, nb1, u);
|
|
||||||
|
|
||||||
return (SharedMethods::Lerp(nal, nbl, v) + 1.0f) / 2.0f;
|
|
||||||
}
|
}
|
||||||
@@ -9,21 +9,48 @@
|
|||||||
class PerlinTerrainNode : public TerrainNode
|
class PerlinTerrainNode : public TerrainNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PerlinTerrainNode(wstring name, wstring seed, float offsetX, float offsetY, float chunkSize, int layers, int widthX = 1023, int widthZ = 1023, float waterHeight = 150.0f, int cellSizeX = 10, int cellSizeZ = 10);
|
PerlinTerrainNode(wstring name, wstring seed, float chunkSize, int widthX = 1023, int widthZ = 1023, float waterHeight = 300.0f, int cellSizeX = 10, int cellSizeZ = 10);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vector<int> p;
|
// the static perlin permutation array, we could calculate a random one but apparently you can run into sequencing issues and this just seems like the best solution
|
||||||
float _offsetX;
|
vector<unsigned char> _staticP = { 151,160,137,91,90,15,
|
||||||
float _offsetY;
|
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||||
|
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||||
|
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||||
|
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||||
|
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||||
|
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||||
|
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||||
|
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||||
|
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||||
|
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||||
|
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||||
|
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
|
||||||
|
151,160,137,91,90,15,
|
||||||
|
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||||
|
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||||
|
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||||
|
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||||
|
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||||
|
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||||
|
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||||
|
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||||
|
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||||
|
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||||
|
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||||
|
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
|
||||||
|
};
|
||||||
|
|
||||||
|
vector<unsigned char> _p;
|
||||||
|
|
||||||
float _chunkSize;
|
float _chunkSize;
|
||||||
int _layers;
|
|
||||||
|
|
||||||
float Fade(float t);
|
float Fade(float t);
|
||||||
float Grad(int hash, float x, float y);
|
float Grad(int hash, float x, float y);
|
||||||
|
|
||||||
|
void GeneratePerlinValues();
|
||||||
bool GeneratePerlinHeights();
|
bool GeneratePerlinHeights();
|
||||||
float GetPerlinValueAt(float x, float y, int octaves, float persistance);
|
float GetPerlinValueAt(float x, float y, int octaves, float persistance);
|
||||||
float GetNoiseValueAt(float x, float y);
|
float GetNoiseValueAt(float x, float y);
|
||||||
void GeneratePerlinValues();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DirectXCore.h"
|
#include "DirectXCore.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct CBUFFER
|
struct CBUFFER
|
||||||
{
|
{
|
||||||
@@ -16,6 +17,13 @@ struct CBUFFER
|
|||||||
float padding[2];
|
float padding[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TerrainPopNode
|
||||||
|
{
|
||||||
|
std::wstring nodeBaseName;
|
||||||
|
std::wstring modelName;
|
||||||
|
float scaleFactor;
|
||||||
|
};
|
||||||
|
|
||||||
namespace SharedMethods
|
namespace SharedMethods
|
||||||
{
|
{
|
||||||
XMMATRIX RotateFromPoint(const float x, const float y, const float z, const XMMATRIX rotationMatrix);
|
XMMATRIX RotateFromPoint(const float x, const float y, const float z, const XMMATRIX rotationMatrix);
|
||||||
|
|||||||
@@ -498,6 +498,52 @@ void TerrainNode::LoadTerrainTextures()
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < _gridCols; x += xStep)
|
||||||
|
{
|
||||||
|
int currentIndex = ((z * _gridCols) + x) * 4;
|
||||||
|
|
||||||
|
float totalHeights = 0.0f;
|
||||||
|
float totalSlope = 0.0f;
|
||||||
|
for (int si = 0; si < 4; si++)
|
||||||
|
{
|
||||||
|
totalHeights += _terrainVerts[currentIndex + si].Position.y;
|
||||||
|
totalSlope += _terrainVerts[currentIndex + si].Normal.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
float heightValue = totalHeights / 4.0f;
|
||||||
|
|
||||||
|
if (heightValue >= heightLower && heightValue <= heightUpper)
|
||||||
|
{
|
||||||
|
float avgSlope = totalSlope / 4.0f;
|
||||||
|
|
||||||
|
if (avgSlope >= slopeLower && avgSlope <= slopeUpper)
|
||||||
|
{
|
||||||
|
int nodeIndex = 0;
|
||||||
|
if (nodesForPop.size() > 1)
|
||||||
|
{
|
||||||
|
nodeIndex = rand() % nodesForPop.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
float scale = (rand() % 100 * 0.01f) * nodesForPop[nodeIndex].scaleFactor;
|
||||||
|
|
||||||
|
float xPos = x * _cellSizeX + _terrainStartX;
|
||||||
|
float yPos = heightValue - 1.0f;
|
||||||
|
float zPos = (-z + 1) * _cellSizeZ + _terrainStartZ;
|
||||||
|
|
||||||
|
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(XMMatrixScaling(scale, scale, scale) * XMMatrixTranslation(xPos, yPos, zPos));
|
||||||
|
currentSceneGraph->Add(newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TerrainNode::GenerateBlendMap()
|
void TerrainNode::GenerateBlendMap()
|
||||||
{
|
{
|
||||||
RGBA snowTops = RGBA{ 0u, 0u, 0u, 255u };
|
RGBA snowTops = RGBA{ 0u, 0u, 0u, 255u };
|
||||||
@@ -507,7 +553,13 @@ void TerrainNode::GenerateBlendMap()
|
|||||||
|
|
||||||
vector<RGBA> colorSteps = {darkDirt, lightDirt, grassLand, grassLand, grassLand, snowTops};
|
vector<RGBA> colorSteps = {darkDirt, lightDirt, grassLand, grassLand, grassLand, snowTops};
|
||||||
|
|
||||||
ColorGradient terrainBlendGradient = ColorGradient(80.0f, 620.0f, colorSteps);
|
float waterOffset = _waterHeight - 50.0f;
|
||||||
|
if (waterOffset < 0.0f)
|
||||||
|
{
|
||||||
|
waterOffset = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorGradient terrainBlendGradient = ColorGradient(waterOffset, 820.0f, colorSteps);
|
||||||
|
|
||||||
// Note that _numberOfRows and _numberOfColumns need to be setup
|
// Note that _numberOfRows and _numberOfColumns need to be setup
|
||||||
// to the number of rows and columns in your grid in order for this
|
// to the number of rows and columns in your grid in order for this
|
||||||
@@ -538,24 +590,30 @@ void TerrainNode::GenerateBlendMap()
|
|||||||
int currentIndex = ((i * _gridCols) + j) * 4;
|
int currentIndex = ((i * _gridCols) + j) * 4;
|
||||||
|
|
||||||
float totalHeights = 0.0f;
|
float totalHeights = 0.0f;
|
||||||
float biggestSlope = 0.0f;
|
float totalSlope = 0.0f;
|
||||||
|
|
||||||
for (int si = 0; si < 4; si++)
|
for (int si = 0; si < 4; si++)
|
||||||
{
|
{
|
||||||
totalHeights += _terrainVerts[currentIndex + si].Position.y;
|
totalHeights += _terrainVerts[currentIndex + si].Position.y;
|
||||||
if (_terrainVerts[currentIndex + si].Normal.y > biggestSlope)
|
totalSlope += _terrainVerts[currentIndex + si].Normal.y;
|
||||||
{
|
|
||||||
biggestSlope = _terrainVerts[currentIndex + si].Normal.y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float avgHeight = totalHeights / 4.0f;
|
float avgHeight = totalHeights / 4.0f;
|
||||||
|
float avgSlope = totalSlope / 4.0f;
|
||||||
|
|
||||||
RGBA currentBlend = terrainBlendGradient.GetRGBAValue(avgHeight);
|
RGBA currentBlend = terrainBlendGradient.GetRGBAValue(avgHeight);
|
||||||
r = (BYTE)currentBlend.red;
|
r = (BYTE)currentBlend.red;
|
||||||
g = (BYTE)currentBlend.green;
|
g = (BYTE)currentBlend.green;
|
||||||
b = (BYTE)currentBlend.blue;
|
b = (BYTE)currentBlend.blue;
|
||||||
a = (BYTE)currentBlend.alpha;
|
a = (BYTE)currentBlend.alpha;
|
||||||
|
// Override the G channel if we are cliff height and slope angle
|
||||||
|
if (avgHeight > 500.0f)
|
||||||
|
{
|
||||||
|
if (avgSlope < 0.6f)
|
||||||
|
{
|
||||||
|
g = (BYTE)SharedMethods::Clamp<int>(avgHeight - 450.0f, 0, 150);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DWORD mapValue = (a << 24) + (b << 16) + (g << 8) + r;
|
DWORD mapValue = (a << 24) + (b << 16) + (g << 8) + r;
|
||||||
*blendMapPtr++ = mapValue;
|
*blendMapPtr++ = mapValue;
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
#include "WICTextureLoader.h"
|
#include "WICTextureLoader.h"
|
||||||
#include "SharedMethods.h"
|
#include "SharedMethods.h"
|
||||||
#include "SceneNode.h"
|
#include "SceneNode.h"
|
||||||
|
#include "SceneGraph.h"
|
||||||
|
#include "MeshNode.h"
|
||||||
|
#include "SplitMeshNode.h"
|
||||||
|
|
||||||
typedef struct TerrainVertex
|
typedef struct TerrainVertex
|
||||||
{
|
{
|
||||||
@@ -49,6 +51,8 @@ public:
|
|||||||
void Render(void);
|
void Render(void);
|
||||||
void virtual Shutdown(void);
|
void virtual Shutdown(void);
|
||||||
|
|
||||||
|
void PopulateTerrain(SceneGraphPointer currentSceneGraph, vector<TerrainPopNode>& nodesForPop, int xStep, int zStep, float heightLower, float heightUpper, float slopeLower, float slopeUpper);
|
||||||
|
|
||||||
float GetHeightAtPoint(float x, float z, bool waterCollide = false);
|
float GetHeightAtPoint(float x, float z, bool waterCollide = false);
|
||||||
bool CheckXBoundary(float x);
|
bool CheckXBoundary(float x);
|
||||||
bool CheckZBoundary(float z);
|
bool CheckZBoundary(float z);
|
||||||
|
|||||||
Reference in New Issue
Block a user