PNoise3.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Modified from original
  2. /*
  3. Based in part on Perlin noise
  4. http ://mrl.nyu.edu/~perlin/doc/oscar.html#noise
  5. Copyright(c) Ken Perlin
  6. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"),
  7. to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
  9. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  11. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  12. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  13. IN THE SOFTWARE.
  14. */
  15. #ifndef CRYINCLUDE_CRYCOMMON_PNOISE3_H
  16. #define CRYINCLUDE_CRYCOMMON_PNOISE3_H
  17. #pragma once
  18. #include <Random.h>
  19. #define NOISE_TABLE_SIZE 256
  20. #define NOISE_MASK (NOISE_TABLE_SIZE-1)
  21. namespace
  22. {
  23. const int kDefaultSeed=0;
  24. }
  25. //////////////////////////////////////////////////////////////////////////
  26. class CPNoise3
  27. {
  28. public:
  29. CPNoise3(void)
  30. {
  31. SetSeedAndReinitialize(kDefaultSeed);
  32. }
  33. //////////////////////////////////////////////////////////////////////////
  34. // 1D quality noise generator, good for many situations like up/down movements,
  35. // flickering/ambient lights etc.
  36. // A typical usage would be to pass system time multiplied by a frequency value, like:
  37. // float fRes=pNoise->Noise1D(fCurrentTime*fFreq);
  38. // the lower the frequency, the smoother the output
  39. inline float Noise1D(float x)
  40. {
  41. // Compute what gradients to use
  42. int qx0 = (int)floorf(x);
  43. int qx1 = qx0 + 1;
  44. float tx0 = x - (float)qx0;
  45. float tx1 = tx0 - 1;
  46. // Make sure we don't come outside the lookup table
  47. qx0 = qx0 & NOISE_MASK;
  48. qx1 = qx1 & NOISE_MASK;
  49. // Compute the dotproduct between the vectors and the gradients
  50. float v0 = m_gx[qx0]*tx0;
  51. float v1 = m_gx[qx1]*tx1;
  52. // Modulate with the weight function
  53. float wx = (3 - 2*tx0)*tx0*tx0;
  54. float v = v0 - wx*(v0 - v1);
  55. return v;
  56. }
  57. //////////////////////////////////////////////////////////////////////////
  58. // 2D quality noise generator, twice slower than Noise1D.
  59. // A typical usage would be to pass 2d coordinates multiplied by a frequency value, like:
  60. // float fRes=pNoise->Noise2D(fX*fFreq,fY*fFreq);
  61. inline float Noise2D(float x, float y)
  62. {
  63. // Compute what gradients to use
  64. int qx0 = (int)floorf(x);
  65. int qx1 = qx0 + 1;
  66. float tx0 = x - (float)qx0;
  67. float tx1 = tx0 - 1;
  68. int qy0 = (int)floorf(y);
  69. int qy1 = qy0 + 1;
  70. float ty0 = y - (float)qy0;
  71. float ty1 = ty0 - 1;
  72. // Make sure we don't come outside the lookup table
  73. qx0 = qx0 & NOISE_MASK;
  74. qx1 = qx1 & NOISE_MASK;
  75. qy0 = qy0 & NOISE_MASK;
  76. qy1 = qy1 & NOISE_MASK;
  77. // Permutate values to get pseudo randomly chosen gradients
  78. int q00 = m_p[(qy0 + m_p[qx0]) & NOISE_MASK];
  79. int q01 = m_p[(qy0 + m_p[qx1]) & NOISE_MASK];
  80. int q10 = m_p[(qy1 + m_p[qx0]) & NOISE_MASK];
  81. int q11 = m_p[(qy1 + m_p[qx1]) & NOISE_MASK];
  82. // Compute the dotproduct between the vectors and the gradients
  83. float v00 = m_gx[q00]*tx0 + m_gy[q00]*ty0;
  84. float v01 = m_gx[q01]*tx1 + m_gy[q01]*ty0;
  85. float v10 = m_gx[q10]*tx0 + m_gy[q10]*ty1;
  86. float v11 = m_gx[q11]*tx1 + m_gy[q11]*ty1;
  87. // Modulate with the weight function
  88. float wx = (3 - 2*tx0)*tx0*tx0;
  89. float v0 = v00 - wx*(v00 - v01);
  90. float v1 = v10 - wx*(v10 - v11);
  91. float wy = (3 - 2*ty0)*ty0*ty0;
  92. float v = v0 - wy*(v0 - v1);
  93. return v;
  94. }
  95. //////////////////////////////////////////////////////////////////////////
  96. // 3D quality noise generator, twice slower than Noise2D, so use with care...
  97. // A typical usage would be to pass 3d coordinates multiplied by a frequency value, like:
  98. // float fRes=pNoise->Noise2D(fX*fFreq,fY*fFreq,fZ*fFreq);
  99. inline float Noise3D(float x, float y, float z)
  100. {
  101. // Compute what gradients to use
  102. int qx0 = (int)floorf(x);
  103. int qx1 = qx0 + 1;
  104. float tx0 = x - (float)qx0;
  105. float tx1 = tx0 - 1;
  106. int qy0 = (int)floorf(y);
  107. int qy1 = qy0 + 1;
  108. float ty0 = y - (float)qy0;
  109. float ty1 = ty0 - 1;
  110. int qz0 = (int)floorf(z);
  111. int qz1 = qz0 + 1;
  112. float tz0 = z - (float)qz0;
  113. float tz1 = tz0 - 1;
  114. // Make sure we don't come outside the lookup table
  115. qx0 = qx0 & NOISE_MASK;
  116. qx1 = qx1 & NOISE_MASK;
  117. qy0 = qy0 & NOISE_MASK;
  118. qy1 = qy1 & NOISE_MASK;
  119. qz0 = qz0 & NOISE_MASK;
  120. qz1 = qz1 & NOISE_MASK;
  121. // Permutate values to get pseudo randomly chosen gradients
  122. int q000 = m_p[(qz0 + m_p[(qy0 + m_p[qx0]) & NOISE_MASK]) & NOISE_MASK];
  123. int q001 = m_p[(qz0 + m_p[(qy0 + m_p[qx1]) & NOISE_MASK]) & NOISE_MASK];
  124. int q010 = m_p[(qz0 + m_p[(qy1 + m_p[qx0]) & NOISE_MASK]) & NOISE_MASK];
  125. int q011 = m_p[(qz0 + m_p[(qy1 + m_p[qx1]) & NOISE_MASK]) & NOISE_MASK];
  126. int q100 = m_p[(qz1 + m_p[(qy0 + m_p[qx0]) & NOISE_MASK]) & NOISE_MASK];
  127. int q101 = m_p[(qz1 + m_p[(qy0 + m_p[qx1]) & NOISE_MASK]) & NOISE_MASK];
  128. int q110 = m_p[(qz1 + m_p[(qy1 + m_p[qx0]) & NOISE_MASK]) & NOISE_MASK];
  129. int q111 = m_p[(qz1 + m_p[(qy1 + m_p[qx1]) & NOISE_MASK]) & NOISE_MASK];
  130. // Compute the dotproduct between the vectors and the gradients
  131. float v000 = m_gx[q000]*tx0 + m_gy[q000]*ty0 + m_gz[q000]*tz0;
  132. float v001 = m_gx[q001]*tx1 + m_gy[q001]*ty0 + m_gz[q001]*tz0;
  133. float v010 = m_gx[q010]*tx0 + m_gy[q010]*ty1 + m_gz[q010]*tz0;
  134. float v011 = m_gx[q011]*tx1 + m_gy[q011]*ty1 + m_gz[q011]*tz0;
  135. float v100 = m_gx[q100]*tx0 + m_gy[q100]*ty0 + m_gz[q100]*tz1;
  136. float v101 = m_gx[q101]*tx1 + m_gy[q101]*ty0 + m_gz[q101]*tz1;
  137. float v110 = m_gx[q110]*tx0 + m_gy[q110]*ty1 + m_gz[q110]*tz1;
  138. float v111 = m_gx[q111]*tx1 + m_gy[q111]*ty1 + m_gz[q111]*tz1;
  139. // Modulate with the weight function
  140. float wx = (3 - 2*tx0)*tx0*tx0;
  141. float v00 = v000 - wx*(v000 - v001);
  142. float v01 = v010 - wx*(v010 - v011);
  143. float v10 = v100 - wx*(v100 - v101);
  144. float v11 = v110 - wx*(v110 - v111);
  145. float wy = (3 - 2*ty0)*ty0*ty0;
  146. float v0 = v00 - wy*(v00 - v01);
  147. float v1 = v10 - wy*(v10 - v11);
  148. float wz = (3 - 2*tz0)*tz0*tz0;
  149. float v = v0 - wz*(v0 - v1);
  150. return v;
  151. }
  152. //////////////////////////////////////////////////////////////////////////
  153. // this needs to be called only once and it's already done by crysystem in the singleton constructor
  154. // Note that every time the initialization function gets called, the PRNG will return
  155. // different values, thus creating different gradients. Not a bad thing but probably
  156. // not your expected behavior
  157. inline void SetSeedAndReinitialize(uint seedValue)
  158. {
  159. int i, j, nSwap;
  160. m_random_generator.Seed(seedValue);
  161. // Initialize the permutation table
  162. for(i = 0; i < NOISE_TABLE_SIZE; i++)
  163. m_p[i] = static_cast<unsigned char>(i);
  164. for(i = 0; i < NOISE_TABLE_SIZE; i++)
  165. {
  166. j = (m_random_generator.GenerateUint32())&NOISE_MASK;
  167. nSwap = m_p[i];
  168. m_p[i] = m_p[j];
  169. m_p[j] = static_cast<unsigned char>(nSwap);
  170. }
  171. // Generate the gradient lookup tables
  172. for(i = 0; i < NOISE_TABLE_SIZE; i++)
  173. {
  174. // Ken Perlin proposes that the gradients are taken from the unit
  175. // circle/sphere for 2D/3D.
  176. // So lets generate a good pseudo-random vector and normalize it
  177. Vec3 v;
  178. // cry_frand is in the 0..1 range
  179. v.x=-0.5f+m_random_generator.GenerateFloat();
  180. v.y=-0.5f+m_random_generator.GenerateFloat();
  181. v.z=-0.5f+m_random_generator.GenerateFloat();
  182. v.Normalize();
  183. m_gx[i] = v.x;
  184. m_gy[i] = v.y;
  185. m_gz[i] = v.z;
  186. }
  187. }
  188. private:
  189. CRndGen m_random_generator;
  190. // Permutation table
  191. unsigned char m_p[NOISE_TABLE_SIZE];
  192. // Gradients
  193. float m_gx[NOISE_TABLE_SIZE];
  194. float m_gy[NOISE_TABLE_SIZE];
  195. float m_gz[NOISE_TABLE_SIZE];
  196. };
  197. #endif // CRYINCLUDE_CRYCOMMON_PNOISE3_H