Files
directx-plane-game/Graphics2/PerlinTerrainNode.cpp
iDunnoDev f6bba67897 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
2022-05-09 17:50:22 +01:00

135 lines
3.3 KiB
C++

#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)
{
_offsetX = offsetX;
_offsetY = offsetY;
_chunkSize = chunkSize;
_layers = layers;
GeneratePerlinValues();
if (!GeneratePerlinHeights())
{
_initError = true;
}
}
// Method for filling the height values array for the terrain generation
bool PerlinTerrainNode::GeneratePerlinHeights()
{
for (int z = 0; z < _gridRows; z++)
{
float mapZ = ((float)z / (float)_gridRows) + 0.5f;
for (int x = 0; x < _gridCols; x++)
{
float mapX = ((float)x / (float)_gridCols) + 0.5f;
float currentHeightValue = GetPerlinValueAt(_offsetX + mapX, _offsetY + mapZ, 8, 0.85f) - 0.25f;
//currentHeightValue = currentHeightValue - floor(currentHeightValue);
_heightValues.push_back(currentHeightValue);
}
}
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)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
float PerlinTerrainNode::Grad(int hash, float x, float y)
{
// Fast Grad switch check converted from a java implimentation of perlin noise
switch (hash & 0xF)
{
case 0x0: return x;
case 0x1: return x + 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
}
}
// Method to calculate the perlin value at x/y with the given octaves and persistance values, also normalised
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);
maxValue += amplitude;
amplitude *= persistance;
frequency *= 2;
}
return total / maxValue;
}
// Method to get the perlin noise value at x/y
float PerlinTerrainNode::GetNoiseValueAt(float x, float y)
{
int x0 = (int)x & 255;
int y0 = (int)y & 255;
int x1 = x0 + 1;
int y1 = y0 + 1;
float dx = x - (float)x0;
float dy = y - (float)y0;
float u = Fade(dx);
float v = Fade(dy);
int aa = p[p[x0] + y0];
int ab = p[p[x0] + y1];
int ba = p[p[x1] + y0];
int bb = p[p[x1] + y1];
float na0 = Grad(aa, dx, dy);
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;
}