| [9096] | 1 | // Utility function used in both noises as an ease curve
|
|---|
| [18840] | 2 | function easeCurve(t)
|
|---|
| [9096] | 3 | {
|
|---|
| 4 | return t*t*t*(t*(t*6-15)+10);
|
|---|
| 5 | }
|
|---|
| 6 |
|
|---|
| 7 | // Find mod of number but only positive values
|
|---|
| 8 | function modPos(num, m)
|
|---|
| 9 | {
|
|---|
| [28036] | 10 | let p = num % m;
|
|---|
| [9096] | 11 | if (p < 0)
|
|---|
| 12 | p += m;
|
|---|
| [18840] | 13 |
|
|---|
| [9096] | 14 | return p;
|
|---|
| 15 | }
|
|---|
| 16 |
|
|---|
| 17 | /////////////////////////////////////////////////////////////////////
|
|---|
| 18 | // Noise2D
|
|---|
| [9271] | 19 | //
|
|---|
| 20 | // Class representing 2D noise with a given base frequency
|
|---|
| 21 | //
|
|---|
| [9096] | 22 | /////////////////////////////////////////////////////////////////////
|
|---|
| 23 |
|
|---|
| 24 | function Noise2D(freq)
|
|---|
| 25 | {
|
|---|
| [9099] | 26 | freq = Math.floor(freq);
|
|---|
| [9096] | 27 | this.freq = freq;
|
|---|
| [20153] | 28 | this.grads = [];
|
|---|
| [18840] | 29 |
|
|---|
| [28036] | 30 | for (let i=0; i < freq; ++i)
|
|---|
| [9096] | 31 | {
|
|---|
| [20153] | 32 | this.grads[i] = [];
|
|---|
| [28036] | 33 | for (let j=0; j < freq; ++j)
|
|---|
| [9096] | 34 | {
|
|---|
| [28036] | 35 | let a = randomAngle();
|
|---|
| [9271] | 36 | this.grads[i][j] = new Vector2D(Math.cos(a), Math.sin(a));
|
|---|
| [9096] | 37 | }
|
|---|
| 38 | }
|
|---|
| 39 | }
|
|---|
| 40 |
|
|---|
| 41 | Noise2D.prototype.get = function(x, y)
|
|---|
| 42 | {
|
|---|
| 43 | x *= this.freq;
|
|---|
| 44 | y *= this.freq;
|
|---|
| [18840] | 45 |
|
|---|
| [28036] | 46 | let ix = modPos(Math.floor(x), this.freq);
|
|---|
| 47 | let iy = modPos(Math.floor(y), this.freq);
|
|---|
| [18840] | 48 |
|
|---|
| [28036] | 49 | let fx = x - ix;
|
|---|
| 50 | let fy = y - iy;
|
|---|
| [18840] | 51 |
|
|---|
| [28036] | 52 | let ix1 = (ix+1) % this.freq;
|
|---|
| 53 | let iy1 = (iy+1) % this.freq;
|
|---|
| [18840] | 54 |
|
|---|
| [28036] | 55 | let s = this.grads[ix][iy].dot(new Vector2D(fx, fy));
|
|---|
| 56 | let t = this.grads[ix1][iy].dot(new Vector2D(fx-1, fy));
|
|---|
| 57 | let u = this.grads[ix][iy1].dot(new Vector2D(fx, fy-1));
|
|---|
| 58 | let v = this.grads[ix1][iy1].dot(new Vector2D(fx-1, fy-1));
|
|---|
| [18840] | 59 |
|
|---|
| [28036] | 60 | let ex = easeCurve(fx);
|
|---|
| 61 | let ey = easeCurve(fy);
|
|---|
| 62 | let a = s + ex*(t-s);
|
|---|
| 63 | let b = u + ex*(v-u);
|
|---|
| [9096] | 64 | return (a + ey*(b-a)) * 0.5 + 0.5;
|
|---|
| 65 | };
|
|---|
| 66 |
|
|---|
| 67 | /////////////////////////////////////////////////////////////////////
|
|---|
| 68 | // Noise3D
|
|---|
| [9271] | 69 | //
|
|---|
| 70 | // Class representing 3D noise with given base frequencies
|
|---|
| 71 | //
|
|---|
| [9096] | 72 | /////////////////////////////////////////////////////////////////////
|
|---|
| 73 |
|
|---|
| 74 | function Noise3D(freq, vfreq)
|
|---|
| 75 | {
|
|---|
| [9099] | 76 | freq = Math.floor(freq);
|
|---|
| 77 | vfreq = Math.floor(vfreq);
|
|---|
| [9096] | 78 | this.freq = freq;
|
|---|
| 79 | this.vfreq = vfreq;
|
|---|
| [20153] | 80 | this.grads = [];
|
|---|
| [18840] | 81 |
|
|---|
| [28036] | 82 | for (let i=0; i < freq; ++i)
|
|---|
| [9096] | 83 | {
|
|---|
| [20153] | 84 | this.grads[i] = [];
|
|---|
| [28036] | 85 | for (let j=0; j < freq; ++j)
|
|---|
| [9096] | 86 | {
|
|---|
| [20153] | 87 | this.grads[i][j] = [];
|
|---|
| [28036] | 88 | for(let k=0; k < vfreq; ++k)
|
|---|
| [9096] | 89 | {
|
|---|
| [28036] | 90 | let v = new Vector3D();
|
|---|
| [9096] | 91 | do
|
|---|
| 92 | {
|
|---|
| [19464] | 93 | v.set(randFloat(-1, 1), randFloat(-1, 1), randFloat(-1, 1));
|
|---|
| [9096] | 94 | }
|
|---|
| 95 | while(v.lengthSquared() > 1 || v.lengthSquared() < 0.1);
|
|---|
| [18840] | 96 |
|
|---|
| [9096] | 97 | v.normalize();
|
|---|
| [18840] | 98 |
|
|---|
| [9096] | 99 | this.grads[i][j][k] = v;
|
|---|
| 100 | }
|
|---|
| 101 | }
|
|---|
| 102 | }
|
|---|
| 103 | }
|
|---|
| 104 |
|
|---|
| 105 | Noise3D.prototype.get = function(x, y, z)
|
|---|
| 106 | {
|
|---|
| 107 | x *= this.freq;
|
|---|
| 108 | y *= this.freq;
|
|---|
| 109 | z *= this.vfreq;
|
|---|
| [18840] | 110 |
|
|---|
| [28036] | 111 | let ix =modPos(Math.floor(x), this.freq);
|
|---|
| 112 | let iy = modPos(Math.floor(y), this.freq);
|
|---|
| 113 | let iz = modPos(Math.floor(z), this.vfreq);
|
|---|
| [18840] | 114 |
|
|---|
| [28036] | 115 | let fx = x - ix;
|
|---|
| 116 | let fy = y - iy;
|
|---|
| 117 | let fz = z - iz;
|
|---|
| [18840] | 118 |
|
|---|
| [28036] | 119 | let ix1 = (ix+1) % this.freq;
|
|---|
| 120 | let iy1 = (iy+1) % this.freq;
|
|---|
| 121 | let iz1 = (iz+1) % this.vfreq;
|
|---|
| [18840] | 122 |
|
|---|
| [28036] | 123 | let s0 = this.grads[ix][iy][iz].dot(new Vector3D(fx, fy, fz));
|
|---|
| 124 | let t0 = this.grads[ix1][iy][iz].dot(new Vector3D(fx-1, fy, fz));
|
|---|
| 125 | let u0 = this.grads[ix][iy1][iz].dot(new Vector3D(fx, fy-1, fz));
|
|---|
| 126 | let v0 = this.grads[ix1][iy1][iz].dot(new Vector3D(fx-1, fy-1, fz));
|
|---|
| [18840] | 127 |
|
|---|
| [28036] | 128 | let s1 = this.grads[ix][iy][iz1].dot(new Vector3D(fx, fy, fz-1));
|
|---|
| 129 | let t1 = this.grads[ix1][iy][iz1].dot(new Vector3D(fx-1, fy, fz-1));
|
|---|
| 130 | let u1 = this.grads[ix][iy1][iz1].dot(new Vector3D(fx, fy-1, fz-1));
|
|---|
| 131 | let v1 = this.grads[ix1][iy1][iz1].dot(new Vector3D(fx-1, fy-1, fz-1));
|
|---|
| [18840] | 132 |
|
|---|
| [28036] | 133 | let ex = easeCurve(fx);
|
|---|
| 134 | let ey = easeCurve(fy);
|
|---|
| 135 | let ez = easeCurve(fz);
|
|---|
| [18840] | 136 |
|
|---|
| [28036] | 137 | let a0 = s0 + ex*(t0-s0);
|
|---|
| 138 | let b0 = u0 + ex*(v0-u0);
|
|---|
| 139 | let c0 = a0 + ey*(b0-a0);
|
|---|
| [18840] | 140 |
|
|---|
| [28036] | 141 | let a1 = s1 + ex*(t1-s1);
|
|---|
| 142 | let b1 = u1 + ex*(v1-u1);
|
|---|
| 143 | let c1 = a1 + ey*(b1-a1);
|
|---|
| [18840] | 144 |
|
|---|
| [9096] | 145 | return (c0 + ez*(c1-c0)) * 0.5 + 0.5;
|
|---|
| 146 | };
|
|---|