HansonServo/noise.cpp

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);
}