├── .gitattributes ├── LICENSE ├── README.md └── simplexNoise.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimplexNoiseJS 2 | 3 | A JavaScript rewrite of typescript [Open-Simplex-Noise](https://github.com/joshforisha/open-simplex-noise-js) an implementation of [OpenSimplex noise](https://en.wikipedia.org/wiki/OpenSimplex_noise) 4 | 5 | The rewrite provides a 15-20% performance improvement on the typescript implementation, file size reduction from 24.28K to 14.66K, and a reduced runtime memory footprint. 6 | 7 | ## Demo 8 | 9 | A demo can be found at codepen [Simplex Noise Example](https://codepen.io/Blindman67/pen/EbKoYx?editors=0010) 10 | 11 | ## Example 12 | 13 | ```javascript 14 | 15 | const seed = Date.now(); 16 | const [width, height] = [888, 222]; 17 | const canvas = document.createElement("canvas"); 18 | const ctx = canvas.getContext("2d"); 19 | const imageData = ctx.createImageData(width, height); 20 | const openSimplex = openSimplexNoise(seed); 21 | const zoom = 8; 22 | var x, y, index = 0; 23 | for (y = 0; y < height; y++) { 24 | for (x = 0; x < width; x++) { 25 | const value = (openSimplex.noise2D(x / zoom, y / zoom) + 1) * 128; 26 | imageData.data[index++] = value; 27 | imageData.data[index++] = value; 28 | imageData.data[index++] = value; 29 | imageData.data[index++] = 255; 30 | } 31 | } 32 | ctx.putImageData(imageData, 0, 0) 33 | ``` 34 | 35 | 36 | ## API 37 | 38 | ### `function openSimplexNoise` 39 | 40 | #### `creation openSimplexNoise(seed) => API` 41 | 42 | #### `API.noise2D (x, y) => -1 < number < 1` 43 | 44 | #### `API.noise3D (x, y, z) => -1 < number < 1` 45 | 46 | #### `API.noise4D (x, y, z, w) => -1 < number < 1` 47 | -------------------------------------------------------------------------------- /simplexNoise.js: -------------------------------------------------------------------------------- 1 | function openSimplexNoise(clientSeed) { 2 | "use strict"; 3 | const SQ5 = 2.23606797749979; 4 | const SQ4 = 2; 5 | const SQ3 = 1.7320508075688772; 6 | const toNums = (s) => s.split(",").map(s => new Uint8Array(s.split("").map(v => Number(v)))); 7 | const decode = (m, r, s) => new Int8Array(s.split("").map(v => parseInt(v, r) + m)); 8 | const toNumsB32 = (s) => s.split(",").map(s => parseInt(s, 32)); 9 | const NORM_2D = 1.0 / 47.0; 10 | const NORM_3D = 1.0 / 103.0; 11 | const NORM_4D = 1.0 / 30.0; 12 | const SQUISH_2D = (SQ3 - 1) / 2; 13 | const SQUISH_3D = (SQ4 - 1) / 3; 14 | const SQUISH_4D = (SQ5 - 1) / 4; 15 | const STRETCH_2D = (1 / SQ3 - 1) / 2; 16 | const STRETCH_3D = (1 / SQ4 - 1) / 3; 17 | const STRETCH_4D = (1 / SQ5 - 1) / 4; 18 | var base2D = toNums("110101000,110101211"); 19 | var base3D = toNums("0000110010101001,2110210120113111,110010101001211021012011"); 20 | var base4D = toNums("0000011000101001001010001,3111031101310113011141111,11000101001001010001211002101021001201102010120011,31110311013101130111211002101021001201102010120011"); 21 | const gradients2D = decode(-5, 11, "a77a073aa3700330"); 22 | const gradients3D = decode(-11, 23, "0ff7mf7fmmfffmfffm07f70f77mm7ff0ff7m0f77m77f0mf7fm7ff0077707770m77f07f70"); 23 | const gradients4D = decode(-3, 7, "6444464444644446044426442464244662444044426442460244204422642246642446244404442604242624240424266224402442044226022420242204222664424642446244400442264224622440624240424262424002422042226222406422462244024420042226222402242062224022420242200222202222022220"); 24 | var lookupPairs2D = () => new Uint8Array([0,1, 1,0, 4,1, 17,0, 20,2, 21,2, 22,5, 23, 5,26, 4,39, 3,42, 4,43, 3]); 25 | var lookupPairs3D = () => new Uint16Array(toNumsB32("0,2,1,1,2,2,5,1,6,0,7,0,10,2,12,2,41,1,45,1,50,5,51,5,g6,0,g7,0,h2,4,h6,4,k5,3,k7,3,l0,5,l1,5,l2,4,l5,3,l6,4,l7,3,l8,d,l9,d,la,c,ld,e,le,c,lf,e,m8,k,ma,i,p9,l,pd,n,q8,k,q9,l,15e,j,15f,m,16a,i,16e,j,19d,n,19f,m,1a8,f,1a9,h,1aa,f,1ad,h,1ae,g,1af,g,1ag,b,1ah,a,1ai,b,1al,a,1am,9,1an,9,1bg,b,1bi,b,1eh,a,1el,a,1fg,8,1fh,8,1qm,9,1qn,9,1ri,7,1rm,7,1ul,6,1un,6,1vg,8,1vh,8,1vi,7,1vl,6,1vm,7,1vn,6")); 26 | var lookupPairs4D = () => new Uint32Array(toNumsB32("0,3,1,2,2,3,5,2,6,1,7,1,8,3,9,2,a,3,d,2,g,3,i,3,m,1,n,1,o,3,q,3,11,2,15,2,16,1,17,1,19,2,1d,2,1m,1,1n,1,1o,0,1p,0,1q,0,1r,0,1s,0,1t,0,1u,0,1v,0,80,3,82,3,88,3,8a,3,8g,3,8i,3,8o,3,8q,3,201,2,205,2,209,2,20d,2,211,2,215,2,219,2,21d,2,280,9,281,9,288,9,289,9,g06,1,g07,1,g0m,1,g0n,1,g16,1,g17,1,g1m,1,g1n,1,g82,8,g86,8,g8i,8,g8m,8,i05,6,i07,6,i15,6,i17,6,i80,9,i81,9,i82,8,i85,6,i86,8,i87,6,i88,9,i89,9,i8i,8,i8m,8,i95,6,i97,6,401o,0,401p,0,401q,0,401r,0,401s,0,401t,0,401u,0,401v,0,408o,7,408q,7,409o,7,409q,7,4219,5,421d,5,421p,5,421t,5,4280,9,4281,9,4288,9,4289,9,428o,7,428q,7,4299,5,429d,5,429o,7,429p,5,429q,7,429t,5,4g1m,4,4g1n,4,4g1u,4,4g1v,4,4g82,8,4g86,8,4g8i,8,4g8m,8,4g8o,7,4g8q,7,4g9m,4,4g9n,4,4g9o,7,4g9q,7,4g9u,4,4g9v,4,4i05,6,4i07,6,4i15,6,4i17,6,4i19,5,4i1d,5,4i1m,4,4i1n,4,4i1p,5,4i1t,5,4i1u,4,4i1v,4,4i80,9,4i81,9,4i82,8,4i85,6,4i86,8,4i87,6,4i88,9,4i89,9,4i8i,8,4i8m,8,4i8o,7,4i8q,7,4i95,6,4i97,6,4i99,5,4i9d,5,4i9m,4,4i9n,4,4i9o,7,4i9p,5,4i9q,7,4i9t,5,4i9u,4,4i9v,4,4ia0,15,4ia1,15,4ia2,14,4ia5,12,4ia6,14,4ia7,12,4ia8,15,4ia9,15,4iai,14,4iam,14,4iao,13,4iaq,13,4ib5,12,4ib7,12,4ib9,11,4ibd,11,4ibm,10,4ibn,10,4ibo,13,4ibp,11,4ibq,13,4ibt,11,4ibu,10,4ibv,10,4ii0,1h,4ii2,1g,4ii8,1h,4iii,1g,4iio,1f,4iiq,1f,4ka1,1e,4ka5,1d,4ka9,1e,4kb5,1d,4kb9,1c,4kbd,1c,4ki0,1h,4ki1,1e,4ki8,1h,4ki9,1e,52a6,1b,52a7,1a,52am,1b,52b7,1a,52bm,19,52bn,19,52i2,1g,52i6,1b,52ii,1g,52im,1b,54a5,1d,54a7,1a,54b5,1d,54b7,1a,54i0,v,54i1,s,54i2,v,54i5,s,54i6,p,54i7,p,8ibo,18,8ibp,17,8ibq,18,8ibt,17,8ibu,16,8ibv,16,8iio,1f,8iiq,1f,8ijo,18,8ijq,18,8kb9,1c,8kbd,1c,8kbp,17,8kbt,17,8ki8,u,8ki9,r,8kio,u,8kj9,r,8kjo,m,8kjp,m,92bm,19,92bn,19,92bu,16,92bv,16,92ii,t,92im,o,92iq,t,92jm,o,92jq,l,92ju,l,94b5,q,94b7,n,94bd,q,94bn,n,94bt,k,94bv,k,94i0,v,94i1,s,94i2,v,94i5,s,94i6,p,94i7,p,94i8,u,94i9,r,94ii,t,94im,o,94io,u,94iq,t,94j5,q,94j7,n,94j9,r,94jd,q,94jm,o,94jn,n,94jo,m,94jp,m,94jq,l,94jt,k,94ju,l,94jv,k,94k0,1t,94k1,1s,94k2,1t,94k5,1s,94k6,1r,94k7,1r,94k8,1q,94k9,1p,94ki,1n,94km,1m,94ko,1q,94kq,1n,94l5,1k,94l7,1j,94l9,1p,94ld,1k,94lm,1m,94ln,1j,94lo,1o,94lp,1o,94lq,1l,94lt,1i,94lu,1l,94lv,1i,94s0,1t,94s2,1t,94s8,1q,94si,1n,94so,1q,94sq,1n,96k1,1s,96k5,1s,96k9,1p,96l5,1k,96l9,1p,96ld,1k,96s0,2f,96s1,2f,96s8,2c,96s9,2c,9kk6,1r,9kk7,1r,9kkm,1m,9kl7,1j,9klm,1m,9kln,1j,9ks2,2e,9ks6,2e,9ksi,29,9ksm,29,9mk5,2d,9mk7,2d,9ml5,26,9ml7,26,9ms0,2f,9ms1,2f,9ms2,2e,9ms5,2d,9ms6,2e,9ms7,2d,d4lo,1o,d4lp,1o,d4lq,1l,d4lt,1i,d4lu,1l,d4lv,1i,d4so,2b,d4sq,28,d4to,2b,d4tq,28,d6l9,2a,d6ld,25,d6lp,2a,d6lt,25,d6s8,2c,d6s9,2c,d6so,2b,d6t9,2a,d6to,2b,d6tp,2a,dklm,27,dkln,24,dklu,27,dklv,24,dksi,29,dksm,29,dksq,28,dktm,27,dktq,28,dktu,27,dml5,26,dml7,26,dmld,25,dmln,24,dmlt,25,dmlv,24,dms0,23,dms1,23,dms2,22,dms5,20,dms6,22,dms7,20,dms8,23,dms9,23,dmsi,22,dmsm,22,dmso,21,dmsq,21,dmt5,20,dmt7,20,dmt9,1v,dmtd,1v,dmtm,1u,dmtn,1u,dmto,21,dmtp,1v,dmtq,21,dmtt,1v,dmtu,1u,dmtv,1u,dmu0,j,dmu1,j,dmu2,i,dmu5,g,dmu6,i,dmu7,g,dmu8,j,dmu9,j,dmui,i,dmum,i,dmuo,h,dmuq,h,dmv5,g,dmv7,g,dmv9,f,dmvd,f,dmvm,e,dmvn,e,dmvo,h,dmvp,f,dmvq,h,dmvt,f,dmvu,e,dmvv,e,dn60,j,dn61,j,dn62,i,dn66,i,dn68,j,dn69,j,dn6i,i,dn6m,i,dn6o,h,dn6q,h,dn7o,h,dn7q,h,dou0,j,dou1,j,dou5,g,dou7,g,dou8,j,dou9,j,dov5,g,dov7,g,dov9,f,dovd,f,dovp,f,dovt,f,dp60,j,dp61,j,dp68,j,dp69,j,e6u2,i,e6u5,g,e6u6,i,e6u7,g,e6ui,i,e6um,i,e6v5,g,e6v7,g,e6vm,e,e6vn,e,e6vu,e,e6vv,e,e762,i,e766,i,e76i,i,e76m,i,e8u5,g,e8u7,g,e8v5,g,e8v7,g,e960,d,e961,d,e962,d,e963,d,e964,d,e965,d,e966,d,e967,d,hmuo,h,hmuq,h,hmv9,f,hmvd,f,hmvm,e,hmvn,e,hmvo,h,hmvp,f,hmvq,h,hmvt,f,hmvu,e,hmvv,e,hn6o,h,hn6q,h,hn7o,h,hn7q,h,hov9,f,hovd,f,hovp,f,hovt,f,hp68,c,hp69,c,hp6o,c,hp6p,c,hp78,c,hp79,c,hp7o,c,hp7p,c,i6vm,e,i6vn,e,i6vu,e,i6vv,e,i76i,b,i76m,b,i76q,b,i76u,b,i77i,b,i77m,b,i77q,b,i77u,b,i8v5,a,i8v7,a,i8vd,a,i8vf,a,i8vl,a,i8vn,a,i8vt,a,i8vv,a,i960,d,i961,d,i962,d,i963,d,i964,d,i965,d,i966,d,i967,d,i968,c,i969,c,i96i,b,i96m,b,i96o,c,i96p,c,i96q,b,i96u,b,i975,a,i977,a,i978,c,i979,c,i97d,a,i97f,a,i97i,b,i97l,a,i97m,b,i97n,a,i97o,c,i97p,c,i97q,b,i97t,a,i97u,b,i97v,a")); 27 | var p2D = decode(-1, 4, "112011021322233123132111"); 28 | var p3D = decode(-1, 5, "112011210110211120110121102132212220132122202131222022243214231243124213241324123222113311221213131221123113311112202311112022311112220342223113342223311342223131322023113322023311320223113320223131322203311322203131"); 29 | var p4D = decode(-1, 6, "11201112101121101102111120111210110121110211112011011211012111021322112220122210132121220212212013122120221212201321122201222102131212202122120213112220122210222532215232152231253212523125221325312252132521232513225123251223232211432114231123212143121421312312214132141231232112431124211323121241312412132311224113241123342221322203311134221232202331113421223202233111342221322203131134221232202313113412223022231311342221322203113134212232022311313412223022231131342212322023111334212232022311133412223022231113322201222101111132202122120111113202212122011111322012221021111132021221202111113201222102211111322201222103311132202122120331113220122210233111322201222103131132022121220313113202122120231311322021221203113132022121220311313201222102231131322012221023111332021221202311133201222102231113422111331113222042121131311322204211213113132220422111331113220242121131311322024211123111332202422111331113202242112131131320224211123111332022421211313113022242112131131302224211123111330222443211423115222244312142131522224413214123152222443112421135222244131241213522224411324112352222443211423113222044312142131322204413214123132220443211423113220244311242113322024413124121332202443121421313202244311242113320224411324112332022441321412313022244131241213302224411324112330222"); 30 | 31 | const setOf = (count, cb = (i)=>i) => { var a = [],i = 0; while (i < count) { a.push(cb(i ++)) } return a }; 32 | const doFor = (count, cb) => { var i = 0; while (i < count && cb(i++) !== true); }; 33 | 34 | function shuffleSeed(seed,count = 1){ 35 | seed = seed * 1664525 + 1013904223 | 0; 36 | count -= 1; 37 | return count > 0 ? shuffleSeed(seed, count) : seed; 38 | } 39 | const types = { 40 | _2D : { 41 | base : base2D, 42 | squish : SQUISH_2D, 43 | dimensions : 2, 44 | pD : p2D, 45 | lookup : lookupPairs2D, 46 | }, 47 | _3D : { 48 | base : base3D, 49 | squish : SQUISH_3D, 50 | dimensions : 3, 51 | pD : p3D, 52 | lookup : lookupPairs3D, 53 | }, 54 | _4D : { 55 | base : base4D, 56 | squish : SQUISH_4D, 57 | dimensions : 4, 58 | pD : p4D, 59 | lookup : lookupPairs4D, 60 | }, 61 | }; 62 | 63 | function createContribution(type, baseSet, index) { 64 | var i = 0; 65 | const multiplier = baseSet[index ++]; 66 | const c = { next : undefined }; 67 | while(i < type.dimensions){ 68 | const axis = ("xyzw")[i]; 69 | c[axis + "sb"] = baseSet[index + i]; 70 | c["d" + axis] = - baseSet[index + i++] - multiplier * type.squish; 71 | } 72 | return c; 73 | } 74 | 75 | function createLookupPairs(lookupArray, contributions){ 76 | var i; 77 | const a = lookupArray(); 78 | const res = new Map(); 79 | for (i = 0; i < a.length; i += 2) { res.set(a[i], contributions[a[i + 1]]) } 80 | return res; 81 | } 82 | 83 | function createContributionArray(type) { 84 | const conts = []; 85 | const d = type.dimensions; 86 | const baseStep = d * d; 87 | var k, i = 0; 88 | while (i < type.pD.length) { 89 | const baseSet = type.base[type.pD[i]]; 90 | let previous, current; 91 | k = 0; 92 | do { 93 | current = createContribution(type, baseSet, k); 94 | if (!previous) { conts[i / baseStep] = current } 95 | else { previous.next = current } 96 | previous = current; 97 | k += d + 1; 98 | } while(k < baseSet.length); 99 | 100 | current.next = createContribution(type, type.pD, i + 1); 101 | if (d >= 3) { current.next.next = createContribution(type, type.pD, i + d + 2) } 102 | if (d === 4) { current.next.next.next = createContribution(type, type.pD, i + 11) } 103 | i += baseStep; 104 | } 105 | const result = [conts, createLookupPairs(type.lookup, conts)]; 106 | type.base = undefined; 107 | type.lookup = undefined; 108 | return result; 109 | } 110 | 111 | const [contributions2D, lookup2D] = createContributionArray(types._2D); 112 | const [contributions3D, lookup3D] = createContributionArray(types._3D); 113 | const [contributions4D, lookup4D] = createContributionArray(types._4D); 114 | const perm = new Uint8Array(256); 115 | const perm2D = new Uint8Array(256); 116 | const perm3D = new Uint8Array(256); 117 | const perm4D = new Uint8Array(256); 118 | const source = new Uint8Array(setOf(256, i => i)); 119 | var seed = shuffleSeed(clientSeed, 3); 120 | doFor(256, i => { 121 | i = 255 - i; 122 | seed = shuffleSeed(seed); 123 | var r = (seed + 31) % (i + 1); 124 | r += r < 0 ? i + 1 : 0; 125 | perm[i] = source[r]; 126 | perm2D[i] = perm[i] & 0x0E; 127 | perm3D[i] = (perm[i] % 24) * 3; 128 | perm4D[i] = perm[i] & 0xFC; 129 | source[r] = source[i]; 130 | }); 131 | base2D = base3D = base4D = undefined; 132 | lookupPairs2D = lookupPairs3D = lookupPairs4D = undefined; 133 | p2D = p3D = p4D = undefined; 134 | 135 | const API = { 136 | noise2D(x, y) { 137 | const pD = perm2D; 138 | const p = perm; 139 | const g = gradients2D; 140 | const stretchOffset = (x + y) * STRETCH_2D; 141 | const xs = x + stretchOffset, ys = y + stretchOffset; 142 | const xsb = Math.floor(xs), ysb = Math.floor(ys); 143 | const squishOffset = (xsb + ysb) * SQUISH_2D; 144 | const dx0 = x - (xsb + squishOffset), dy0 = y - (ysb + squishOffset); 145 | var c = (() => { 146 | const xins = xs - xsb, yins = ys - ysb; 147 | const inSum = xins + yins; 148 | return lookup2D.get( 149 | (xins - yins + 1) | 150 | (inSum << 1) | 151 | ((inSum + yins) << 2) | 152 | ((inSum + xins) << 4) 153 | ); 154 | })(); 155 | var i, value = 0; 156 | while (c !== undefined) { 157 | const dx = dx0 + c.dx; 158 | const dy = dy0 + c.dy; 159 | let attn = 2 - dx * dx - dy * dy; 160 | if (attn > 0) { 161 | i = pD[(p[(xsb + c.xsb) & 0xFF] + (ysb + c.ysb)) & 0xFF]; 162 | attn *= attn; 163 | value += attn * attn * (g[i++] * dx + g[i] * dy); 164 | } 165 | c = c.next; 166 | } 167 | return value * NORM_2D; 168 | }, 169 | noise3D(x, y, z) { 170 | const pD = perm3D; 171 | const p = perm; 172 | const g = gradients3D; 173 | const stretchOffset = (x + y + z) * STRETCH_3D; 174 | const xs = x + stretchOffset, ys = y + stretchOffset, zs = z + stretchOffset; 175 | const xsb = Math.floor(xs), ysb = Math.floor(ys), zsb = Math.floor(zs); 176 | const squishOffset = (xsb + ysb + zsb) * SQUISH_3D; 177 | const dx0 = x - (xsb + squishOffset), dy0 = y - (ysb + squishOffset), dz0 = z - (zsb + squishOffset); 178 | var c = (() => { 179 | const xins = xs - xsb, yins = ys - ysb, zins = zs - zsb; 180 | const inSum = xins + yins + zins; 181 | return lookup3D.get( 182 | (yins - zins + 1) | 183 | ((xins - yins + 1) << 1) | 184 | ((xins - zins + 1) << 2) | 185 | (inSum << 3) | 186 | ((inSum + zins) << 5) | 187 | ((inSum + yins) << 7) | 188 | ((inSum + xins) << 9) 189 | ); 190 | })(); 191 | var i, value = 0; 192 | while (c !== undefined) { 193 | const dx = dx0 + c.dx, dy = dy0 + c.dy, dz = dz0 + c.dz; 194 | let attn = 2 - dx * dx - dy * dy - dz * dz; 195 | if (attn > 0) { 196 | i = pD[(((p[(xsb + c.xsb) & 0xFF] + (ysb + c.ysb)) & 0xFF) + (zsb + c.zsb)) & 0xFF]; 197 | attn *= attn; 198 | value += attn * attn * (g[i++] * dx + g[i++] * dy + g[i] * dz); 199 | } 200 | c = c.next; 201 | } 202 | return value * NORM_3D; 203 | }, 204 | noise4D(x, y, z, w) { 205 | const pD = perm4D; 206 | const p = perm; 207 | const g = gradients4D; 208 | const stretchOffset = (x + y + z + w) * STRETCH_4D; 209 | const xs = x + stretchOffset, ys = y + stretchOffset, zs = z + stretchOffset, ws = w + stretchOffset; 210 | const xsb = Math.floor(xs), ysb = Math.floor(ys), zsb = Math.floor(zs), wsb = Math.floor(ws); 211 | const squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_4D; 212 | const dx0 = x - (xsb + squishOffset), dy0 = y - (ysb + squishOffset), dz0 = z - (zsb + squishOffset), dw0 = w - (wsb + squishOffset); 213 | var c = (() => { 214 | const xins = xs - xsb, yins = ys - ysb, zins = zs - zsb, wins = ws - wsb; 215 | const inSum = xins + yins + zins + wins; 216 | return lookup4D.get( 217 | (zins - wins + 1) | 218 | ((yins - zins + 1) << 1) | 219 | ((yins - wins + 1) << 2) | 220 | ((xins - yins + 1) << 3) | 221 | ((xins - zins + 1) << 4) | 222 | ((xins - wins + 1) << 5) | 223 | (inSum << 6) | 224 | ((inSum + wins) << 8) | 225 | ((inSum + zins) << 11) | 226 | ((inSum + yins) << 14) | 227 | ((inSum + xins) << 17) 228 | ); 229 | })(); 230 | var i, value = 0; 231 | while (c !== undefined) { 232 | const dx = dx0 + c.dx, dy = dy0 + c.dy, dz = dz0 + c.dz, dw = dw0 + c.dw; 233 | let attn = 2 - dx * dx - dy * dy - dz * dz - dw * dw; 234 | if (attn > 0) { 235 | i = pD[(((((p[(xsb + c.xsb) & 0xFF] + (ysb + c.ysb)) & 0xFF) + (zsb + c.zsb)) & 0xFF) + (wsb + c.wsb)) & 0xFF]; 236 | attn *= attn; 237 | value += attn * attn * (g[i++] * dx + g[i++] * dy + g[i++] * dz + g[i] * dw); 238 | } 239 | c = c.next; 240 | } 241 | return value * NORM_4D; 242 | }, 243 | } 244 | return API; 245 | } 246 | --------------------------------------------------------------------------------