mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-28 10:30:38 +01:00
242 lines
8.0 KiB
C++
242 lines
8.0 KiB
C++
/*
|
|
* PerlinNoise.hpp
|
|
*
|
|
* Created on: Jul 11, 2008
|
|
* Author: pete
|
|
*/
|
|
|
|
#ifndef PERLINNOISE_HPP_
|
|
#define PERLINNOISE_HPP_
|
|
|
|
#include <math.h>
|
|
|
|
class PerlinNoise
|
|
{
|
|
public:
|
|
|
|
float noise_lq[256][256];
|
|
float noise_lq_lite[32][32];
|
|
float noise_mq[256][256];
|
|
float noise_hq[256][256];
|
|
float noise_perlin[512][512];
|
|
float noise_lq_vol[32][32][32];
|
|
float noise_hq_vol[32][32][32];
|
|
|
|
|
|
PerlinNoise();
|
|
virtual ~PerlinNoise();
|
|
|
|
private:
|
|
|
|
static inline float noise( int x)
|
|
{
|
|
x = (x<<13)^x;
|
|
return (((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 2147483648.0);
|
|
}
|
|
|
|
static inline float noise(int x, int y)
|
|
{
|
|
int n = x + y * 57;
|
|
return noise(n);
|
|
}
|
|
|
|
static inline float noise(int x, int y, int z)
|
|
{
|
|
int n = x + y * 57 + z * 141;
|
|
return noise(n);
|
|
}
|
|
|
|
static inline float cos_interp(float a, float b, float x)
|
|
{
|
|
float ft = x * 3.1415927;
|
|
float f = (1 - cos(ft)) * .5;
|
|
|
|
return a*(1-f) + b*f;
|
|
}
|
|
|
|
static inline float cubic_interp(float v0, float v1, float v2, float v3, float x)
|
|
{
|
|
float P = (v3 - v2) - (v0 - v1);
|
|
float Q = (v0 - v1) - P;
|
|
float R = v2 - v0;
|
|
|
|
return P*pow(x,3) + Q * pow(x,2) + R*x + v1;
|
|
}
|
|
|
|
static inline float InterpolatedNoise(float x, float y)
|
|
{
|
|
int integer_X = int(x);
|
|
float fractional_X = x - integer_X;
|
|
|
|
int integer_Y = int(y);
|
|
float fractional_Y = y - integer_Y;
|
|
|
|
float a0 = noise(integer_X - 1, integer_Y - 1);
|
|
float a1 = noise(integer_X, integer_Y - 1);
|
|
float a2 = noise(integer_X + 1, integer_Y - 1);
|
|
float a3 = noise(integer_X + 2, integer_Y - 1);
|
|
|
|
float x0 = noise(integer_X - 1, integer_Y);
|
|
float x1 = noise(integer_X, integer_Y);
|
|
float x2 = noise(integer_X + 1, integer_Y);
|
|
float x3 = noise(integer_X + 2, integer_Y);
|
|
|
|
float y0 = noise(integer_X + 0, integer_Y + 1);
|
|
float y1 = noise(integer_X, integer_Y + 1);
|
|
float y2 = noise(integer_X + 1, integer_Y + 1);
|
|
float y3 = noise(integer_X + 2, integer_Y + 1);
|
|
|
|
float b0 = noise(integer_X - 1, integer_Y + 2);
|
|
float b1 = noise(integer_X, integer_Y + 2);
|
|
float b2 = noise(integer_X + 1, integer_Y + 2);
|
|
float b3 = noise(integer_X + 2, integer_Y + 2);
|
|
|
|
float i0 = cubic_interp(a0 , a1, a2, a3, fractional_X);
|
|
float i1 = cubic_interp(x0 , x1, x2, x3, fractional_X);
|
|
float i2 = cubic_interp(y0 , y1, y2, y3, fractional_X);
|
|
float i3 = cubic_interp(b0 , b1, b2, b3, fractional_X);
|
|
|
|
return cubic_interp(i0, i1 , i2 , i3, fractional_Y);
|
|
|
|
}
|
|
|
|
static inline float perlin_octave_2d(float x,float y, int width, int seed, float period)
|
|
{
|
|
|
|
float freq=1/(float)(period);
|
|
|
|
int num=(int)(width*freq);
|
|
int step_x=(int)(x*freq);
|
|
int step_y=(int)(y*freq);
|
|
float zone_x=x*freq-step_x;
|
|
float zone_y=y*freq-step_y;
|
|
int box=step_x+step_y*num;
|
|
int noisedata=(box+seed);
|
|
|
|
float u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
|
|
float a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
|
|
float b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
|
|
float v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
|
|
|
|
float value=cubic_interp(u,a,b,v,zone_y);
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
static inline float perlin_octave_2d_cos(float x,float y, int width, int seed, float period)
|
|
{
|
|
|
|
float freq=1/(float)(period);
|
|
|
|
int num=(int)(width*freq);
|
|
int step_x=(int)(x*freq);
|
|
int step_y=(int)(y*freq);
|
|
float zone_x=x*freq-step_x;
|
|
float zone_y=y*freq-step_y;
|
|
int box=step_x+step_y*num;
|
|
int noisedata=(box+seed);
|
|
|
|
float a=cos_interp(noise(noisedata),noise(noisedata+1),zone_x);
|
|
float b=cos_interp(noise(noisedata+num),noise(noisedata+1+num),zone_x);
|
|
|
|
float value=cos_interp(a,b,zone_y);
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
|
|
static inline float perlin_octave_3d(float x,float y, float z,int width, int seed, float period)
|
|
{
|
|
float freq=1/(float)(period);
|
|
|
|
int num=(int)(width*freq);
|
|
int step_x=(int)(x*freq);
|
|
int step_y=(int)(y*freq);
|
|
int step_z=(int)(z*freq);
|
|
float zone_x=x*freq-step_x;
|
|
float zone_y=y*freq-step_y;
|
|
float zone_z=z*freq-step_z;
|
|
|
|
int boxB=step_x+step_y+step_z*num;
|
|
int boxC=step_x+step_y+step_z*(num+1);
|
|
int boxD=step_x+step_y+step_z*(num+2);
|
|
int boxA=step_x+step_y+step_z*(num-1);
|
|
|
|
float u,a,b,v,noisedata,box;
|
|
|
|
box = boxA;
|
|
noisedata=(box+seed);
|
|
u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
|
|
a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
|
|
b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
|
|
v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
|
|
float A=cubic_interp(u,a,b,v,zone_y);
|
|
|
|
box = boxB;
|
|
noisedata=(box+seed);
|
|
u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
|
|
a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
|
|
b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
|
|
v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
|
|
float B=cubic_interp(u,a,b,v,zone_y);
|
|
|
|
box = boxC;
|
|
noisedata=(box+seed);
|
|
u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
|
|
a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
|
|
b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
|
|
v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
|
|
float C=cubic_interp(u,a,b,v,zone_y);
|
|
|
|
box = boxD;
|
|
noisedata=(box+seed);
|
|
u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
|
|
a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
|
|
b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
|
|
v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
|
|
float D=cubic_interp(u,a,b,v,zone_y);
|
|
|
|
float value =cubic_interp(A,B,C,D,zone_z);
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
static inline float perlin_noise_2d(int x, int y, int width, int octaves, int seed, float persistance, float basePeriod)
|
|
{
|
|
float p = persistance;
|
|
float val = 0.0;
|
|
|
|
for (int i = 0; i<octaves;i++)
|
|
{
|
|
val += perlin_octave_2d_cos(x,y,width,seed,basePeriod) * p;
|
|
|
|
basePeriod *= 0.5;
|
|
p *= persistance;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
static inline float perlin_noise_3d(int x, int y, int z, int width, int octaves, int seed, float persistance, float basePeriod)
|
|
{
|
|
float p = persistance;
|
|
float val = 0.0;
|
|
|
|
for (int i = 0; i<octaves;i++)
|
|
{
|
|
val += perlin_octave_3d(x,y,z,width,seed,basePeriod) * p;
|
|
|
|
basePeriod *= 0.5;
|
|
p *= persistance;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
#endif /* PERLINNOISE_HPP_ */
|