GR32.Noise.Simplex.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. unit GR32.Noise.Simplex;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Simplex Noise for Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Anders Melander <[email protected]>
  26. *
  27. *
  28. * Portions created by the Initial Developer are Copyright (C) 2024
  29. * the Initial Developer. All Rights Reserved.
  30. *
  31. * ***** END LICENSE BLOCK ***** *)
  32. interface
  33. {$include GR32.inc}
  34. //------------------------------------------------------------------------------
  35. //
  36. // Simplex Noise
  37. //
  38. //------------------------------------------------------------------------------
  39. // References:
  40. //
  41. // - "Noise hardware"
  42. // Ken Perlin
  43. // Real-Time Shading SIGGRAPH Course Notes (2001),
  44. // http://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf
  45. //
  46. // - "Simplex noise demystified"
  47. // Stefan Gustavson
  48. // Linköping University, Sweden ([email protected])
  49. // 2005-03-22 (with 2012 errata)
  50. // https://github.com/stegu/perlin-noise/blob/master/simplexnoise.pdf
  51. //
  52. //------------------------------------------------------------------------------
  53. //
  54. // Adapted from code by Stefan Gustavson
  55. //
  56. // https://github.com/stegu/perlin-noise/blob/master/src/simplexnoise1234.c
  57. // https://github.com/stegu/perlin-noise/blob/master/src/sdnoise1234.c
  58. //
  59. // Original Pascal port by Teemu Valo for nxPascal.
  60. //
  61. // This is Stefan Gustavson's original copyright notice:
  62. //
  63. // /* sdnoise1234, Simplex noise with true analytic
  64. // * derivative in 1D to 4D.
  65. // *
  66. // * Copyright © 2003-2011, Stefan Gustavson
  67. // *
  68. // * Contact: [email protected]
  69. // *
  70. // * This library is public domain software, released by the author
  71. // * into the public domain in February 2011. You may do anything
  72. // * you like with it. You may even remove all attributions,
  73. // * but of course I'd appreciate it if you kept my name somewhere.
  74. // *
  75. // * This library is distributed in the hope that it will be useful,
  76. // * but WITHOUT ANY WARRANTY; without even the implied warranty of
  77. // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  78. // * General Public License for more details.
  79. // */
  80. //
  81. //------------------------------------------------------------------------------
  82. //------------------------------------------------------------------------------
  83. //
  84. // TSimplexNoise
  85. //
  86. //------------------------------------------------------------------------------
  87. type
  88. TSimplexNoise = class
  89. private
  90. class var
  91. FSeedMultiplier: Int64;
  92. private
  93. const
  94. // Literal values since Delphi can't compute Sqrt at compile time :-(
  95. F2 = 0.36602540378443864676372317075294; // 0.5 * (Sqrt(3.0) - 1.0)
  96. G2 = 0.21132486540518711774542560974902; // (3.0 - Sqrt(3.0)) / 6.0
  97. F3 = 1.0 / 3.0;
  98. G3 = 1.0 / 6.0;
  99. F4 = 0.30901699437494742410229341718282; // (Sqrt(5.0) - 1.0) / 4.0
  100. G4 = 0.13819660112501051517954131656344; // (5.0 - Sqrt(5.0)) / 20.0
  101. private
  102. // To remove the need for index wrapping, we double the permutation table length
  103. FPerm: array[0..511] of byte;
  104. FPermMod12: array[0..511] of byte;
  105. FSeed: Int64;
  106. procedure InitWithSeed(const ASeed: Int64);
  107. class constructor Create;
  108. public
  109. constructor Create; overload;
  110. constructor Create(const ASeed: Int64); overload;
  111. function Noise(const x, y: Double): Double; overload;
  112. function Noise(const x, y, z: Double): Double; overload;
  113. function Noise(const x, y, z, w: Double): Double; overload;
  114. property Seed: Int64 read FSeed;
  115. class property SeedMult: Int64 read FSeedMultiplier write FSeedMultiplier;
  116. end;
  117. implementation
  118. uses
  119. Math,
  120. GR32_LowLevel;
  121. type
  122. T8Bytes = array[0..7] of byte;
  123. type
  124. TVector3 = record
  125. case Integer of
  126. 0: (V: array[0..2] of Double;);
  127. 1: (X: Double;
  128. Y: Double;
  129. Z: Double;);
  130. end;
  131. TVector4 = record
  132. case Integer of
  133. 0: (V: array[0..3] of Double;);
  134. 1: (X: Double;
  135. Y: Double;
  136. Z: Double;
  137. W: Double;);
  138. end;
  139. var
  140. Gradient3D: array[0..11] of TVector3 = (
  141. (x: 1; y: 1; z: 0), (x:-1; y: 1; z: 0), (x: 1; y:-1; z: 0), (x:-1; y:-1; z: 0),
  142. (x: 1; y: 0; z: 1), (x:-1; y: 0; z: 1), (x: 1; y: 0; z:-1), (x:-1; y: 0; z:-1),
  143. (x: 0; y: 1; z: 1), (x: 0; y:-1; z: 1), (x: 0; y: 1; z:-1), (x: 0; y:-1; z:-1));
  144. Gradient4D: array[0..31] of TVector4 = (
  145. (x: 0; y: 1; z: 1; w: 1), (x: 0; y: 1; z: 1; w:-1), (x: 0; y: 1; z:-1; w: 1), (x: 0; y: 1; z:-1; w:-1),
  146. (x: 0; y:-1; z: 1; w: 1), (x: 0; y:-1; z: 1; w:-1), (x: 0; y:-1; z:-1; w: 1), (x: 0; y:-1; z:-1; w:-1),
  147. (x: 1; y: 0; z: 1; w: 1), (x: 0; y:-1; z: 1; w:-1), (x: 0; y:-1; z:-1; w: 1), (x: 0; y:-1; z:-1; w:-1),
  148. (x:-1; y: 0; z: 1; w: 1), (x:-1; y: 0; z: 1; w:-1), (x:-1; y: 0; z:-1; w: 1), (x:-1; y: 0; z:-1; w:-1),
  149. (x: 1; y: 1; z: 0; w: 1), (x: 1; y: 1; z: 0; w:-1), (x: 1; y:-1; z: 0; w: 1), (x: 1; y:-1; z: 0; w:-1),
  150. (x:-1; y: 1; z: 0; w: 1), (x:-1; y: 1; z: 0; w:-1), (x:-1; y:-1; z: 0; w: 1), (x:-1; y:-1; z: 0; w:-1),
  151. (x: 1; y: 1; z: 1; w: 0), (x: 1; y: 1; z:-1; w: 0), (x: 1; y:-1; z: 1; w: 0), (x: 1; y:-1; z:-1; w: 0),
  152. (x:-1; y: 1; z: 1; w: 0), (x:-1; y: 1; z:-1; w: 0), (x:-1; y:-1; z: 1; w: 0), (x:-1; y:-1; z:-1; w: 0));
  153. p: array[byte] of byte = (151,160,137,91,90,15,
  154. 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
  155. 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
  156. 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
  157. 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
  158. 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
  159. 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
  160. 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
  161. 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
  162. 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
  163. 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
  164. 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
  165. 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180);
  166. function Dot(const v: TVector3; const x, y: Double): Double; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  167. begin
  168. Result := (v.x * x) + (v.y * y);
  169. end;
  170. function Dot(const v: TVector3; const x, y, z: Double): Double; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  171. begin
  172. Result:= (v.x * x) + (v.y * y) + (v.z * z);
  173. end;
  174. function Dot(const v: TVector4; const x, y, z, w: Double): Double; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  175. begin
  176. Result := (v.x * x) + (v.y * y) + (v.z * z) + (v.w * w);
  177. end;
  178. //------------------------------------------------------------------------------
  179. //
  180. // TSimplexNoise
  181. //
  182. //------------------------------------------------------------------------------
  183. class constructor TSimplexNoise.Create;
  184. begin
  185. FSeedMultiplier := 85123154182917;
  186. end;
  187. //------------------------------------------------------------------------------
  188. // Seed overflowing is expected and ok
  189. {$IFOPT Q+}{$DEFINE Q_PLUS}{$OVERFLOWCHECKS OFF}{$ENDIF}
  190. constructor TSimplexNoise.Create;
  191. begin
  192. InitWithSeed(Random(High(Integer)));
  193. end;
  194. constructor TSimplexNoise.Create(const ASeed: Int64);
  195. begin
  196. InitWithSeed(ASeed * FSeedMultiplier);
  197. end;
  198. {$IFDEF Q_PLUS}{$OVERFLOWCHECKS ON}{$UNDEF Q_PLUS}{$ENDIF}
  199. //------------------------------------------------------------------------------
  200. procedure TSimplexNoise.InitWithSeed(const ASeed: Int64);
  201. var
  202. i: integer;
  203. begin
  204. FSeed := ASeed;
  205. // Pretty crappy seed hash but most likely "good enough"
  206. for i := 0 to High(FPerm) do
  207. begin
  208. FPerm[i] := p[i and 255] xor T8Bytes(ASeed)[i and 7];
  209. FPermMod12[i] := Byte(FPerm[i] mod 12);
  210. end;
  211. end;
  212. //------------------------------------------------------------------------------
  213. // 2D simplex
  214. //------------------------------------------------------------------------------
  215. function TSimplexNoise.Noise(const x, y: Double): Double;
  216. var
  217. i1, j1: integer; // Offsets for second (middle) corner of simplex in (i,j) coords
  218. i, j, ii, jj: integer;
  219. gi0, gi1, gi2: integer;
  220. n0, n1, n2: Double; // Noise contributions from the three corners
  221. s, t: Double;
  222. X0, Y0: Double;
  223. xx, yy: Double;
  224. x1, y1: Double;
  225. x2, y2: Double;
  226. t0, t1, t2: Double;
  227. begin
  228. // Skew the input space to determine which simplex cell we're in
  229. s := (x + y) * F2; // Hairy factor for 2D
  230. i := FastFloor(x + s);
  231. j := FastFloor(y + s);
  232. t := (i + j) * G2;
  233. X0 := i - t; // Unskew the cell origin back to (x,y) space
  234. Y0 := j - t;
  235. xx := x - X0; // The x,y distances from the cell origin
  236. yy := y - Y0;
  237. // For the 2D case, the simplex shape is an equilateral triangle.
  238. // Determine which simplex we are in.
  239. if (xx > yy) then
  240. begin // lower triangle, XY order: (0,0)->(1,0)->(1,1)
  241. i1:=1;
  242. j1:=0;
  243. end else
  244. begin // upper triangle, YX order: (0,0)->(0,1)->(1,1)
  245. i1:=0;
  246. j1:=1;
  247. end;
  248. // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
  249. // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
  250. // c = (3-sqrt(3))/6
  251. x1 := xx - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
  252. y1 := yy - j1 + G2;
  253. x2 := xx - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
  254. y2 := yy - 1.0 + 2.0 * G2;
  255. // Work out the hashed gradient indices of the three simplex corners
  256. ii := i and 255;
  257. jj := j and 255;
  258. gi0 := FPermMod12[ii + FPerm[jj ]];
  259. gi1 := FPermMod12[ii + i1 + FPerm[jj + j1]];
  260. gi2 := FPermMod12[ii + 1 + FPerm[jj + 1 ]];
  261. // Calculate the contribution from the three corners
  262. t0 := 0.5 - (xx * xx) - (yy * yy);
  263. if (t0 < 0) then
  264. n0 := 0.0
  265. else
  266. begin
  267. t0 := t0 * t0;
  268. n0 := t0 * t0 * Dot(Gradient3D[gi0], xx, yy); // (x,y) of Gradient3D used for 2D gradient
  269. end;
  270. t1 := 0.5 - (x1 * x1) - (y1 * y1);
  271. if (t1 < 0) then
  272. n1 := 0.0
  273. else
  274. begin
  275. t1 := t1 * t1;
  276. n1 := t1 * t1 * Dot(Gradient3D[gi1], x1, y1);
  277. end;
  278. t2 := 0.5 - (x2 * x2) - (y2 * y2);
  279. if (t2 < 0) then
  280. n2 := 0.0
  281. else
  282. begin
  283. t2 := t2 * t2;
  284. n2 := t2 * t2 * Dot(Gradient3D[gi2], x2, y2);
  285. end;
  286. // Add contributions from each corner to get the final noise value.
  287. // The result is scaled to return values in the interval [-1,1].
  288. Result := 70.14805770653952 * (n0 + n1 + n2);
  289. end;
  290. //------------------------------------------------------------------------------
  291. // 3D simplex
  292. //------------------------------------------------------------------------------
  293. function TSimplexNoise.Noise(const x, y, z: Double): Double;
  294. var
  295. i1, j1, k1: integer; // Offsets for second corner of simplex in (i,j,k) coords
  296. i2, j2, k2: integer; // Offsets for third corner of simplex in (i,j,k) coords
  297. i, j, k, ii, jj, kk: integer;
  298. gi0, gi1, gi2, gi3: integer;
  299. n0, n1, n2, n3: Double; // Noise contributions from the four corners
  300. s, t: Double;
  301. X0, Y0, Z0: Double;
  302. xx, yy, zz: Double;
  303. x1, y1, z1: Double;
  304. x2, y2, z2: Double;
  305. x3, y3, z3: Double;
  306. t0, t1, t2, t3: Double;
  307. begin
  308. // Skew the input space to determine which simplex cell we're in
  309. s := (x + y + z) * F3; // Very nice and simple skew factor for 3D
  310. i := FastFloor(x + s);
  311. j := FastFloor(y + s);
  312. k := FastFloor(z + s);
  313. t := (i + j + k) * G3;
  314. X0 := i - t; // Unskew the cell origin back to (x,y,z) space
  315. Y0 := j - t;
  316. Z0 := k - t;
  317. xx := x - X0; // The x,y,z distances from the cell origin
  318. yy := y - Y0;
  319. zz := z - Z0;
  320. // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
  321. // Determine which simplex we are in.
  322. if (xx >= yy) then
  323. begin
  324. if (yy >= zz) then
  325. begin
  326. i1 := 1; j1 := 0; k1 := 0; i2 := 1; j2 := 1; k2 := 0; // X Y Z order
  327. end else
  328. if (xx >= zz) then
  329. begin
  330. i1 := 1; j1 := 0; k1 := 0; i2 := 1; j2 := 0; k2 := 1; // X Z Y order
  331. end else
  332. begin
  333. i1 := 0; j1 := 0; k1 := 1; i2 := 1; j2 := 0; k2 := 1; // Z X Y order
  334. end;
  335. end else
  336. begin // xx < yy
  337. if (yy < zz) then
  338. begin
  339. i1 := 0; j1 := 0; k1 := 1; i2 := 0; j2 := 1; k2 := 1; // Z Y X order
  340. end else
  341. if(xx < zz) then
  342. begin
  343. i1 := 0; j1 := 1; k1 := 0; i2 := 0; j2 := 1; k2 := 1; // Y Z X order
  344. end else
  345. begin
  346. i1 := 0; j1 := 1; k1 := 0; i2 := 1; j2 := 1; k2 := 0; // Y X Z order
  347. end;
  348. end;
  349. // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
  350. // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
  351. // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
  352. // c = 1/6.
  353. x1 := xx - i1 + G3; // Offsets for second corner in (x,y,z) coords
  354. y1 := yy - j1 + G3;
  355. z1 := zz - k1 + G3;
  356. x2 := xx - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
  357. y2 := yy - j2 + 2.0 * G3;
  358. z2 := zz - k2 + 2.0 * G3;
  359. x3 := xx - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
  360. y3 := yy - 1.0 + 3.0 * G3;
  361. z3 := zz - 1.0 + 3.0 * G3;
  362. // Work out the hashed gradient indices of the four simplex corners
  363. ii := i and 255;
  364. jj := j and 255;
  365. kk := k and 255;
  366. gi0 := FPermMod12[ii + FPerm[jj + FPerm[kk ]]];
  367. gi1 := FPermMod12[ii + i1 + FPerm[jj + j1 + FPerm[kk + k1]]];
  368. gi2 := FPermMod12[ii + i2 + FPerm[jj + j2 + FPerm[kk + k2]]];
  369. gi3 := FPermMod12[ii + 1 + FPerm[jj + 1 + FPerm[kk + 1 ]]];
  370. // Calculate the contribution from the four corners
  371. t0 := 0.6 - (xx * xx) - (yy * yy) - (zz * zz);
  372. if (t0 < 0) then
  373. n0 := 0.0
  374. else
  375. begin
  376. t0 := t0 * t0;
  377. n0 := t0 * t0 * Dot(Gradient3D[gi0], xx, yy, zz);
  378. end;
  379. t1 := 0.6 - (x1 * x1) - (y1 * y1) - (z1 * z1);
  380. if (t1 < 0) then
  381. n1 := 0.0
  382. else
  383. begin
  384. t1 := t1 * t1;
  385. n1 := t1 * t1 * Dot(Gradient3D[gi1], x1, y1, z1);
  386. end;
  387. t2 := 0.6 - (x2 * x2) - (y2 * y2) - (z2 * z2);
  388. if (t2 < 0) then
  389. n2 := 0.0
  390. else
  391. begin
  392. t2 := t2 * t2;
  393. n2 := t2 * t2 * Dot(Gradient3D[gi2], x2, y2, z2);
  394. end;
  395. t3 := 0.6 - (x3 * x3) - (y3 * y3) - (z3 * z3);
  396. if (t3 < 0) then
  397. n3 := 0.0
  398. else
  399. begin
  400. t3 := t3 * t3;
  401. n3 := t3 * t3 * Dot(Gradient3D[gi3], x3, y3, z3);
  402. end;
  403. // Add contributions from each corner to get the final noise value.
  404. // The result is scaled to stay just inside [-1,1]
  405. Result := 32.0 * (n0 + n1 + n2 + n3);
  406. Assert(Result >= -1);
  407. Assert(Result <= 1);
  408. end;
  409. //------------------------------------------------------------------------------
  410. // 4D simplex
  411. //------------------------------------------------------------------------------
  412. function TSimplexNoise.Noise(const x, y, z, w: Double): Double;
  413. var
  414. i, j, k, l: integer;
  415. ii, jj, kk, ll: integer;
  416. rankx, ranky, rankz, rankw: integer;
  417. gi0, gi1, gi2, gi3, gi4: integer;
  418. i1, j1, k1, l1: integer;
  419. i2, j2, k2, l2: integer;
  420. i3, j3, k3, l3: integer;
  421. n0, n1, n2, n3, n4: Double;
  422. X0, Y0, Z0, W0: Double;
  423. xx, yy, zz, ww: Double;
  424. s, t, t0, t1, t2, t3, t4: Double;
  425. x1, y1, z1, w1: Double;
  426. x2, y2, z2, w2: Double;
  427. x3, y3, z3, w3: Double;
  428. x4, y4, z4, w4: Double;
  429. begin
  430. // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
  431. s := (x + y + z + w) * F4; // Factor for 4D skewing
  432. i := FastFloor(x + s);
  433. j := FastFloor(y + s);
  434. k := FastFloor(z + s);
  435. l := FastFloor(w + s);
  436. t := (i + j + k + l) * G4; // Factor for 4D unskewing
  437. X0 := i - t; // Unskew the cell origin back to (x,y,z,w) space
  438. Y0 := j - t;
  439. Z0 := k - t;
  440. W0 := l - t;
  441. xx := x - X0; // The x,y,z,w distances from the cell origin
  442. yy := y - Y0;
  443. zz := z - Z0;
  444. ww := w - W0;
  445. // For the 4D case, the simplex is a 4D shape I won't even try to describe.
  446. // To find out which of the 24 possible simplices we're in, we need to
  447. // determine the magnitude ordering of x0, y0, z0 and w0.
  448. // Six pair-wise comparisons are performed between each possible pair
  449. // of the four coordinates, and the results are used to rank the numbers.
  450. rankx := 0;
  451. ranky := 0;
  452. rankz := 0;
  453. rankw := 0;
  454. if (xx > yy) then
  455. inc(rankx)
  456. else
  457. inc(ranky);
  458. if (xx > zz) then
  459. inc(rankx)
  460. else
  461. inc(rankz);
  462. if (xx > ww) then
  463. inc(rankx)
  464. else
  465. inc(rankw);
  466. if (yy > zz) then
  467. inc(ranky)
  468. else
  469. inc(rankz);
  470. if (yy > ww) then
  471. inc(ranky)
  472. else
  473. inc(rankw);
  474. if (zz > ww) then
  475. inc(rankz)
  476. else
  477. inc(rankw);
  478. // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
  479. // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
  480. // impossible. Only the 24 indices which have non-zero entries make any sense.
  481. // We use a thresholding to set the coordinates in turn from the largest magnitude.
  482. // Rank 3 denotes the largest coordinate.
  483. if (rankx >= 3) then
  484. i1:=1
  485. else
  486. i1:=0;
  487. if (ranky >= 3) then
  488. j1:=1
  489. else
  490. j1:=0;
  491. if (rankz >= 3) then
  492. k1:=1
  493. else
  494. k1:=0;
  495. if (rankw >= 3) then
  496. l1:=1
  497. else
  498. l1:=0;
  499. // Rank 2 denotes the second largest coordinate.
  500. if (rankx >= 2) then
  501. i2:=1
  502. else
  503. i2:=0;
  504. if (ranky >= 2) then
  505. j2:=1
  506. else
  507. j2:=0;
  508. if (rankz >= 2) then
  509. k2:=1
  510. else
  511. k2:=0;
  512. if (rankw >= 2) then
  513. l2:=1
  514. else
  515. l2:=0;
  516. // Rank 1 denotes the second smallest coordinate.
  517. if (rankx >= 1) then
  518. i3:=1
  519. else
  520. i3:=0;
  521. if (ranky >= 1) then
  522. j3:=1
  523. else
  524. j3:=0;
  525. if (rankz >= 1) then
  526. k3:=1
  527. else
  528. k3:=0;
  529. if (rankw >= 1) then
  530. l3:=1
  531. else
  532. l3:=0;
  533. // The fifth corner has all coordinate offsets = 1, so no need to compute that.
  534. x1 := xx - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
  535. y1 := yy - j1 + G4;
  536. z1 := zz - k1 + G4;
  537. w1 := ww - l1 + G4;
  538. x2 := xx - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords
  539. y2 := yy - j2 + 2.0*G4;
  540. z2 := zz - k2 + 2.0*G4;
  541. w2 := ww - l2 + 2.0*G4;
  542. x3 := xx - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords
  543. y3 := yy - j3 + 3.0*G4;
  544. z3 := zz - k3 + 3.0*G4;
  545. w3 := ww - l3 + 3.0*G4;
  546. x4 := xx - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords
  547. y4 := yy - 1.0 + 4.0*G4;
  548. z4 := zz - 1.0 + 4.0*G4;
  549. w4 := ww - 1.0 + 4.0*G4;
  550. // Work out the hashed gradient indices of the five simplex corners
  551. ii := i and 255;
  552. jj := j and 255;
  553. kk := k and 255;
  554. ll := l and 255;
  555. gi0 := FPerm[ii + FPerm[jj + FPerm[kk + FPerm[ll ]]]] mod 32; // TODO : Replace "mod" with bit mask ?
  556. gi1 := FPerm[ii + i1+FPerm[jj + j1 + FPerm[kk + k1+FPerm[ll+l1]]]] mod 32;
  557. gi2 := FPerm[ii + i2+FPerm[jj + j2 + FPerm[kk + k2+FPerm[ll+l2]]]] mod 32;
  558. gi3 := FPerm[ii + i3+FPerm[jj + j3 + FPerm[kk + k3+FPerm[ll+l3]]]] mod 32;
  559. gi4 := FPerm[ii + 1+ FPerm[jj + 1 + FPerm[kk + 1+FPerm[ll+1 ]]]] mod 32;
  560. // Calculate the contribution from the five corners
  561. t0 := 0.6 - (xx * xx) - (yy * yy) - (zz * zz) - (ww * ww);
  562. if (t0 < 0) then
  563. n0 := 0.0
  564. else
  565. begin
  566. t0 := t0 * t0;
  567. n0 := t0 * t0 * Dot(Gradient4D[gi0], xx, yy, zz, ww);
  568. end;
  569. t1 := 0.6 - (x1 * x1) - (y1 * y1) - (z1 * z1) - (w1 * w1);
  570. if (t1 < 0) then
  571. n1 := 0.0
  572. else
  573. begin
  574. t1 := t1 * t1;
  575. n1 := t1 * t1 * Dot(Gradient4D[gi1], x1, y1, z1, w1);
  576. end;
  577. t2 := 0.6 - (x2 * x2) - (y2 * y2) - (z2 * z2) - (w2 * w2);
  578. if (t2 < 0) then
  579. n2 := 0.0
  580. else
  581. begin
  582. t2 := t2 * t2;
  583. n2 := t2 * t2 * Dot(Gradient4D[gi2], x2, y2, z2, w2);
  584. end;
  585. t3 := 0.6 - (x3 * x3) - (y3 * y3) - (z3 * z3) - (w3 * w3);
  586. if (t3 < 0) then
  587. n3 := 0.0
  588. else
  589. begin
  590. t3 := t3 * t3;
  591. n3 := t3 * t3 * Dot(Gradient4D[gi3], x3, y3, z3, w3);
  592. end;
  593. t4 := 0.6 - (x4 * x4) - (y4 * y4) - (z4 * z4) - (w4 * w4);
  594. if (t4 < 0) then
  595. n4 := 0.0
  596. else
  597. begin
  598. t4 := t4 * t4;
  599. n4 := t4 * t4 * Dot(Gradient4D[gi4], x4, y4, z4, w4);
  600. end;
  601. // Sum up and scale the result to cover the range [-1,1]
  602. Result:= 27.0 * (n0 + n1 + n2 + n3 + n4);
  603. end;
  604. //------------------------------------------------------------------------------
  605. end.