Perlin Noise Implementation File
This commit is contained in:
88
Core/src/Core/Perlin.cpp
Normal file
88
Core/src/Core/Perlin.cpp
Normal 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();
|
||||
}
|
Reference in New Issue
Block a user