79 lines
1.6 KiB
C++
79 lines
1.6 KiB
C++
#include "noise.h"
|
|
#include <math.h>
|
|
#include <algorithm>
|
|
|
|
|
|
uint8_t perm[512];
|
|
static uint16_t currentSeed = 0xFFFF;
|
|
|
|
|
|
inline static float fade(float t) {
|
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
}
|
|
|
|
inline static float noiseLerp(float a, float b, float t) {
|
|
return a + t * (b - a);
|
|
}
|
|
|
|
inline static float grad(uint8_t hash, float x) {
|
|
uint8_t h = hash & 15;
|
|
float grad = 1.0f + (h & 7); // 1 to 8
|
|
if (h & 8) grad = -grad;
|
|
return (grad * x) / 4.0f; // match JS scaling
|
|
}
|
|
|
|
static void generatePermutation(uint16_t seed, uint8_t* perm) {
|
|
uint8_t p[256];
|
|
uint32_t s = seed;
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
s = (s * 1664525 + 1013904223) % 4294967296;
|
|
p[i] = i;
|
|
}
|
|
|
|
for (int i = 255; i > 0; i--) {
|
|
uint32_t j = s % (i + 1);
|
|
std::swap(p[i], p[j]);
|
|
s = (s * 1664525 + 1013904223) % 4294967296;
|
|
}
|
|
|
|
for (int i = 0; i < 512; i++) {
|
|
perm[i] = p[i & 255];
|
|
}
|
|
}
|
|
|
|
float perlin1D_octave(uint16_t seed, float x, int octaves = 4, float persistence = 0.5f) {
|
|
|
|
if (seed != currentSeed) {
|
|
generatePermutation(seed, perm);
|
|
currentSeed = seed;
|
|
}
|
|
|
|
float total = 0.0f;
|
|
float amplitude = 1.0f;
|
|
float frequency = 1.0f;
|
|
float maxValue = 0.0f;
|
|
|
|
for (int i = 0; i < octaves; i++) {
|
|
total += perlin1D(seed, x * frequency) * amplitude;
|
|
maxValue += amplitude;
|
|
amplitude *= persistence;
|
|
frequency *= 2.0f;
|
|
}
|
|
|
|
return total / maxValue;
|
|
}
|
|
|
|
|
|
float perlin1D(uint16_t seed, float x) {
|
|
|
|
int xi = static_cast<int>(floor(x)) & 255;
|
|
float xf = x - floor(x);
|
|
float u = fade(xf);
|
|
|
|
uint8_t a = perm[xi];
|
|
uint8_t b = perm[xi + 1];
|
|
|
|
return noiseLerp(grad(a, xf), grad(b, xf - 1.0f), u);
|
|
}
|