noise2d.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "util/noise2d.h"
  23. #include "core/util/tVector.h"
  24. //--------------------------------------
  25. Noise2D::Noise2D()
  26. {
  27. dMemset(mPermutation, 0, sizeof(mPermutation));
  28. dMemset(mGradient, 0, sizeof(mGradient));
  29. mSeed = 0;
  30. }
  31. Noise2D::~Noise2D()
  32. {
  33. }
  34. //--------------------------------------
  35. void Noise2D::normalize(F32 v[2])
  36. {
  37. F32 s;
  38. s = mSqrt(v[0] * v[0] + v[1] * v[1]);
  39. v[0] = v[0] / s;
  40. v[1] = v[1] / s;
  41. }
  42. //--------------------------------------
  43. void Noise2D::setSeed(U32 seed)
  44. {
  45. if (mSeed == seed)
  46. return;
  47. mSeed = seed;
  48. mRandom.setSeed(mSeed);
  49. S32 i, j, k;
  50. for (i = 0 ; i < SIZE ; i++) {
  51. mPermutation[i] = i;
  52. for (j = 0 ; j < 2 ; j++)
  53. mGradient[i][j] = mRandom.randF( -1.0f, 1.0f );
  54. normalize(mGradient[i]);
  55. }
  56. while (--i) {
  57. k = mPermutation[i];
  58. j = mRandom.randI(0, SIZE-1);
  59. mPermutation[i] = mPermutation[j];
  60. mPermutation[j] = k;
  61. }
  62. // extend the size of the arrays x2 to get rid of a bunch of MODs
  63. // we'd have to do later in the code
  64. for (i = 0 ; i < SIZE + 2 ; i++) {
  65. mPermutation[SIZE + i] = mPermutation[i];
  66. for (j = 0 ; j < 2 ; j++)
  67. mGradient[SIZE + i][j] = mGradient[i][j];
  68. }
  69. }
  70. //--------------------------------------
  71. U32 Noise2D::getSeed()
  72. {
  73. return mSeed;
  74. }
  75. inline F32 Noise2D::curve(F32 t)
  76. {
  77. return t * t * (3.0f - 2.0f * t);
  78. }
  79. inline F32 clamp(F32 f, F32 m)
  80. {
  81. while (f > m)
  82. f -= m;
  83. while (f < 0.0f)
  84. f += m;
  85. return f;
  86. }
  87. //--------------------------------------
  88. void Noise2D::fBm( Vector<F32> *dst, U32 size, U32 interval, F32 h, F32 octaves )
  89. {
  90. interval = getMin(U32(128), getMax(U32(1), interval));
  91. F32 H = getMin(1.0f, getMax(0.0f, h));
  92. octaves = getMin(5.0f, getMax(1.0f, octaves));
  93. F32 lacunarity = 2.0f;
  94. F32 exponent_array[32];
  95. U32 shift = getBinLog2( size );
  96. // precompute and store spectral weights
  97. // seize required memory for exponent_array
  98. F32 frequency = 1.0;
  99. for (U32 i=0; i<=octaves; i++)
  100. {
  101. // compute weight for each frequency
  102. exponent_array[i] = mPow( frequency, -H );
  103. frequency *= lacunarity;
  104. }
  105. // initialize dst
  106. for (S32 k=0; k < (size*size); k++)
  107. (*dst)[k] = 0.0f;
  108. F32 scale = 1.0f / (F32)size * interval;
  109. for (S32 o=0; o<octaves; o++)
  110. {
  111. F32 exp = exponent_array[o];
  112. for (S32 y=0; y<size; y++)
  113. {
  114. F32 fy = (F32)y * scale;
  115. for (S32 x=0; x<size; x++)
  116. {
  117. F32 fx = (F32)x * scale;
  118. F32 noise = getValue(fx, fy, interval);
  119. (*dst)[x + (y << shift)] += noise * exp;
  120. }
  121. }
  122. scale *= lacunarity;
  123. interval = (U32)(interval * lacunarity);
  124. }
  125. }
  126. //--------------------------------------
  127. void Noise2D::rigidMultiFractal(Vector<F32> *dst, Vector<F32> *sig, U32 size, U32 interval, F32 h, F32 octaves)
  128. {
  129. interval = getMin(U32(128), getMax(U32(1), interval));
  130. F32 H = getMin(1.0f, getMax(0.0f, h));
  131. octaves = getMin(5.0f, getMax(1.0f, octaves));
  132. F32 lacunarity = 2.0f;
  133. F32 offset = 1.0f;
  134. F32 gain = 2.0f;
  135. U32 shift = getBinLog2( size );
  136. F32 exponent_array[32];
  137. // precompute and store spectral weights
  138. // seize required memory for exponent_array
  139. F32 frequency = 1.0;
  140. for (U32 i=0; i<=octaves; i++)
  141. {
  142. // compute weight for each frequency
  143. exponent_array[i] = mPow( frequency, -H );
  144. frequency *= lacunarity;
  145. }
  146. F32 scale = 1.0f / (F32)size * interval;
  147. //--------------------------------------
  148. // compute first octave
  149. for (S32 y=0; y<size; y++)
  150. {
  151. F32 fy = (F32)y * scale;
  152. for (S32 x=0; x<size; x++)
  153. {
  154. F32 fx = (F32)x * scale;
  155. F32 signal = mFabs(getValue(fx,fy,interval)); // get absolute value of signal (this creates the ridges)
  156. //signal = mSqrt(signal);
  157. signal = offset - signal; // invert and translate (note that "offset" should be ~= 1.0)
  158. signal *= signal + 0.1; // square the signal, to increase "sharpness" of ridges
  159. // assign initial values
  160. (*dst)[x + (y << shift)] = signal;
  161. (*sig)[x + (y << shift)] = signal;
  162. }
  163. }
  164. //--------------------------------------
  165. // compute remaining octaves
  166. for (S32 o=1; o<octaves; o++)
  167. {
  168. // increase the frequency
  169. scale *= lacunarity;
  170. interval = (U32)(interval * lacunarity);
  171. F32 exp = exponent_array[o];
  172. for (S32 y=0; y<size; y++)
  173. {
  174. F32 fy = (F32)y * scale;
  175. for (S32 x=0; x<size; x++)
  176. {
  177. F32 fx = (F32)x * scale;
  178. U32 index = x + (y << shift);
  179. F32 result = (*dst)[index];
  180. F32 signal = (*sig)[index];
  181. // weight successive contributions by previous signal
  182. F32 weight = mClampF(signal * gain, 0.0f, 1.0f);
  183. signal = mFabs(getValue( fx, fy, interval ));
  184. signal = offset - signal;
  185. signal *= signal + 0.2;
  186. // weight the contribution
  187. signal *= weight;
  188. result += signal * exp;
  189. (*dst)[index] = result;
  190. (*sig)[index] = signal;
  191. }
  192. }
  193. }
  194. for (S32 k=0; k < (size*size); k++)
  195. (*dst)[k] = ((*dst)[k]-1.0f)/2.0f;
  196. }
  197. bool Noise2D::erodeHydraulic( Vector<F32> *src, Vector<F32> *dst, U32 iterations, U32 size )
  198. {
  199. // early out if there is nothing to do
  200. if (iterations == 0 )
  201. {
  202. *dst = *src;
  203. return true;
  204. }
  205. F32 fmin, fmax;
  206. getMinMax( src, &fmin, &fmax, size);
  207. U32 shift = getBinLog2( size );
  208. U32 mask = size - 1;
  209. // currently using SCRATCH_3 for debugging -- Rick
  210. Vector<F32> scratch = *src;
  211. U32 *o = (U32*)scratch.address();
  212. Vector<F32> a = *src;
  213. Vector<F32> b = *src;
  214. Vector<F32> c = *src;
  215. for (S32 k=0; k < (size*size); k++)
  216. c[k] = 0.0f;
  217. for (S32 i=0; i<iterations; i++)
  218. {
  219. b = a;
  220. for (S32 y=0; y<size; y++)
  221. {
  222. for (S32 x=0; x<size; x++)
  223. {
  224. U32 srcOffset = (x + (y << shift));
  225. F32 height = a[srcOffset];
  226. o[srcOffset] = srcOffset;
  227. for (S32 y1=y-1; y1 <= y+1; y1++)
  228. {
  229. F32 maxDelta = 0.0f;
  230. S32 ywrap = (y1 & mask);
  231. for (S32 x1=x-1; x1 <= x+1; x1++)
  232. {
  233. if (x1 != x && y1 != y)
  234. {
  235. U32 adjOffset = ((x1 & mask) + (ywrap << shift));
  236. F32 &adjHeight = a[adjOffset];
  237. F32 delta = height - adjHeight;
  238. if (x1 != x || y1 != y)
  239. delta *= 1.414213562f; // compensate for diagonals
  240. if (delta > maxDelta)
  241. {
  242. maxDelta = delta;
  243. o[srcOffset] = adjOffset;
  244. }
  245. }
  246. }
  247. }
  248. }
  249. }
  250. for (S32 j=0; j < (size*size); j++)
  251. {
  252. F32 &s = a[j];
  253. F32 &d = b[ o[j] ];
  254. F32 delta = s - d;
  255. if (delta > 0.0f)
  256. {
  257. F32 alt = (s-fmin) / (fmax-fmin);
  258. F32 amt = delta * (0.1f * (1.0f-alt));
  259. s -= amt;
  260. d += amt;
  261. }
  262. }
  263. // debug only
  264. for (S32 k=0; k < (size*size); k++)
  265. c[k] += b[k] - a[k];
  266. Vector<F32> tmp = a;
  267. a = b;
  268. b = tmp;
  269. }
  270. *dst = b;
  271. //*dst = *c;
  272. return true;
  273. }
  274. bool Noise2D::erodeThermal(Vector<F32> *src, Vector<F32> *dst, F32 slope, F32 materialLoss, U32 iterations, U32 size, U32 squareSize, F32 maxHeight )
  275. {
  276. // early out if there is nothing to do
  277. if (iterations == 0 )
  278. {
  279. *dst = *src;
  280. return true;
  281. }
  282. F32 fmin, fmax;
  283. getMinMax(src, &fmin, &fmax, size);
  284. Vector<F32> a = *src;
  285. // Heightfield *b = getScratch(1);
  286. Vector<F32> r;
  287. r.setSize( size * size );
  288. //dMemset( r.address(), 0, r.memSize() );
  289. F32 conservation = 1.0f - mClampF(materialLoss, 0.0f, 100.0f)/100.0f;
  290. slope = mClampF(conservation, 0.0f, 89.0f); // clamp to 0-89 degrees
  291. F32 talusConst = mTan(mDegToRad(slope)) * squareSize; // in world units
  292. talusConst = talusConst * (fmax-fmin) / maxHeight; // scale to current height units
  293. F32 p = 0.1f;
  294. U32 mask = size - 1;
  295. U32 shift = getBinLog2( size );
  296. for (U32 i=0; i<iterations; i++)
  297. {
  298. // clear out the rubble accumulation field
  299. dMemset( r.address(), 0, r.memSize() );
  300. for (S32 y=0; y<size; y++)
  301. {
  302. for (S32 x=0; x<size; x++)
  303. {
  304. F32 *height = &a[ x + ( y << shift )];
  305. F32 *dstHeight = &r[ x + ( y << shift )];
  306. // for each height look at the immediate surrounding heights
  307. // if any are higher than talusConst erode on me
  308. for (S32 y1=y-1; y1 <= y+1; y1++)
  309. {
  310. S32 ywrap = (y1 & mask);
  311. for (S32 x1=x-1; x1 <= x+1; x1++)
  312. {
  313. if (x1 != x && y1 != y)
  314. {
  315. S32 adjOffset = ((x1 & mask) + (ywrap << shift));
  316. F32 adjHeight = a[adjOffset];
  317. F32 delta = adjHeight - *height;
  318. if (delta > talusConst)
  319. {
  320. F32 rubble = p * (delta - talusConst);
  321. r[adjOffset] -= rubble;
  322. *dstHeight += rubble * conservation;
  323. }
  324. }
  325. }
  326. }
  327. }
  328. }
  329. for (S32 k=0; k < (size*size); k++)
  330. a[k] += r[k];
  331. }
  332. *dst = a;
  333. return true;
  334. }
  335. void Noise2D::getMinMax( Vector<F32> *src, F32 *fmin, F32 *fmax, U32 size )
  336. {
  337. if (!src)
  338. return;
  339. F32 *p = (*src).address();
  340. *fmin = *p;
  341. *fmax = *p;
  342. for (S32 i=0; i < (size*size); i++, p++)
  343. {
  344. if (*fmin > *p) *fmin = *p;
  345. if (*fmax < *p) *fmax = *p;
  346. }
  347. }
  348. //--------------------------------------
  349. F32 Noise2D::turbulence(F32 x, F32 y, F32 freq)
  350. {
  351. F32 t, x2, y2;
  352. for ( t = 0.0f ; freq >= 3.0f ; freq /= 2.0f)
  353. {
  354. x2 = freq * x;
  355. y2 = freq * y;
  356. t += mFabs(getValue(x2, y2, (S32)freq)) / freq;
  357. }
  358. return t;
  359. }
  360. //--------------------------------------
  361. inline void Noise2D::setup(F32 t, S32 &b0, S32 &b1, F32 &r0, F32 &r1)
  362. {
  363. // find the bounding integers of u
  364. b0 = S32(t) & SIZE_MASK;
  365. b1 = (b0+1) & SIZE_MASK;
  366. // seperate the fractional components
  367. r0 = t - (S32)t;
  368. r1 = r0 - 1.0f;
  369. }
  370. inline F32 Noise2D::dot(const F32 *q, F32 rx, F32 ry)
  371. {
  372. return (rx * q[0] + ry * q[1] );
  373. }
  374. //--------------------------------------
  375. F32 Noise2D::getValue(F32 x, F32 y, S32 interval)
  376. {
  377. S32 bx0, bx1, by0, by1;
  378. F32 rx0, rx1, ry0, ry1;
  379. // Imagine having a square of the type
  380. // p0---p1 Where p0 = (bx0, by0) +----> U
  381. // |(u,v)| p1 = (bx1, by0) |
  382. // | | p2 = (bx0, by1) | Coordinate System
  383. // p2---p3 p3 = (bx1, by1) V
  384. // The u, v point in 2D texture space is bounded by this rectangle.
  385. // Goal, determine the scalar at the points p0, p1, p2, p3.
  386. // Then the scalar of the point (u, v) will be found by linear interpolation.
  387. // First step: Get the 2D coordinates of the points p0, p1, p2, p3.
  388. // We also need vectors pointing from each point in the square above and
  389. // ending at the (u,v) coordinate located inside the square.
  390. // The vector (rx0, ry0) goes from P0 to the (u,v) coordinate.
  391. // The vector (rx1, ry0) goes from P1 to the (u,v) coordinate.
  392. // The vector (rx0, ry1) goes from P2 to the (u,v) coordinate.
  393. // The vector (rx1, ry1) goes from P3 to the (u,v) coordinate.
  394. setup(x, bx0, bx1, rx0, rx1);
  395. setup(y, by0, by1, ry0, ry1);
  396. // Make sure the box corners fall within the interval
  397. // so that the final output will wrap on itself
  398. bx0 = bx0 % interval;
  399. bx1 = bx1 % interval;
  400. by0 = by0 % interval;
  401. by1 = by1 % interval;
  402. S32 i = mPermutation[ bx0 ];
  403. S32 j = mPermutation[ bx1 ];
  404. S32 b00 = mPermutation[ i + by0 ];
  405. S32 b10 = mPermutation[ j + by0 ];
  406. S32 b01 = mPermutation[ i + by1 ];
  407. S32 b11 = mPermutation[ j + by1 ];
  408. // Next, calculate the dropoff component about the point p0.
  409. F32 sx = curve(rx0);
  410. F32 sy = curve(ry0);
  411. // Now, for each point in the square shown above, calculate the dot
  412. // product of the gradiant vector and the vector going from each square
  413. // corner point to the (u,v) point inside the square.
  414. F32 u = dot(mGradient[ b00 ], rx0,ry0);
  415. F32 v = dot(mGradient[ b10 ], rx1,ry0);
  416. // Interpolation along the X axis.
  417. F32 a = mLerp(u, v,sx);
  418. u = dot(mGradient[ b01 ], rx0,ry1);
  419. v = dot(mGradient[ b11 ], rx1,ry1);
  420. // Interpolation along the Y axis.
  421. F32 b = mLerp( u, v, sx);
  422. // Final Interpolation
  423. return mLerp(a, b,sy);
  424. }