From 3b7b104568648b2c864f129b044cc73ee542e673 Mon Sep 17 00:00:00 2001 From: seleb Date: Sun, 15 Nov 2015 17:56:43 -0500 Subject: [PATCH] added perlin noise/seeded rng --- .../S-Tengine2/S-Tengine2 - 2012.vcxproj | 1 + .../S-Tengine2/S-Tengine2 - 2013.vcxproj | 3 + .../Source/S-Tengine2/include/NumberUtils.h | 18 +++ S-Tengine2/Source/S-Tengine2/include/rng.h | 119 ++++++++++++++++++ .../Source/S-Tengine2/src/NumberUtils.cpp | 81 +++++++++++- 5 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 S-Tengine2/Source/S-Tengine2/include/rng.h diff --git a/S-Tengine2/Source/S-Tengine2/S-Tengine2 - 2012.vcxproj b/S-Tengine2/Source/S-Tengine2/S-Tengine2 - 2012.vcxproj index 9d451789..13a29868 100644 --- a/S-Tengine2/Source/S-Tengine2/S-Tengine2 - 2012.vcxproj +++ b/S-Tengine2/Source/S-Tengine2/S-Tengine2 - 2012.vcxproj @@ -154,6 +154,7 @@ + diff --git a/S-Tengine2/Source/S-Tengine2/S-Tengine2 - 2013.vcxproj b/S-Tengine2/Source/S-Tengine2/S-Tengine2 - 2013.vcxproj index 50fcd095..c2214f20 100644 --- a/S-Tengine2/Source/S-Tengine2/S-Tengine2 - 2013.vcxproj +++ b/S-Tengine2/Source/S-Tengine2/S-Tengine2 - 2013.vcxproj @@ -154,11 +154,13 @@ + + @@ -303,6 +305,7 @@ + diff --git a/S-Tengine2/Source/S-Tengine2/include/NumberUtils.h b/S-Tengine2/Source/S-Tengine2/include/NumberUtils.h index a081c862..2cde9b1a 100644 --- a/S-Tengine2/Source/S-Tengine2/include/NumberUtils.h +++ b/S-Tengine2/Source/S-Tengine2/include/NumberUtils.h @@ -4,7 +4,25 @@ namespace sweet{ class NumberUtils{ public: + // returns a random number in the range _min <= res < _max static float randomFloat(float _min, float _max); + // returns a random number in the range 0 to 1 + static float randomFloat(); + // returns a random number in the range _min <= res <= _max static int randomInt(int _min, int _max); + // returns a random number in the range 0 to something really really high + static int randomInt(); + + + // seeds the random number generator + static void seed(unsigned long int _seed); + + /* Perlin Noise port */ + static double pNoise(double _x, double _y, double _z); + private: + static long int p[512]; + static double fade(double _t); + static double lerp(double _t, double _a, double _b); + static double grad(int _hash, double _x, double _y, double _z); }; } \ No newline at end of file diff --git a/S-Tengine2/Source/S-Tengine2/include/rng.h b/S-Tengine2/Source/S-Tengine2/include/rng.h new file mode 100644 index 00000000..ffe2eecb --- /dev/null +++ b/S-Tengine2/Source/S-Tengine2/include/rng.h @@ -0,0 +1,119 @@ +#ifndef __STDC__ +#define undef__STDC__ 1 +#define __STDC__ 1 +#endif + + +/* This program by D E Knuth is in the public domain and freely copyable + * AS LONG AS YOU MAKE ABSOLUTELY NO CHANGES! + * It is explained in Seminumerical Algorithms, 3rd edition, Section 3.6 + * (or in the errata to the 2nd edition --- see + * http://www-cs-faculty.stanford.edu/~knuth/taocp.html + * in the changes to Volume 2 on pages 171 and following). */ + +/* N.B. The MODIFICATIONS introduced in the 9th printing (2002) are + included here; there's no backwards compatibility with the original. */ + +/* This version also adopts Brendan McKay's suggestion to + accommodate naive users who forget to call ran_start(seed). */ + +/* If you find any bugs, please report them immediately to + * taocp@cs.stanford.edu + * (and you will be rewarded if the bug is genuine). Thanks! */ + +/************ see the book for explanations and caveats! *******************/ +/************ in particular, you need two's complement arithmetic **********/ + +#define KK 100 /* the long lag */ +#define LL 37 /* the short lag */ +#define MM (1L<<30) /* the modulus */ +#define mod_diff(x,y) (((x)-(y))&(MM-1)) /* subtraction mod MM */ + +long ran_x[KK]; /* the generator state */ + +#ifdef __STDC__ +void ran_array(long aa[],int n) +#else +void ran_array(aa,n) /* put n new random numbers in aa */ + long *aa; /* destination */ + int n; /* array length (must be at least KK) */ +#endif +{ + register int i,j; + for (j=0;j=MM) ss-=MM-2; /* cyclic shift 29 bits */ + } + x[1]++; /* make x[1] (and only x[1]) odd */ + for (ss=seed&(MM-1),t=TT-1; t; ) { + for (j=KK-1;j>0;j--) x[j+j]=x[j], x[j+j-1]=0; /* "square" */ + for (j=KK+KK-2;j>=KK;j--) + x[j-(KK-LL)]=mod_diff(x[j-(KK-LL)],x[j]), + x[j-KK]=mod_diff(x[j-KK],x[j]); + if (is_odd(ss)) { /* "multiply by z" */ + for (j=KK;j>0;j--) x[j]=x[j-1]; + x[0]=x[KK]; /* shift the buffer cyclically */ + x[LL]=mod_diff(x[LL],x[KK]); + } + if (ss) ss>>=1; else t--; + } + for (j=0;j=0? *ran_arr_ptr++: ran_arr_cycle()) +long ran_arr_cycle() +{ + if (ran_arr_ptr==&ran_arr_dummy) + ran_start(314159L); /* the user forgot to initialize */ + ran_array(ran_arr_buf,QUALITY); + ran_arr_buf[KK]=-1; + ran_arr_ptr=ran_arr_buf+1; + return ran_arr_buf[0]; +} + +//#include +//int main() +//{ +// register int m; long a[2009]; +// ran_start(310952L); +// for (m=0;m<=2009;m++) ran_array(a,1009); +// printf("%ld\n", a[0]); /* 995235265 */ +// ran_start(310952L); +// for (m=0;m<=1009;m++) ran_array(a,2009); +// printf("%ld\n", a[0]); /* 995235265 */ +// return 0; +//} + +#ifdef undef__STDC__ +#undef __STDC__ +#endif \ No newline at end of file diff --git a/S-Tengine2/Source/S-Tengine2/src/NumberUtils.cpp b/S-Tengine2/Source/S-Tengine2/src/NumberUtils.cpp index 3dfd52be..5be7c1ad 100644 --- a/S-Tengine2/Source/S-Tengine2/src/NumberUtils.cpp +++ b/S-Tengine2/Source/S-Tengine2/src/NumberUtils.cpp @@ -1,15 +1,84 @@ #pragma once +#include #include -#include +#include float sweet::NumberUtils::randomFloat(float _min, float _max){ - float random = static_cast(rand()) / static_cast(RAND_MAX); - float diff = _max - _min; - float r = random * diff; - return _min + r; + return _min + randomFloat() * (_max - _min +1); + return 0; +} +float sweet::NumberUtils::randomFloat(){ + return (float)ran_arr_cycle()/(INT_MAX/2); } int sweet::NumberUtils::randomInt(int _min, int _max){ - return _min + (rand() % (_max - _min + 1)); + return _min + ran_arr_cycle() % (_max - _min +1); +} +int sweet::NumberUtils::randomInt(){ + return ran_arr_cycle(); +} + + + +long int sweet::NumberUtils::p[512]; + +void sweet::NumberUtils::seed(unsigned long int _seed){ + ran_start(_seed); + + // stuff for perlin noise permutation array + for(unsigned long int i = 0; i < 256; ++i){ + ran_array(p, 256); + } + for(unsigned long int i = 0; i < 256; ++i){ + p[i] %= 256; + p[256+i] = p[i]; + } +} + +// C++ port of improved perlin function found at http://mrl.nyu.edu/~perlin/noise/ +// ORIGINAL JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN +double sweet::NumberUtils::pNoise(double _x, double _y, double _z){ + + // unit cube that contains point + int X = (int)std::floor(_x) & 255, + Y = (int)std::floor(_y) & 255, + Z = (int)std::floor(_z) & 255; + + // relative XYZ of point in cube + _x -= std::floor(_x); + _y -= std::floor(_y); + _z -= std::floor(_z); + + // compute fade curves for XYZ + double + u = fade(_x), + v = fade(_y), + w = fade(_z); + + // hash coordinates of the 8 cube corners + int A = p[X]+Y, + AA = p[A]+Z, + AB = p[A+1]+Z, + B = p[X+1]+Y, + BA = p[B]+Z, + BB = p[B+1]+Z; + // and add blended results from 8 corners of cube + 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)))); +} + +double sweet::NumberUtils::fade(double _t) { return _t * _t * _t * (_t * (_t * 6 - 15) + 10); } +double sweet::NumberUtils::lerp(double _t, double _a, double _b) { return _a + _t * (_b - _a); } +double sweet::NumberUtils::grad(int _hash, double _x, double _y, double _z) { + int h = _hash & 15; // Convert LO 4 bits of hash code into 12 gradient directions + double u = h<8 ? _x : _y, + v = h<4 ? _y : h==12||h==14 ? _x : _z; + return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); } \ No newline at end of file