noise2d.cpp 14 KB

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