diff options
Diffstat (limited to 'src/procgen.cpp')
-rw-r--r-- | src/procgen.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/procgen.cpp b/src/procgen.cpp new file mode 100644 index 0000000..09ccae5 --- /dev/null +++ b/src/procgen.cpp @@ -0,0 +1,87 @@ +#include "common.hpp" +#include <cmath> + +namespace procgen { + +void prng_t::seed(uint32_t seed) +{ + state = seed; + next(); + next(); +} + +uint32_t prng_t::next(void) +{ + // glibc's LCG parameters (with m = 2^32 - 1). + state *= 1103515245; + state += 12345; + return state; +} + +float prng_t::next_float(void) +{ + return (float)next() / 4294967295.0f; +} + +void prng_t::unit_vec(float out[2]) +{ + float t; + + t = next_float() * 2.0f * M_PI; + out[0] = cos(t); + out[1] = sin(t); +} + +void perlin_noise_t::generate(prng_t *prng, size_t size_) +{ + if (table) + delete table; + + size = size_; + table = new float[size * size][2]; + + for (size_t y = 0; y < size; y++) + for (size_t x = 0; x < size; x++) + prng->unit_vec(table[y * size + x]); +} + +float perlin_noise_t::table_dot(size_t nx, size_t ny, float dx, float dy) +{ + return table[ny * size + nx][0] * dx + table[ny * size + nx][1] * dy; +} + +static float smooth_step(float x) +{ + return 3 * x * x - 2 * x * x * x; +} + +float perlin_noise_t::get(float x, float y, float scale) +{ + size_t nx, ny, nx1, ny1; + float s, t, a, b, c, d; + + x /= scale; + y /= scale; + + nx = mod<ssize_t>(floor(x), size); + ny = mod<ssize_t>(floor(y), size); + nx1 = (nx == size - 1 ? 0 : nx + 1); + ny1 = (ny == size - 1 ? 0 : ny + 1); + + s = smooth_step(x - floor(x)); + t = smooth_step(y - floor(y)); + + a = table_dot(nx, ny, -s, -t); + b = table_dot(nx1, ny, -s + 1.0f, -t); + c = table_dot(nx, ny1, -s, -t + 1.0f); + d = table_dot(nx1, ny1, -s + 1.0f, -t + 1.0f); + + return bilerp(a, b, c, d, s, t); +} + +perlin_noise_t::~perlin_noise_t() +{ + delete table; +} + +} // namespace procgen |