Add perlin noise implementation.
This commit is contained in:
parent
0f5a237b10
commit
bb0620f3aa
|
@ -0,0 +1,8 @@
|
||||||
|
SOURCES := noise.cc test.cc util.cc
|
||||||
|
|
||||||
|
noise: $(SOURCES)
|
||||||
|
g++ -o $@ $(SOURCES)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f noise
|
|
@ -0,0 +1,93 @@
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "noise.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
// C++ conversion of Ken Perlin's improved noise generator from
|
||||||
|
// https://mrl.nyu.edu/~perlin/noise/
|
||||||
|
|
||||||
|
|
||||||
|
static double
|
||||||
|
grad(int hash, double x, double y, double z)
|
||||||
|
{
|
||||||
|
int h = hash & 15;
|
||||||
|
double u = h < 8 ? x : y;
|
||||||
|
double v = h < 4 ? y : h == 12 || h == 14 ? x : z;
|
||||||
|
|
||||||
|
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static double
|
||||||
|
lerp(double t, double a, double b)
|
||||||
|
{
|
||||||
|
return a + t * (b - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static double
|
||||||
|
fade(double t)
|
||||||
|
{
|
||||||
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NoiseGenerator::NoiseGenerator()
|
||||||
|
{
|
||||||
|
// Generate a random permutation of 256 values from 0 to 255
|
||||||
|
// inclusive. This is generated by setting each value in the
|
||||||
|
// array to its index value, then putting it through a
|
||||||
|
// Fisher-Yates shuffle.
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
perm[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 255; i > 0; i--) {
|
||||||
|
int j = random() % (i + 1);
|
||||||
|
swap_u8(perm[i], perm[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
p[i] = perm[i];
|
||||||
|
p[i+256] = perm[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
NoiseGenerator::sample(double x, double y, double z)
|
||||||
|
{
|
||||||
|
uint16_t ux = (uint16_t)floor(x) & 255;
|
||||||
|
uint16_t uy = (uint16_t)floor(y) & 255;
|
||||||
|
uint16_t uz = (uint16_t)floor(z) & 255;
|
||||||
|
double u, v, w;
|
||||||
|
uint16_t a, aa, ab, b, ba, bb;
|
||||||
|
|
||||||
|
x -= floor(x);
|
||||||
|
u = fade(x);
|
||||||
|
|
||||||
|
y -= floor(y);
|
||||||
|
v = fade(y);
|
||||||
|
|
||||||
|
z -= floor(z);
|
||||||
|
w = fade(z);
|
||||||
|
|
||||||
|
a = p[ux] + uy;
|
||||||
|
aa = p[a] + uz;
|
||||||
|
ab = p[a + 1] + uz;
|
||||||
|
|
||||||
|
b = p[ux + 1] + uy;
|
||||||
|
ba = p[b] + uz;
|
||||||
|
bb = p[b + 1] + uz;
|
||||||
|
|
||||||
|
return lerp(w, lerp(v, lerp(u, grad(p[aa], x, y, z),
|
||||||
|
grad(p[ba], x-1, y, z)),
|
||||||
|
lerp(u, grad(p[ab], x, y-1, z),
|
||||||
|
grad(p[bb], x-1, y-1, z))),
|
||||||
|
lerp(v, lerp(u, grad(p[aa+1], x, y, z-1),
|
||||||
|
grad(p[ba+1], x-1, y, z-1)),
|
||||||
|
lerp(u, grad(p[ab+1], x, y-1, z-1),
|
||||||
|
grad(p[bb+1], x-1, y-1, z-1))));
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef __NOISE_H
|
||||||
|
#define __NOISE_H
|
||||||
|
|
||||||
|
|
||||||
|
class NoiseGenerator {
|
||||||
|
public:
|
||||||
|
NoiseGenerator();
|
||||||
|
double sample(double x, double y, double z);
|
||||||
|
void randomise();
|
||||||
|
private:
|
||||||
|
uint8_t p[512];
|
||||||
|
uint8_t perm[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __NOISE_H
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include "noise.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
NoiseGenerator noise;
|
||||||
|
|
||||||
|
for (double t = 0; t < 5; t += 0.01) {
|
||||||
|
cout << t << "\t" << noise.sample(t, t, t) << endl;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "util.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
swap_u8(uint8_t &a, uint8_t &b)
|
||||||
|
{
|
||||||
|
a ^= b;
|
||||||
|
b ^= a;
|
||||||
|
a ^= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
swap_ul(unsigned long &a, unsigned long &b)
|
||||||
|
{
|
||||||
|
a ^= b;
|
||||||
|
b ^= a;
|
||||||
|
a ^= b;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef __UTIL_H
|
||||||
|
#define __UTIL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
void swap_u8(uint8_t &a, uint8_t &b);
|
||||||
|
void swap_ul(unsigned long &a, unsigned long &b);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __UTIL_H
|
Loading…
Reference in New Issue