Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
7.0 KiB

  1. //========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: noise() primitives.
  4. //
  5. //=====================================================================================//
  6. #include <math.h>
  7. #include "basetypes.h"
  8. #ifndef _PS3
  9. #include <memory.h>
  10. #endif
  11. #include "tier0/dbg.h"
  12. #include "mathlib/mathlib.h"
  13. #include "mathlib/vector.h"
  14. #include "mathlib/noise.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. // generate high quality noise based upon "sparse convolution". HIgher quality than perlin noise,
  18. // and no direcitonal artifacts.
  19. #include "noisedata.h"
  20. #define N_IMPULSES_PER_CELL 5
  21. #define NORMALIZING_FACTOR 1.0
  22. //(0.5/N_IMPULSES_PER_CELL)
  23. static inline int LatticeCoord(float x)
  24. {
  25. return ((int) floor(x)) & 0xff;
  26. }
  27. static inline int Hash4D(int ix, int iy, int iz, int idx)
  28. {
  29. int ret=perm_a[ix];
  30. ret=perm_b[(ret+iy) & 0xff];
  31. ret=perm_c[(ret+iz) & 0xff];
  32. ret=perm_d[(ret+idx) & 0xff];
  33. return ret;
  34. }
  35. #define SQ(x) ((x)*(x))
  36. static float CellNoise( int ix, int iy, int iz, float xfrac, float yfrac, float zfrac,
  37. float (*pNoiseShapeFunction)(float) )
  38. {
  39. float ret=0;
  40. for(int idx=0;idx<N_IMPULSES_PER_CELL;idx++)
  41. {
  42. int coord_idx=Hash4D( ix, iy, iz, idx );
  43. float dsq=SQ(impulse_xcoords[coord_idx]-xfrac)+
  44. SQ(impulse_ycoords[coord_idx]-yfrac)+
  45. SQ(impulse_zcoords[coord_idx]-zfrac);
  46. dsq = sqrt( dsq );
  47. if (dsq < 1.0 )
  48. {
  49. ret += (*pNoiseShapeFunction)( 1-dsq );
  50. }
  51. }
  52. return ret;
  53. }
  54. float SparseConvolutionNoise( Vector const &pnt )
  55. {
  56. return SparseConvolutionNoise( pnt, QuinticInterpolatingPolynomial );
  57. }
  58. float FractalNoise( Vector const &pnt, int n_octaves)
  59. {
  60. float scale=1.0;
  61. float iscale=1.0;
  62. float ret=0;
  63. float sumscale=0;
  64. for(int o=0;o<n_octaves;o++)
  65. {
  66. Vector p1=pnt;
  67. p1 *= scale;
  68. ret+=iscale * SparseConvolutionNoise( p1 );
  69. sumscale += iscale;
  70. scale *= 2.0;
  71. iscale *= 0.5;
  72. }
  73. return ret * ( 1.0/sumscale );
  74. }
  75. float Turbulence( Vector const &pnt, int n_octaves)
  76. {
  77. float scale=1.0;
  78. float iscale=1.0;
  79. float ret=0;
  80. float sumscale=0;
  81. for(int o=0;o<n_octaves;o++)
  82. {
  83. Vector p1=pnt;
  84. p1 *= scale;
  85. ret+=iscale * fabs ( 2.0*( SparseConvolutionNoise( p1 )-.5 ) );
  86. sumscale += iscale;
  87. scale *= 2.0;
  88. iscale *= 0.5;
  89. }
  90. return ret * ( 1.0/sumscale );
  91. }
  92. #ifdef MEASURE_RANGE
  93. float fmin1=10000000.0;
  94. float fmax1=-1000000.0;
  95. #endif
  96. float SparseConvolutionNoise(Vector const &pnt, float (*pNoiseShapeFunction)(float) )
  97. {
  98. // computer integer lattice point
  99. int ix=LatticeCoord(pnt.x);
  100. int iy=LatticeCoord(pnt.y);
  101. int iz=LatticeCoord(pnt.z);
  102. // compute offsets within unit cube
  103. float xfrac=pnt.x-floor(pnt.x);
  104. float yfrac=pnt.y-floor(pnt.y);
  105. float zfrac=pnt.z-floor(pnt.z);
  106. float sum_out=0.;
  107. for(int ox=-1; ox<=1; ox++)
  108. for(int oy=-1; oy<=1; oy++)
  109. for(int oz=-1; oz<=1; oz++)
  110. {
  111. sum_out += CellNoise( ix+ox, iy+oy, iz+oz,
  112. xfrac-ox, yfrac-oy, zfrac-oz,
  113. pNoiseShapeFunction );
  114. }
  115. #ifdef MEASURE_RANGE
  116. fmin1=min(sum_out,fmin1);
  117. fmax1=max(sum_out,fmax1);
  118. #endif
  119. return RemapValClamped( sum_out, .544487, 9.219176, 0.0, 1.0 );
  120. }
  121. float TileableSparseConvolutionNoise(Vector const &pnt, float (*pNoiseShapeFunction)(float) )
  122. {
  123. // computer integer lattice point
  124. int ix=LatticeCoord(pnt.x);
  125. int iy=LatticeCoord(pnt.y);
  126. int iz=LatticeCoord(pnt.z);
  127. // compute offsets within unit cube
  128. float xfrac=pnt.x-floor(pnt.x);
  129. float yfrac=pnt.y-floor(pnt.y);
  130. float zfrac=pnt.z-floor(pnt.z);
  131. float sum_out=0.;
  132. for(int ox=-1; ox<=1; ox++)
  133. for(int oy=-1; oy<=1; oy++)
  134. for(int oz=-1; oz<=1; oz++)
  135. {
  136. sum_out += CellNoise( ix+ox, iy+oy, iz+oz,
  137. xfrac-ox, yfrac-oy, zfrac-oz,
  138. pNoiseShapeFunction );
  139. }
  140. #ifdef MEASURE_RANGE
  141. fmin1=min(sum_out,fmin1);
  142. fmax1=max(sum_out,fmax1);
  143. #endif
  144. return RemapValClamped( sum_out, .544487, 9.219176, 0.0, 1.0 );
  145. }
  146. // Improved Perlin Noise
  147. // The following code is the c-ification of Ken Perlin's new noise algorithm
  148. // "JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN"
  149. // as available here: http://mrl.nyu.edu/~perlin/noise/
  150. float NoiseGradient(int hash, float x, float y, float z)
  151. {
  152. int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
  153. float u = h<8 ? x : y; // INTO 12 GRADIENT DIRECTIONS.
  154. float v = h<4 ? y : (h==12||h==14 ? x : z);
  155. return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
  156. }
  157. int NoiseHashIndex( int i )
  158. {
  159. static int s_permutation[] =
  160. {
  161. 151,160,137,91,90,15,
  162. 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
  163. 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
  164. 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
  165. 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
  166. 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
  167. 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
  168. 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
  169. 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
  170. 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
  171. 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
  172. 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
  173. 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
  174. };
  175. return s_permutation[ i & 0xff ];
  176. }
  177. float ImprovedPerlinNoise( Vector const &pnt )
  178. {
  179. float fx = floor(pnt.x);
  180. float fy = floor(pnt.y);
  181. float fz = floor(pnt.z);
  182. int X = (int)fx & 255; // FIND UNIT CUBE THAT
  183. int Y = (int)fy & 255; // CONTAINS POINT.
  184. int Z = (int)fz & 255;
  185. float x = pnt.x - fx; // FIND RELATIVE X,Y,Z
  186. float y = pnt.y - fy; // OF POINT IN CUBE.
  187. float z = pnt.z - fz;
  188. float u = QuinticInterpolatingPolynomial(x); // COMPUTE FADE CURVES
  189. float v = QuinticInterpolatingPolynomial(y); // FOR EACH OF X,Y,Z.
  190. float w = QuinticInterpolatingPolynomial(z);
  191. int A = NoiseHashIndex( X ) + Y; // HASH COORDINATES OF
  192. int AA = NoiseHashIndex( A ) + Z; // THE 8 CUBE CORNERS,
  193. int AB = NoiseHashIndex( A + 1 ) + Z;
  194. int B = NoiseHashIndex( X + 1 ) + Y;
  195. int BA = NoiseHashIndex( B ) + Z;
  196. int BB = NoiseHashIndex( B + 1 ) + Z;
  197. float g0 = NoiseGradient(NoiseHashIndex(AA ), x , y , z );
  198. float g1 = NoiseGradient(NoiseHashIndex(BA ), x-1, y , z );
  199. float g2 = NoiseGradient(NoiseHashIndex(AB ), x , y-1, z );
  200. float g3 = NoiseGradient(NoiseHashIndex(BB ), x-1, y-1, z );
  201. float g4 = NoiseGradient(NoiseHashIndex(AA+1), x , y , z-1 );
  202. float g5 = NoiseGradient(NoiseHashIndex(BA+1), x-1, y , z-1 );
  203. float g6 = NoiseGradient(NoiseHashIndex(AB+1), x , y-1, z-1 );
  204. float g7 = NoiseGradient(NoiseHashIndex(BB+1), x-1, y-1, z-1 );
  205. // AND ADD BLENDED RESULTS FROM 8 CORNERS OF CUBE
  206. float g01 = Lerp( u, g0, g1 );
  207. float g23 = Lerp( u, g2, g3 );
  208. float g45 = Lerp( u, g4, g5 );
  209. float g67 = Lerp( u, g6, g7 );
  210. float g0123 = Lerp( v, g01, g23 );
  211. float g4567 = Lerp( v, g45, g67 );
  212. return Lerp( w, g0123,g4567 );
  213. }