Added alot of parameters to make the generator way more natural, also added classes for 3D but not currently used

My mental health is dwindling
This commit is contained in:
Namonay
2025-05-24 01:55:04 +02:00
parent 910f21b9b9
commit 93759f45c0
2 changed files with 142 additions and 35 deletions

View File

@@ -2,9 +2,14 @@
#include <Block.h>
#include <cstdint>
#include <random>
#include <stdexcept>
Noise::Noise(const std::uint32_t seed): seed(std::mt19937(seed))
Noise::Noise(const std::uint32_t seed, float frequency, float amplitude, int octaves, float lacunarity, float persistance): seed(std::mt19937(seed)), frequency(frequency), amplitude(amplitude), octaves(octaves), lacunarity(lacunarity), persistance(persistance)
{
if (amplitude > 1.0f || amplitude < -1.0f)
{
throw std::invalid_argument("Amplitude value must be in [-1;1]");
}
InitPermutation();
}
@@ -25,40 +30,25 @@ void Noise::InitPermutation(void)
std::cout << val << " ";
}
std::cout << std::endl;
std::cout << perlin2D(0, 0) << std::endl;
std::cout << perlin2D(20, 20) << std::endl;
std::cout << perlin2D(150, 150) << std::endl;
std::cout << perlin2D(0.078f, 0.4f) << std::endl;
std::cout << perlin3D2(0, 0, 0) << std::endl;
std::cout << perlin3D2(20, 20, 20) << std::endl;
std::cout << perlin3D(150, 150, 150) << std::endl;
std::cout << perlin3D(0.078f, 0.4f, 0.2f) << std::endl;
}
float Noise::fade(float t)
[[nodiscard]] const float Noise::fade(float t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
float Noise::lerp(float a, float b, float t)
[[nodiscard]] const float Noise::lerp(float a, float b, float t)
{
return (a + t * (b - a));
}
float Noise::grad(int hash, float x, float y)
{
int h = hash & 7;
float u = h < 4 ? x : y;
float v = h < 4 ? y : x;
return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
}
int Noise::perlin2D(int x, int y) {
float scaledX = static_cast<float>(x) * 0.01f;
float scaledY = static_cast<float>(y) * 0.01f;
return floor(perlin2D(scaledX, scaledY) * 255.0f);
}
float Noise::perlin2D(float x, float y) {
const float Noise::perlin2D(float x, float y) {
int xi = (int)floor(x) & 255;
int yi = (int)floor(y) & 255;
@@ -73,14 +63,122 @@ float Noise::perlin2D(float x, float y) {
int ba = perms[perms[xi + 1] + yi];
int bb = perms[perms[xi + 1] + yi + 1];
float x1 = lerp(grad(aa, xf, yf),
grad(ba, xf - 1, yf), u);
float x2 = lerp(grad(ab, xf, yf - 1),
grad(bb, xf - 1, yf - 1), u);
float x1 = lerp(grad2D(aa, xf, yf),
grad2D(ba, xf - 1, yf), u);
float x2 = lerp(grad2D(ab, xf, yf - 1),
grad2D(bb, xf - 1, yf - 1), u);
return (lerp(x1, x2, v) + 1.0f) / 2.0f; // Normalize to [0, 1]
return ((lerp(x1, x2, v) + 1.0f) / 2.0f);
}
const int Noise::perlin2D2(float x, float y) // Wrapper to apply various mumbo jumbo to get a very worldlike generation
{
float total = 0.0f;
float tmp_freq = frequency;
float tmp_amp = amplitude;
float maxValue = 0.0f;
for (int i = 0; i < this->octaves; ++i) {
total += perlin2D(x * tmp_freq, y * tmp_freq) * tmp_amp;
maxValue += tmp_amp;
tmp_amp *= persistance;
tmp_freq *= lacunarity;
}
float normalized = total / maxValue;
normalized = std::clamp(normalized, 0.0f, 1.0f);
return static_cast<int>(normalized * 255.0f);
}
const int Noise::perlin2D(int x, int y) { // Wrapper to unnormalise input and output
float scaledX = static_cast<float>(x) * frequency;
float scaledY = static_cast<float>(y) * frequency;
return floor(perlin2D2(scaledX, scaledY));
}
[[nodiscard]] const float Noise::grad2D(int hash, float x, float y)
{
int h = hash & 7; // 8 directions
float u = h < 4 ? x : y;
float v = h < 4 ? y : x;
return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
}
[[nodiscard]] const float Noise::grad(int hash, float x, float y, float z) {
int h = hash & 15; // 16 directions possibles
float u = h < 8 ? x : y;
float v = h < 4 ? y : (h == 12 || h == 14 ? x : z);
return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
}
const int Noise::perlin3D(int x, int y, int z)
{
float scaledX = static_cast<float>(x) * frequency;
float scaledY = static_cast<float>(y) * frequency;
float scaledZ = static_cast<float>(z) * frequency;
return floor(perlin3D2(scaledX, scaledY, scaledZ));
}
const float Noise::perlin3D(float x, float y, float z) {
int xi = (int)floor(x) & 255;
int yi = (int)floor(y) & 255;
int zi = (int)floor(z) & 255;
float xf = x - floor(x);
float yf = y - floor(y);
float zf = z - floor(z);
float u = fade(xf);
float v = fade(yf);
float w = fade(zf);
int aaa = perms[perms[perms[xi] + yi] + zi];
int aba = perms[perms[perms[xi] + yi + 1] + zi];
int aab = perms[perms[perms[xi] + yi] + zi + 1];
int abb = perms[perms[perms[xi] + yi + 1] + zi + 1];
int baa = perms[perms[perms[xi + 1] + yi] + zi];
int bba = perms[perms[perms[xi + 1] + yi + 1] + zi];
int bab = perms[perms[perms[xi + 1] + yi] + zi + 1];
int bbb = perms[perms[perms[xi + 1] + yi + 1] + zi + 1];
float x1, x2, y1, y2;
x1 = lerp(grad(aaa, xf, yf, zf),
grad(baa, xf - 1, yf, zf), u);
x2 = lerp(grad(aba, xf, yf - 1, zf),
grad(bba, xf - 1, yf - 1, zf), u);
y1 = lerp(x1, x2, v);
x1 = lerp(grad(aab, xf, yf, zf - 1),
grad(bab, xf - 1, yf, zf - 1), u);
x2 = lerp(grad(abb, xf, yf - 1, zf - 1),
grad(bbb, xf - 1, yf - 1, zf - 1), u);
y2 = lerp(x1, x2, v);
return ((lerp(y1, y2, w) + 1.0f) / 2.0f) * amplitude;
}
const int Noise::perlin3D2(float x, float y, float z)
{
float total = 0.0f;
float tmp_freq = frequency;
float tmp_amp = amplitude;
float maxValue = 0.0f;
for (int i = 0; i < this->octaves; ++i) {
total += perlin3D(x * tmp_freq, y * tmp_freq, z * tmp_freq) * tmp_amp;
maxValue += tmp_amp;
tmp_amp *= persistance;
tmp_freq *= lacunarity;
}
float normalized = total / maxValue;
normalized = std::clamp(normalized, 0.0f, 1.0f);
return static_cast<int>(normalized * 255.0f);
}
[[nodiscard]] std::array<std::uint32_t, CHUNK_SIZE.y> Noise::GetHeight(Scop::Vec2i pos)
{
std::array<std::uint32_t, CHUNK_SIZE.y> data;
@@ -98,6 +196,5 @@ float Noise::perlin2D(float x, float y) {
else
data[y] = static_cast<std::uint32_t>(BlockType::Stone);
}
return data;
}

View File

@@ -11,20 +11,30 @@
class Noise
{
public:
Noise(const std::uint32_t seed = 42);
Noise(const std::uint32_t seed = 42, float frequency = 0.05f, float amplitude = 0.9f, int octaves = 4, float lacunarity = 2.0f, float persistance = 0.5f);
[[nodiscard]] std::array<std::uint32_t, CHUNK_SIZE.y> GetHeight(Scop::Vec2i pos);
float perlin2D(float x, float y);
int perlin2D(int x, int y);
const float perlin2D(float x, float y);
const int perlin2D(int x, int y);
const int perlin2D2(float x, float y);
const int perlin3D(int x, int y, int z);
const float perlin3D(float x, float y, float z);
const int perlin3D2(float x, float y, float z);
~Noise() = default;
private:
std::mt19937 seed;
std::array<int, NOISE_SIZE> perms;
const float frequency;
const float amplitude;
const int octaves;
const float lacunarity;
const float persistance;
void InitPermutation(void);
float fade(float t);
float lerp(float a, float b, float t);
float grad(int hash, float x, float y);
[[nodiscard]] const float fade(float t);
[[nodiscard]] const float lerp(float a, float b, float t);
[[nodiscard]] const float grad2D(int hash, float x, float y);
[[nodiscard]] const float grad(int hash, float x, float y, float z);
};
#endif