fractal-noise
Advanced tools
Comparing version 0.5.0 to 0.6.0
@@ -5,2 +5,9 @@ # Change Log | ||
## [v0.6] – 2017-02-15 | ||
### Changed | ||
- Convert to fractal wrapper library. | ||
### Removed | ||
- Remove noise generation functions. | ||
## [v0.5] – 2017-02-14 | ||
@@ -33,3 +40,4 @@ ### Changed | ||
[Unreleased]: https://github.com/joshforisha/fractal-noise-js/compare/v0.5...HEAD | ||
[Unreleased]: https://github.com/joshforisha/fractal-noise-js/compare/v0.6...HEAD | ||
[v0.6]: https://github.com/joshforisha/fractal-noise-js/compare/v0.5...v0.6 | ||
[v0.5]: https://github.com/joshforisha/fractal-noise-js/compare/v0.4...v0.5 | ||
@@ -36,0 +44,0 @@ [v0.4]: https://github.com/joshforisha/fractal-noise-js/compare/v0.3...v0.4 |
@@ -1,2 +0,6 @@ | ||
export interface Options { | ||
export declare type Noise1Fn = (x: number) => number; | ||
export declare type Noise2Fn = (x: number, y: number) => number; | ||
export declare type Noise3Fn = (x: number, y: number, z: number) => number; | ||
export declare type Noise4Fn = (x: number, y: number, z: number, w: number) => number; | ||
export declare type Options = { | ||
amplitude?: number; | ||
@@ -6,7 +10,7 @@ frequency?: number; | ||
persistence?: number; | ||
} | ||
export declare function generateCuboid(width: number, height: number, depth: number, options?: Options): Uint8Array[][]; | ||
export declare function generateCylinder(circumference: number, height: number, options?: Options): Uint8Array[]; | ||
export declare function generateLine(length: number, options?: Options): number[]; | ||
export declare function generateRectangle(width: number, height: number, options?: Options): Uint8Array[]; | ||
export declare function generateSphere(circumference: number, options?: Options): Uint8Array[]; | ||
}; | ||
export declare function cuboid(width: number, height: number, depth: number, noise3: Noise3Fn, options?: Options): number[][]; | ||
export declare function cylinderSurface(circumference: number, height: number, noise3: Noise3Fn, options?: Options): number[]; | ||
export declare function line(length: number, noise1: Noise1Fn, options?: Options): number[]; | ||
export declare function rectangle(width: number, height: number, noise2: Noise2Fn, options?: Options): number[]; | ||
export declare function sphereSurface(circumference: number, noise3: Noise3Fn, options?: Options): number[]; |
205
lib/index.js
"use strict"; | ||
var TWO_PI = 2 * Math.PI; | ||
function cerp(p0, p1, p2, p3, x) { | ||
return ((-0.5 * p0 + 1.5 * p1 - 1.5 * p2 + 0.5 * p3) * Math.pow(x, 3) + | ||
(p0 - 2.5 * p1 + 2 * p2 - 0.5 * p3) * Math.pow(x, 2) + | ||
(-0.5 * p0 + 0.5 * p2) * x + | ||
p1); | ||
} | ||
function generate1DNoiseFn(source) { | ||
var sx = source.length; | ||
return function (ox) { | ||
var x = ox % sx + sx; | ||
var _x = Math.floor(x); | ||
var xi = x - _x; | ||
var x0 = ((_x - 1) + sx) % sx; | ||
var x1 = _x % sx; | ||
var x2 = (_x + 1) % sx; | ||
var x3 = (_x + 2) % sx; | ||
return cerp(source[x0], source[x1], source[x2], source[x3], xi); | ||
}; | ||
} | ||
function generate2DNoiseFn(source) { | ||
var _a = [source.length, source[0].length], sx = _a[0], sy = _a[1]; | ||
return function (ox, oy) { | ||
var _a = [ox % sx + sx, oy % sy + sy], x = _a[0], y = _a[1]; | ||
var _b = [Math.floor(x), Math.floor(y)], _x = _b[0], _y = _b[1]; | ||
var _c = [x - _x, y - _y], xi = _c[0], yi = _c[1]; | ||
var _d = [((_x - 1) + sx) % sx, ((_y - 1) + sy) % sy], x0 = _d[0], y0 = _d[1]; | ||
var _e = [_x % sx, _y % sy], x1 = _e[0], y1 = _e[1]; | ||
var _f = [(_x + 1) % sx, (_y + 1) % sy], x2 = _f[0], y2 = _f[1]; | ||
var _g = [(_x + 2) % sx, (_y + 2) % sy], x3 = _g[0], y3 = _g[1]; | ||
return cerp(cerp(source[x0][y0], source[x1][y0], source[x2][y0], source[x3][y0], xi), cerp(source[x0][y1], source[x1][y1], source[x2][y1], source[x3][y1], xi), cerp(source[x0][y2], source[x1][y2], source[x2][y2], source[x3][y2], xi), cerp(source[x0][y3], source[x1][y3], source[x2][y3], source[x3][y3], xi), yi); | ||
}; | ||
} | ||
function generate3DNoiseFn(source) { | ||
var _a = [source.length, source[0].length, source[0][0].length], sx = _a[0], sy = _a[1], sz = _a[2]; | ||
return function (ox, oy, oz) { | ||
var _a = [ox % sx + sx, oy % sy + sy, oz % sz + sz], x = _a[0], y = _a[1], z = _a[2]; | ||
var _b = [Math.floor(x), Math.floor(y), Math.floor(z)], _x = _b[0], _y = _b[1], _z = _b[2]; | ||
var _c = [x - _x, y - _y, z - _z], xi = _c[0], yi = _c[1], zi = _c[2]; | ||
var _d = [((_x - 1) + sx) % sx, ((_y - 1) + sy) % sy, ((_z - 1) + sz) % sz], x0 = _d[0], y0 = _d[1], z0 = _d[2]; | ||
var _e = [_x % sx, _y % sy, _z % sz], x1 = _e[0], y1 = _e[1], z1 = _e[2]; | ||
var _f = [(_x + 1) % sx, (_y + 1) % sy, (_z + 1) % sz], x2 = _f[0], y2 = _f[1], z2 = _f[2]; | ||
var _g = [(_x + 2) % sx, (_y + 2) % sy, (_z + 2) % sz], x3 = _g[0], y3 = _g[1], z3 = _g[2]; | ||
return cerp(cerp(cerp(source[x0][y0][z0], source[x1][y0][z0], source[x2][y0][z0], source[x3][y0][z0], xi), cerp(source[x0][y1][z0], source[x1][y1][z0], source[x2][y1][z0], source[x3][y1][z0], xi), cerp(source[x0][y2][z0], source[x1][y2][z0], source[x2][y2][z0], source[x3][y2][z0], xi), cerp(source[x0][y3][z0], source[x1][y3][z0], source[x2][y3][z0], source[x3][y3][z0], xi), yi), cerp(cerp(source[x0][y0][z1], source[x1][y0][z1], source[x2][y0][z1], source[x3][y0][z1], xi), cerp(source[x0][y1][z1], source[x1][y1][z1], source[x2][y1][z1], source[x3][y1][z1], xi), cerp(source[x0][y2][z1], source[x1][y2][z1], source[x2][y2][z1], source[x3][y2][z1], xi), cerp(source[x0][y3][z1], source[x1][y3][z1], source[x2][y3][z1], source[x3][y3][z1], xi), yi), cerp(cerp(source[x0][y0][z2], source[x1][y0][z2], source[x2][y0][z2], source[x3][y0][z2], xi), cerp(source[x0][y1][z2], source[x1][y1][z2], source[x2][y1][z2], source[x3][y1][z2], xi), cerp(source[x0][y2][z2], source[x1][y2][z2], source[x2][y2][z2], source[x3][y2][z2], xi), cerp(source[x0][y3][z2], source[x1][y3][z2], source[x2][y3][z2], source[x3][y3][z2], xi), yi), cerp(cerp(source[x0][y0][z3], source[x1][y0][z3], source[x2][y0][z3], source[x3][y0][z3], xi), cerp(source[x0][y1][z3], source[x1][y1][z3], source[x2][y1][z3], source[x3][y1][z3], xi), cerp(source[x0][y2][z3], source[x1][y2][z3], source[x2][y2][z3], source[x3][y2][z3], xi), cerp(source[x0][y3][z3], source[x1][y3][z3], source[x2][y3][z3], source[x3][y3][z3], xi), yi), zi); | ||
}; | ||
} | ||
function generateArray(count, fn) { | ||
var items = []; | ||
for (var i = 0; i < count; i++) | ||
items.push(fn(i)); | ||
return items; | ||
} | ||
function generateCuboid(width, height, depth, options) { | ||
function cuboid(width, height, depth, noise3, options) { | ||
if (options === void 0) { options = {}; } | ||
var _a = processOptions(options), amplitude = _a.amplitude, frequency = _a.frequency, octaves = _a.octaves, persistence = _a.persistence; | ||
var white = generateArray(width, function () { return generateArray(height, function () { | ||
return window.crypto.getRandomValues(new Uint8Array(depth)); | ||
}); }); | ||
var noise = generate3DNoiseFn(white); | ||
return generateArray(width, function (x) { return generateArray(height, function (y) { return generateArray(depth, function (z) { | ||
return generateArray(octaves, function (octave) { | ||
var freq = frequency * Math.pow(2, octave); | ||
return noise(x * freq, y * freq, z * freq) * (amplitude * Math.pow(persistence, octave)); | ||
}).reduce(function (total, num) { return total + num; }, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))); | ||
}); }); }); | ||
var field = new Array(width); | ||
for (var x = 0; x < width; x++) { | ||
field[x] = new Array(height); | ||
for (var y = 0; y < height; y++) { | ||
field[x][y] = new Array(depth); | ||
for (var z = 0; z < depth; z++) { | ||
var value = 0.0; | ||
for (var octave = 0; octave < octaves; octave++) { | ||
var freq = frequency * Math.pow(2, octave); | ||
value += noise3(x * freq, y * freq, z * freq) * (amplitude * Math.pow(persistence, octave)); | ||
} | ||
field[x][y][z] = value / (2 - (1 / Math.pow(2, octaves - 1))); | ||
} | ||
} | ||
} | ||
return field; | ||
} | ||
exports.generateCuboid = generateCuboid; | ||
function generateCylinder(circumference, height, options) { | ||
exports.cuboid = cuboid; | ||
function cylinderSurface(circumference, height, noise3, options) { | ||
if (options === void 0) { options = {}; } | ||
var _a = processOptions(options), amplitude = _a.amplitude, frequency = _a.frequency, octaves = _a.octaves, persistence = _a.persistence; | ||
var diameter = Math.ceil(circumference / Math.PI); | ||
var white = generateArray(diameter, function () { return generateArray(height, function () { | ||
return window.crypto.getRandomValues(new Uint8Array(diameter)); | ||
}); }); | ||
var noise = generate3DNoiseFn(white); | ||
var radius = circumference / TWO_PI; | ||
return generateArray(circumference, function (x) { return generateArray(height, function (y) { | ||
return generateArray(octaves, function (octave) { | ||
var freq = frequency * Math.pow(2, octave); | ||
var nx = x / circumference; | ||
var rdx = nx * TWO_PI; | ||
var _a = [radius * Math.sin(rdx), radius * Math.cos(rdx)], a = _a[0], b = _a[1]; | ||
return noise(a * freq, b * freq, y * freq) * (amplitude * Math.pow(persistence, octave)); | ||
}).reduce(function (total, num) { return total + num; }, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))); | ||
}); }); | ||
var field = new Array(circumference); | ||
for (var x = 0; x < circumference; x++) { | ||
field[x] = new Array(height); | ||
for (var y = 0; y < height; y++) { | ||
var value = 0.0; | ||
for (var octave = 0; octave < octaves; octave++) { | ||
var freq = frequency * Math.pow(2, octave); | ||
var nx = x / circumference; | ||
var rdx = nx * TWO_PI; | ||
var _b = [radius * Math.sin(rdx), radius * Math.cos(rdx)], a = _b[0], b = _b[1]; | ||
value += noise3(a * freq, b * freq, y * freq) * (amplitude * Math.pow(persistence, octave)); | ||
} | ||
field[x][y] = value / (2 - (1 / Math.pow(2, octaves - 1))); | ||
} | ||
} | ||
return field; | ||
} | ||
exports.generateCylinder = generateCylinder; | ||
function generateLine(length, options) { | ||
exports.cylinderSurface = cylinderSurface; | ||
function line(length, noise1, options) { | ||
if (options === void 0) { options = {}; } | ||
var _a = processOptions(options), amplitude = _a.amplitude, frequency = _a.frequency, octaves = _a.octaves, persistence = _a.persistence; | ||
var white = window.crypto.getRandomValues(new Uint8Array(length)); | ||
var noise = generate1DNoiseFn(white); | ||
return generateArray(length, function (x) { | ||
return generateArray(octaves, function (octave) { | ||
var field = new Array(length); | ||
for (var x = 0; x < length; x++) { | ||
var value = 0.0; | ||
for (var octave = 0; octave < octaves; octave++) { | ||
var freq = frequency * Math.pow(2, octaves); | ||
return noise(x * freq) * (amplitude * Math.pow(persistence, octave)); | ||
}).reduce(function (total, num) { return total + num; }, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))); | ||
}); | ||
value += noise1(x * freq) * (amplitude * Math.pow(persistence, octave)); | ||
} | ||
field[x] = value / (2 - (1 / Math.pow(2, octaves - 1))); | ||
} | ||
return field; | ||
} | ||
exports.generateLine = generateLine; | ||
function generateRectangle(width, height, options) { | ||
exports.line = line; | ||
function rectangle(width, height, noise2, options) { | ||
if (options === void 0) { options = {}; } | ||
var _a = processOptions(options), amplitude = _a.amplitude, frequency = _a.frequency, octaves = _a.octaves, persistence = _a.persistence; | ||
var white = generateArray(width, function () { return window.crypto.getRandomValues(new Uint8Array(height)); }); | ||
var noise = generate2DNoiseFn(white); | ||
return generateArray(width, function (x) { return generateArray(height, function (y) { | ||
return generateArray(octaves, function (octave) { | ||
var freq = frequency * Math.pow(2, octave); | ||
return noise(x * freq, y * freq) * (amplitude * Math.pow(persistence, octave)); | ||
}).reduce(function (total, num) { return total + num; }, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))); | ||
}); }); | ||
var field = new Array(width); | ||
for (var x = 0; x < width; x++) { | ||
field[x] = new Array(height); | ||
for (var y = 0; y < height; y++) { | ||
var value = 0.0; | ||
for (var octave = 0; octave < octaves; octave++) { | ||
var freq = frequency * Math.pow(2, octave); | ||
value += noise2(x * freq, y * freq) * (amplitude * Math.pow(persistence, octave)); | ||
} | ||
field[x][y] = value / (2 - (1 / Math.pow(2, octaves - 1))); | ||
} | ||
} | ||
return field; | ||
} | ||
exports.generateRectangle = generateRectangle; | ||
function generateSphere(circumference, options) { | ||
exports.rectangle = rectangle; | ||
function sphereSurface(circumference, noise3, options) { | ||
if (options === void 0) { options = {}; } | ||
var _a = processOptions(options), amplitude = _a.amplitude, frequency = _a.frequency, octaves = _a.octaves, persistence = _a.persistence; | ||
var diameter = Math.ceil(circumference / Math.PI); | ||
var white = generateArray(diameter, function () { return generateArray(diameter, function () { | ||
return window.crypto.getRandomValues(new Uint8Array(diameter)); | ||
}); }); | ||
var noise = generate3DNoiseFn(white); | ||
var radius = circumference / TWO_PI; | ||
return generateArray(circumference, function (x) { return generateArray(circumference, function (y) { | ||
return generateArray(octaves, function (octave) { | ||
var freq = frequency * Math.pow(2, octave); | ||
var _a = [x / circumference, y / circumference], nx = _a[0], ny = _a[1]; | ||
var _b = [nx * TWO_PI, ny * TWO_PI], rdx = _b[0], rdy = _b[1]; | ||
var sinY = Math.sin(rdy + Math.PI); | ||
var sinRds = 2 * Math.PI; | ||
var a = sinRds * Math.sin(rdx) * sinY; | ||
var b = sinRds * Math.cos(rdx) * sinY; | ||
var d = sinRds * Math.cos(rdy); | ||
return noise(a * freq, b * freq, d * freq) * (amplitude * Math.pow(persistence, octave)); | ||
}).reduce(function (total, num) { return total + num; }, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))); | ||
}); }); | ||
var field = new Array(circumference); | ||
for (var x = 0; x < circumference; x++) { | ||
field[x] = new Array(circumference); | ||
for (var y = 0; y < circumference; y++) { | ||
var value = 0.0; | ||
for (var octave = 0; octave < octaves; octave++) { | ||
var freq = frequency * Math.pow(2, octave); | ||
var _b = [x / circumference, y / circumference], nx = _b[0], ny = _b[1]; | ||
var _c = [nx * TWO_PI, ny * TWO_PI], rdx = _c[0], rdy = _c[1]; | ||
var sinY = Math.sin(rdy + Math.PI); | ||
var sinRds = 2 * Math.PI; | ||
var a = sinRds * Math.sin(rdx) * sinY; | ||
var b = sinRds * Math.cos(rdx) * sinY; | ||
var d = sinRds * Math.cos(rdy); | ||
value += noise3(a * freq, b * freq, d * freq) * (amplitude * Math.pow(persistence, octave)); | ||
} | ||
field[x][y] = value / (2 - (1 / Math.pow(2, octaves - 1))); | ||
} | ||
} | ||
return field; | ||
} | ||
exports.generateSphere = generateSphere; | ||
exports.sphereSurface = sphereSurface; | ||
function processOptions(options) { | ||
@@ -145,0 +108,0 @@ return { |
{ | ||
"name": "fractal-noise", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Fractal noise library", | ||
@@ -5,0 +5,0 @@ "main": "lib/index", |
@@ -6,3 +6,3 @@ # Fractal Noise | ||
Fractal noise library | ||
Fractal noise functions designed to be used with any noise generation algorithm. | ||
@@ -15,4 +15,6 @@ ## Install | ||
These images were all generated using basic value noise with `width: 888` and `height: 111`. | ||
```javascript | ||
generateCylinder(width, height, { frequency: 0.04, octaves: 2 }) | ||
cylinderSurface(width, height, valueNoise3D, { frequency: 0.04, octaves: 2 }) | ||
``` | ||
@@ -22,3 +24,3 @@ ![Low frequency, double octave cylinder](https://github.com/joshforisha/fractal-noise-js/blob/master/images/cylinder-low-2.png) | ||
```javascript | ||
generateCylinder(width, height, { frequency: 0.06, octaves: 8 }) | ||
cylinderSurface(width, height, valueNoise3D, { frequency: 0.06, octaves: 8 }) | ||
``` | ||
@@ -28,3 +30,3 @@ ![Medium frequency, high octave cylinder](https://github.com/joshforisha/fractal-noise-js/blob/master/images/cylinder-medium-8.png) | ||
```javascript | ||
generateLine(width) // (Replicated across y-axis) | ||
line(width, valueNoise1D) // (Replicated across y-axis) | ||
``` | ||
@@ -34,3 +36,3 @@ ![Default line](https://github.com/joshforisha/fractal-noise-js/blob/master/images/line-default.png) | ||
```javascript | ||
generateLine(height, { frequency: 0.1 }) // (Replicated across x-axis) | ||
line(height, valueNoise1D, { frequency: 0.1 }) // (Replicated across x-axis) | ||
``` | ||
@@ -40,3 +42,3 @@ ![High frequency line](https://github.com/joshforisha/fractal-noise-js/blob/master/images/line-high.png) | ||
```javascript | ||
generateRectangle(width, height) | ||
rectangle(width, height, valueNoise2D) | ||
``` | ||
@@ -46,3 +48,3 @@ ![Default rectangle](https://github.com/joshforisha/fractal-noise-js/blob/master/images/rectangle-default.png) | ||
```javascript | ||
generateRectangle(width, height, { frequency: 0.04, octaves: 8 }) | ||
rectangle(width, height, valueNoise2D, { frequency: 0.04, octaves: 8 }) | ||
``` | ||
@@ -53,4 +55,3 @@ ![Low frequency, high octave rectangle](https://github.com/joshforisha/fractal-noise-js/blob/master/images/rectangle-low-8.png) | ||
##### Options | ||
The `options` object for each `generate` function contains the following properties: | ||
##### `type Options = { amplitude?, frequency?, octaves?, persistence? }` | ||
* `amplitude?: number` – Defaults to `1.0` | ||
@@ -61,15 +62,44 @@ * `frequency?: number` – Defaults to `1.0` | ||
##### `generateCuboid (width: number, height: number, depth: number, options: Options = {}): Uint8Array[][]` | ||
##### `makeCuboid (width, height, depth, noise3, options?): number[][]` | ||
* `width: number` | ||
* `height: number` | ||
* `depth: number` | ||
* `noise3: (x: number, y: number, z: number) => number` | ||
* `options?: Options = {}` | ||
Generates a three-dimensional noise field for a rectangular cuboid. | ||
##### `generateCylinder (circumference: number, height: number, options: Options = {}): Uint8Array[]` | ||
##### `makeCylinderSurface(circumference, height, noise3, options?): number[][]` | ||
* `circumference: number` | ||
* `height: number` | ||
* `noise3: (x: number, y: number, z: number) => number` | ||
* `options?: Options = {}` | ||
Generates a two-dimensional noise field formed around a three-dimensional cylinder, such that it is continuous across the x-boundaries. | ||
##### `generateLine (length: number, options: Options = {}): number[]` | ||
##### `makeLine (length, noise1, options?): number[]` | ||
* `length: number` | ||
* `noise1: (x: number) => number` | ||
* `options?: Options = {}` | ||
Generates a one-dimensional noise field. | ||
##### `generateRectangle (width: number, height: number, options: Options = {}): Uint8Array[]` | ||
##### `makeRectangle (width, height, noise2, options?): number[][]` | ||
* `width: number` | ||
* `height: number` | ||
* `noise2: (x: number, y: number) => number` | ||
* `options?: Options = {}` | ||
Generates a two-dimensional noise field isolated to `width` and `height` (non-continuous noise). | ||
##### `generateSphere (circumference: number, options: Options = {}): Uint8Array[]` | ||
##### `makeSphereSurface (circumference, options?): number[][]` | ||
* `circumference: number` | ||
* `noise3: (x: number, y: number, z: number) => number` | ||
* `options?: Options = {}` | ||
Generates a two-dimensional noise field formed on the surface of a three-dimensional sphere. |
263
src/index.ts
const TWO_PI = 2 * Math.PI | ||
export interface Options { | ||
amplitude?: number | ||
frequency?: number | ||
octaves?: number | ||
persistence?: number | ||
} | ||
export type Noise1Fn = (x: number) => number | ||
function cerp (p0: number, p1: number, p2: number, p3: number, x: number): number { | ||
return ( | ||
(-0.5 * p0 + 1.5 * p1 - 1.5 * p2 + 0.5 * p3) * Math.pow(x, 3) + | ||
(p0 - 2.5 * p1 + 2 * p2 - 0.5 * p3) * Math.pow(x, 2) + | ||
(-0.5 * p0 + 0.5 * p2) * x + | ||
p1 | ||
) | ||
} | ||
export type Noise2Fn = (x: number, y: number) => number | ||
function generate1DNoiseFn (source: Uint8Array): (ox: number) => number { | ||
const sx = source.length | ||
return ox => { | ||
const x = ox % sx + sx | ||
const _x = Math.floor(x) | ||
const xi = x - _x | ||
const x0 = ((_x - 1) + sx) % sx | ||
const x1 = _x % sx | ||
const x2 = (_x + 1) % sx | ||
const x3 = (_x + 2) % sx | ||
return cerp(source[x0], source[x1], source[x2], source[x3], xi) | ||
} | ||
} | ||
export type Noise3Fn = (x: number, y: number, z: number) => number | ||
function generate2DNoiseFn (source: Uint8Array[]): (ox: number, oy: number) => number { | ||
const [sx, sy] = [source.length, source[0].length] | ||
return (ox, oy) => { | ||
const [x, y] = [ox % sx + sx, oy % sy + sy] | ||
const [_x, _y] = [Math.floor(x), Math.floor(y)] | ||
const [xi, yi] = [x - _x, y - _y] | ||
const [x0, y0] = [((_x - 1) + sx) % sx, ((_y - 1) + sy) % sy] | ||
const [x1, y1] = [_x % sx, _y % sy] | ||
const [x2, y2] = [(_x + 1) % sx, (_y + 1) % sy] | ||
const [x3, y3] = [(_x + 2) % sx, (_y + 2) % sy] | ||
return cerp( | ||
cerp(source[x0][y0], source[x1][y0], source[x2][y0], source[x3][y0], xi), | ||
cerp(source[x0][y1], source[x1][y1], source[x2][y1], source[x3][y1], xi), | ||
cerp(source[x0][y2], source[x1][y2], source[x2][y2], source[x3][y2], xi), | ||
cerp(source[x0][y3], source[x1][y3], source[x2][y3], source[x3][y3], xi), | ||
yi | ||
) | ||
} | ||
} | ||
export type Noise4Fn = (x: number, y: number, z: number, w: number) => number | ||
function generate3DNoiseFn (source: Uint8Array[][]): (ox: number, oy: number, oz: number) => number { | ||
const [sx, sy, sz] = [source.length, source[0].length, source[0][0].length] | ||
return (ox, oy, oz) => { | ||
const [x, y, z] = [ox % sx + sx, oy % sy + sy, oz % sz + sz] | ||
const [_x, _y, _z] = [Math.floor(x), Math.floor(y), Math.floor(z)] | ||
const [xi, yi, zi] = [x - _x, y - _y, z - _z] | ||
const [x0, y0, z0] = [((_x - 1) + sx) % sx, ((_y - 1) + sy) % sy, ((_z - 1) + sz) % sz] | ||
const [x1, y1, z1] = [_x % sx, _y % sy, _z % sz] | ||
const [x2, y2, z2] = [(_x + 1) % sx, (_y + 1) % sy, (_z + 1) % sz] | ||
const [x3, y3, z3] = [(_x + 2) % sx, (_y + 2) % sy, (_z + 2) % sz] | ||
return cerp( | ||
cerp( | ||
cerp(source[x0][y0][z0], source[x1][y0][z0], source[x2][y0][z0], source[x3][y0][z0], xi), | ||
cerp(source[x0][y1][z0], source[x1][y1][z0], source[x2][y1][z0], source[x3][y1][z0], xi), | ||
cerp(source[x0][y2][z0], source[x1][y2][z0], source[x2][y2][z0], source[x3][y2][z0], xi), | ||
cerp(source[x0][y3][z0], source[x1][y3][z0], source[x2][y3][z0], source[x3][y3][z0], xi), | ||
yi | ||
), | ||
cerp( | ||
cerp(source[x0][y0][z1], source[x1][y0][z1], source[x2][y0][z1], source[x3][y0][z1], xi), | ||
cerp(source[x0][y1][z1], source[x1][y1][z1], source[x2][y1][z1], source[x3][y1][z1], xi), | ||
cerp(source[x0][y2][z1], source[x1][y2][z1], source[x2][y2][z1], source[x3][y2][z1], xi), | ||
cerp(source[x0][y3][z1], source[x1][y3][z1], source[x2][y3][z1], source[x3][y3][z1], xi), | ||
yi | ||
), | ||
cerp( | ||
cerp(source[x0][y0][z2], source[x1][y0][z2], source[x2][y0][z2], source[x3][y0][z2], xi), | ||
cerp(source[x0][y1][z2], source[x1][y1][z2], source[x2][y1][z2], source[x3][y1][z2], xi), | ||
cerp(source[x0][y2][z2], source[x1][y2][z2], source[x2][y2][z2], source[x3][y2][z2], xi), | ||
cerp(source[x0][y3][z2], source[x1][y3][z2], source[x2][y3][z2], source[x3][y3][z2], xi), | ||
yi | ||
), | ||
cerp( | ||
cerp(source[x0][y0][z3], source[x1][y0][z3], source[x2][y0][z3], source[x3][y0][z3], xi), | ||
cerp(source[x0][y1][z3], source[x1][y1][z3], source[x2][y1][z3], source[x3][y1][z3], xi), | ||
cerp(source[x0][y2][z3], source[x1][y2][z3], source[x2][y2][z3], source[x3][y2][z3], xi), | ||
cerp(source[x0][y3][z3], source[x1][y3][z3], source[x2][y3][z3], source[x3][y3][z3], xi), | ||
yi | ||
), | ||
zi | ||
) | ||
} | ||
export type Options = { | ||
amplitude?: number, | ||
frequency?: number, | ||
octaves?: number, | ||
persistence?: number | ||
} | ||
function generateArray (count: number, fn: (index: number) => any): any[] { | ||
const items = [] | ||
for (let i = 0; i < count; i++) items.push(fn(i)) | ||
return items | ||
} | ||
export function generateCuboid (width: number, height: number, depth: number, options: Options = {}): Uint8Array[][] { | ||
export function cuboid ( | ||
width: number, | ||
height: number, | ||
depth: number, | ||
noise3: Noise3Fn, | ||
options: Options = {} | ||
): number[][] { | ||
const { amplitude, frequency, octaves, persistence } = processOptions(options) | ||
const white = generateArray(width, () => generateArray(height, () => | ||
window.crypto.getRandomValues(new Uint8Array(depth)) | ||
)) | ||
const noise = generate3DNoiseFn(white) | ||
return generateArray(width, x => generateArray(height, y => generateArray(depth, z => | ||
generateArray(octaves, octave => { | ||
const freq = frequency * Math.pow(2, octave) | ||
return noise(x * freq, y * freq, z * freq) * (amplitude * Math.pow(persistence, octave)) | ||
}).reduce((total, num) => total + num, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))) | ||
))) | ||
const field = new Array(width) | ||
for (let x = 0; x < width; x++) { | ||
field[x] = new Array(height) | ||
for (let y = 0; y < height; y++) { | ||
field[x][y] = new Array(depth) | ||
for (let z = 0; z < depth; z++) { | ||
let value = 0.0 | ||
for (let octave = 0; octave < octaves; octave++) { | ||
const freq = frequency * Math.pow(2, octave) | ||
value += noise3(x * freq, y * freq, z * freq) * (amplitude * Math.pow(persistence, octave)) | ||
} | ||
field[x][y][z] = value / (2 - (1 / Math.pow(2, octaves - 1))) | ||
} | ||
} | ||
} | ||
return field | ||
} | ||
export function generateCylinder (circumference: number, height: number, options: Options = {}): Uint8Array[] { | ||
export function cylinderSurface ( | ||
circumference: number, | ||
height: number, | ||
noise3: Noise3Fn, | ||
options: Options = {} | ||
): number[] { | ||
const { amplitude, frequency, octaves, persistence } = processOptions(options) | ||
const diameter = Math.ceil(circumference / Math.PI) | ||
const white = generateArray(diameter, () => generateArray(height, () => | ||
window.crypto.getRandomValues(new Uint8Array(diameter)) | ||
)) | ||
const noise = generate3DNoiseFn(white) | ||
const radius = circumference / TWO_PI | ||
return generateArray(circumference, x => generateArray(height, y => | ||
generateArray(octaves, octave => { | ||
const freq = frequency * Math.pow(2, octave) | ||
const nx = x / circumference | ||
const rdx = nx * TWO_PI | ||
const [a, b] = [radius * Math.sin(rdx), radius * Math.cos(rdx)] | ||
return noise(a * freq, b * freq, y * freq) * (amplitude * Math.pow(persistence, octave)) | ||
}).reduce((total, num) => total + num, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))) | ||
)) | ||
const field = new Array(circumference) | ||
for (let x = 0; x < circumference; x++) { | ||
field[x] = new Array(height) | ||
for (let y = 0; y < height; y++) { | ||
let value = 0.0 | ||
for (let octave = 0; octave < octaves; octave++) { | ||
const freq = frequency * Math.pow(2, octave) | ||
const nx = x / circumference | ||
const rdx = nx * TWO_PI | ||
const [a, b] = [radius * Math.sin(rdx), radius * Math.cos(rdx)] | ||
value += noise3(a * freq, b * freq, y * freq) * (amplitude * Math.pow(persistence, octave)) | ||
} | ||
field[x][y] = value / (2 - (1 / Math.pow(2, octaves - 1))) | ||
} | ||
} | ||
return field | ||
} | ||
export function generateLine (length: number, options: Options = {}): number[] { | ||
export function line (length: number, noise1: Noise1Fn, options: Options = {}): number[] { | ||
const { amplitude, frequency, octaves, persistence } = processOptions(options) | ||
const white = <Uint8Array> window.crypto.getRandomValues(new Uint8Array(length)) | ||
const noise = generate1DNoiseFn(white) | ||
return generateArray(length, x => | ||
generateArray(octaves, octave => { | ||
const field = new Array(length) | ||
for (let x = 0; x < length; x++) { | ||
let value = 0.0 | ||
for (let octave = 0; octave < octaves; octave++) { | ||
const freq = frequency * Math.pow(2, octaves) | ||
return noise(x * freq) * (amplitude * Math.pow(persistence, octave)) | ||
}).reduce((total, num) => total + num, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))) | ||
) | ||
value += noise1(x * freq) * (amplitude * Math.pow(persistence, octave)) | ||
} | ||
field[x] = value / (2 - (1 / Math.pow(2, octaves - 1))) | ||
} | ||
return field | ||
} | ||
export function generateRectangle (width: number, height: number, options: Options = {}): Uint8Array[] { | ||
export function rectangle ( | ||
width: number, | ||
height: number, | ||
noise2: Noise2Fn, | ||
options: Options = {} | ||
): number[] { | ||
const { amplitude, frequency, octaves, persistence } = processOptions(options) | ||
const white = generateArray(width, () => window.crypto.getRandomValues(new Uint8Array(height))) | ||
const noise = generate2DNoiseFn(white) | ||
return generateArray(width, x => generateArray(height, y => | ||
generateArray(octaves, octave => { | ||
const freq = frequency * Math.pow(2, octave) | ||
return noise(x * freq, y * freq) * (amplitude * Math.pow(persistence, octave)) | ||
}).reduce((total, num) => total + num, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))) | ||
)) | ||
const field = new Array(width) | ||
for (let x = 0; x < width; x++) { | ||
field[x] = new Array(height) | ||
for (let y = 0; y < height; y++) { | ||
let value = 0.0 | ||
for (let octave = 0; octave < octaves; octave++) { | ||
const freq = frequency * Math.pow(2, octave) | ||
value += noise2(x * freq, y * freq) * (amplitude * Math.pow(persistence, octave)) | ||
} | ||
field[x][y] = value / (2 - (1 / Math.pow(2, octaves - 1))) | ||
} | ||
} | ||
return field | ||
} | ||
export function generateSphere (circumference: number, options: Options = {}): Uint8Array[] { | ||
export function sphereSurface (circumference: number, noise3: Noise3Fn, options: Options = {}): number[] { | ||
const { amplitude, frequency, octaves, persistence } = processOptions(options) | ||
const diameter = Math.ceil(circumference / Math.PI) | ||
const white = generateArray(diameter, () => generateArray(diameter, () => | ||
window.crypto.getRandomValues(new Uint8Array(diameter)) | ||
)) | ||
const noise = generate3DNoiseFn(white) | ||
const radius = circumference / TWO_PI | ||
return generateArray(circumference, x => generateArray(circumference, y => | ||
generateArray(octaves, octave => { | ||
const freq = frequency * Math.pow(2, octave) | ||
const [nx, ny] = [x / circumference, y / circumference] | ||
const [rdx, rdy] = [nx * TWO_PI, ny * TWO_PI] | ||
const sinY = Math.sin(rdy + Math.PI) | ||
const sinRds = 2 * Math.PI | ||
const a = sinRds * Math.sin(rdx) * sinY | ||
const b = sinRds * Math.cos(rdx) * sinY | ||
const d = sinRds * Math.cos(rdy) | ||
return noise(a * freq, b * freq, d * freq) * (amplitude * Math.pow(persistence, octave)) | ||
}).reduce((total, num) => total + num, 0) | ||
/ (2 - (1 / Math.pow(2, octaves - 1))) | ||
)) | ||
const field = new Array(circumference) | ||
for (let x = 0; x < circumference; x++) { | ||
field[x] = new Array(circumference) | ||
for (let y = 0; y < circumference; y++) { | ||
let value = 0.0 | ||
for (let octave = 0; octave < octaves; octave++) { | ||
const freq = frequency * Math.pow(2, octave) | ||
const [nx, ny] = [x / circumference, y / circumference] | ||
const [rdx, rdy] = [nx * TWO_PI, ny * TWO_PI] | ||
const sinY = Math.sin(rdy + Math.PI) | ||
const sinRds = 2 * Math.PI | ||
const a = sinRds * Math.sin(rdx) * sinY | ||
const b = sinRds * Math.cos(rdx) * sinY | ||
const d = sinRds * Math.cos(rdy) | ||
value += noise3(a * freq, b * freq, d * freq) * (amplitude * Math.pow(persistence, octave)) | ||
} | ||
field[x][y] = value / (2 - (1 / Math.pow(2, octaves - 1))) | ||
} | ||
} | ||
return field | ||
} | ||
@@ -187,0 +132,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
97
414148
16
265
1