Perlin Noise Implementation File

This commit is contained in:
2024-09-19 14:14:24 -04:00
parent c7bc78739b
commit c3d712f546

88
Core/src/Core/Perlin.cpp Normal file
View File

@@ -0,0 +1,88 @@
#include <Core/Perlin.hpp>
void CaveGame::Core::PerlinNoise::InitGradients() {
for (int i = 0; i < GradientSizeTable; i++)
{
double z = 1.f - 2.f * random.Float();
double r = J3ML::Math::Sqrt(1.f - z * z);
double theta = 2 * J3ML::Math::Pi * random.Float();
gradients[i * 3] = r * J3ML::Math::Cos(theta);
gradients[i * 3 + 1] = r * J3ML::Math::Sin(theta);
gradients[i * 3 + 2] = z;
}
}
int CaveGame::Core::PerlinNoise::Index(int ix, int iy, int iz) {
return Permutate(ix + Permutate(iy + Permutate(iz)));
}
double CaveGame::Core::PerlinNoise::Lattice(int ix, int iy, int iz, double fx, double fy, double fz) {
// Look up a random gradient at [ix, iy, iz] and dot it with the [fx, fy, fz] vector.
int index = Index(ix, iy, iz);
int g = index * 3;
return gradients[g] * fx + gradients[g + 1] * fy + gradients[g + 2] * fz;
}
double CaveGame::Core::PerlinNoise::Lerp(double t, double value0, double value1) {
return J3ML::Math::Lerp(value0, value1, t);
}
int CaveGame::Core::PerlinNoise::Permutate(int x) {
int mask = GradientSizeTable - 1;
return permutations[x & mask];
}
double CaveGame::Core::PerlinNoise::Smooth(double x) {
// Smoothing curve. This is used to calculate interpolants so that the noise doesn't look blocky when the frequency is low.
return x * x * (3 - 2 * x);
}
double CaveGame::Core::PerlinNoise::Noise(double x, double y, double z) {
// The main noise function. Looks up the pseudorandom gradients at the nearest lattice points,
// dots them with the input vector, and interpolates the results to produce a single output value in [-0.5, 0.5] range.
int ix = J3ML::Math::FloorInt(x);
double fx0 = x - ix;
double fx1 = fx0 - 1;
double wx = Smooth(fx0);
int iy = J3ML::Math::FloorInt(y);
double fy0 = y - iy;
double fy1 = fy0 - 1;
double wy = Smooth(fy0);
int iz = J3ML::Math::FloorInt(z);
double fz0 = z - iz;
double fz1 = fz0 - 1;
double wz = Smooth(fz0);
double vx0 = Lattice(ix, iy, iz, fx0, fy0, fz0);
double vx1 = Lattice(ix+1, iy, iz, fx1, fy0, fz0);
double vy0 = Lerp(wx, vx0, vx1);
vx0 = Lattice(ix, iy + 1, iz, fx0, fy1, fz0);
vx1 = Lattice(ix + 1, iy + 1, iz, fx1, fy1, fz0);
double vy1 = Lerp(wx, vx0, vx1);
double vz0 = Lerp(wy, vy0, vy1);
vx0 = Lattice(ix, iy, iz + 1, fx0, fy0, fz1);
vx1 = Lattice(ix + 1, iy, iz + 1, fx1, fy0, fz1);
vy0 = Lerp(wx, vx0, vx1);
vx0 = Lattice(ix, iy + 1, iz + 1, fx0, fy1, fz1);
vx1 = Lattice(ix + 1, iy + 1, iz + 1, fx1, fy1, fz1);
vy1 = Lerp(wx, vx0, vx1);
double vz1 = Lerp(wy, vy0, vy1);
return J3ML::Math::Min(0.5, J3ML::Math::Max(-0.5, Lerp(wz, vz0, vz1)));
}
CaveGame::Core::PerlinNoise::PerlinNoise(int seed) {
random = RNG(seed);
InitGradients();
}
CaveGame::Core::PerlinNoise::PerlinNoise(J3ML::Algorithm::RNG rng) : random(rng) {
InitGradients();
}