noise2d.cpp 14 KB

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