#include "stdafx.h"
#include "hwinperlinnoice.h"
namespace harlinn
{
namespace windows
{
namespace
{
int _grad3[12][3] =
{
{1,1,0}, {-1,1,0}, {1,-1,0}, {-1,-1,0},
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}
};
int _initPerm[] =
{
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69,
142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219,
203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230,
220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209,
76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173,
186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206,
59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163,
70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232,
178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128,
195, 78, 66, 215, 61, 156, 180
};
int _perm[512] = {0,};
bool permInitialize()
{
for (int i = 0; i < 512; i++)
{
_perm[i] = _initPerm[i & 255];
}
return true;
}
bool permInitialized = permInitialize();
inline int Floor(double x)
{
return x > 0 ? (int)x : (int)x - 1;
}
inline double Dot(int* g, double x, double y, double z)
{
return g[0] * x + g[1] * y + g[2] * z;
}
inline double Fade(double t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
inline double Mix(double a, double b, double t)
{
return (1 - t) * a + t * b;
}
inline double Noise(double x, double y, double z)
{
int X = Floor(x);
int Y = Floor(y);
int Z = Floor(z);
x = x - X;
y = y - Y;
z = z - Z;
X = X & 255;
Y = Y & 255;
Z = Z & 255;
int gi000 = _perm[X + _perm[Y + _perm[Z]]] % 12;
int gi001 = _perm[X + _perm[Y + _perm[Z + 1]]] % 12;
int gi010 = _perm[X + _perm[Y + 1 + _perm[Z]]] % 12;
int gi011 = _perm[X + _perm[Y + 1 + _perm[Z + 1]]] % 12;
int gi100 = _perm[X + 1 + _perm[Y + _perm[Z]]] % 12;
int gi101 = _perm[X + 1 + _perm[Y + _perm[Z + 1]]] % 12;
int gi110 = _perm[X + 1 + _perm[Y + 1 + _perm[Z]]] % 12;
int gi111 = _perm[X + 1 + _perm[Y + 1 + _perm[Z + 1]]] % 12;
double n000 = Dot(_grad3[gi000], x, y, z);
double n100 = Dot(_grad3[gi100], x - 1, y, z);
double n010 = Dot(_grad3[gi010], x, y - 1, z);
double n110 = Dot(_grad3[gi110], x - 1, y - 1, z);
double n001 = Dot(_grad3[gi001], x, y, z - 1);
double n101 = Dot(_grad3[gi101], x - 1, y, z - 1);
double n011 = Dot(_grad3[gi011], x, y - 1, z - 1);
double n111 = Dot(_grad3[gi111], x - 1, y - 1, z - 1);
double u = Fade(x);
double v = Fade(y);
double w = Fade(z);
double nx00 = Mix(n000, n100, u);
double nx01 = Mix(n001, n101, u);
double nx10 = Mix(n010, n110, u);
double nx11 = Mix(n011, n111, u);
double nxy0 = Mix(nx00, nx10, v);
double nxy1 = Mix(nx01, nx11, v);
double nxyz = Mix(nxy0, nxy1, w);
return nxyz;
}
double Generate(double x, double y, double z, double amplitude, double frequency, double persistence, int octaves)
{
double noiseValue = 0;
for (int i = 0; i < octaves; i++)
{
noiseValue += Noise(x * frequency, y * frequency, z * frequency) * amplitude;
frequency *= 2;
amplitude *= persistence;
}
noiseValue /= octaves;
return noiseValue;
}
int NoiceToColor(double noiseValue)
{
if (noiseValue < 0)
{
noiseValue = 0;
}
else if (noiseValue > 1)
{
noiseValue = 1;
}
return (int) (noiseValue * 255);
}
void GenerateNoise(int* pixels, int width, int height, double amplitude, double frequency, double persistence, int octaves, double zStart)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int r = NoiceToColor(Generate(x, y, zStart, amplitude, frequency, persistence, octaves));
int g = NoiceToColor(Generate(x, y, zStart + 100, amplitude, frequency, persistence, octaves));
int b = NoiceToColor(Generate(x, y, zStart + 200, amplitude, frequency, persistence, octaves));
pixels[y * width + x] = (255 << 24) + (r << 16) + (g << 8) + b;
}
}
}
}
HWIN_EXPORT PerlinNoice::PerlinNoice()
: pixels(nullptr),
width(0),
height(0),
amplitude(1.2),
frequency(0.020),
persistence(0.9),
octaves(3),
zStart(0)
{
}
HWIN_EXPORT PerlinNoice::PerlinNoice(int theWidth, int theHeight,double theAmplitude, double theFrequency, double thePersistence, int theOctaves, double theZStart)
: pixels(nullptr),
width(theWidth),
height(theHeight),
amplitude(theAmplitude),
frequency(theFrequency),
persistence(thePersistence),
octaves(theOctaves),
zStart(theZStart)
{
}
HWIN_EXPORT PerlinNoice::PerlinNoice(const PerlinNoice& other)
: pixels(nullptr),
width(other.width),
height(other.height),
amplitude(other.amplitude),
frequency(other.frequency),
persistence(other.persistence),
octaves(other.octaves),
zStart(other.zStart)
{
if(other.pixels)
{
size_t size = width*height;
pixels = new int[size];
memcpy(pixels,other.pixels,size);
}
}
HWIN_EXPORT PerlinNoice::PerlinNoice(PerlinNoice&& other)
: pixels(other.pixels),
width(other.width),
height(other.height),
amplitude(other.amplitude),
frequency(other.frequency),
persistence(other.persistence),
octaves(other.octaves),
zStart(other.zStart)
{
if(other.pixels)
{
other.pixels = nullptr;
}
}
HWIN_EXPORT PerlinNoice::~PerlinNoice()
{
if(pixels)
{
delete[] pixels;
}
}
HWIN_EXPORT PerlinNoice& PerlinNoice::operator = (const PerlinNoice& other)
{
size_t oldSize = width*height;
width = other.width;
height = other.height;
amplitude = other.amplitude;
frequency = other.frequency;
persistence = other.persistence;
octaves = other.octaves;
zStart = other.zStart;
if((other.pixels)&&(other.pixels != pixels))
{
size_t newSize = width*height;
if( pixels )
{
if(newSize != oldSize)
{
delete[] pixels;
pixels = new int[newSize];
}
}
else
{
pixels = new int[newSize];
}
memcpy(pixels,other.pixels,newSize);
}
else if(pixels)
{
delete[] pixels;
pixels = nullptr;
}
return *this;
}
HWIN_EXPORT PerlinNoice& PerlinNoice::operator = (PerlinNoice&& other)
{
if(this != &other )
{
width = other.width;
height = other.height;
amplitude = other.amplitude;
frequency = other.frequency;
persistence = other.persistence;
octaves = other.octaves;
zStart = other.zStart;
pixels = other.pixels;
other.pixels = nullptr;
}
return *this;
}
HWIN_EXPORT int* PerlinNoice::Pixels()
{
if(pixels == nullptr)
{
pixels = new int[width*height];
GenerateNoise(pixels,width,height,amplitude, frequency, persistence, octaves, zStart);
}
return pixels;
}
};
};