├── .babelrc ├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── dist └── worley-noise.js ├── examples ├── advanced.html ├── anim.html └── basic.html ├── img ├── e1.png ├── e2.png ├── e3.png ├── m1.png ├── m2.png └── noise3D.gif ├── package-lock.json ├── package.json ├── src ├── index.js └── worley-noise.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"], 3 | "plugins": ["@babel/plugin-transform-modules-commonjs"] 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | # editorconfig-tools is unable to ignore longs strings or urls 11 | max_line_length = null 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | .env.test 60 | 61 | # parcel-bundler cache (https://parceljs.org/) 62 | .cache 63 | 64 | # next.js build output 65 | .next 66 | 67 | # nuxt.js build output 68 | .nuxt 69 | 70 | # vuepress build output 71 | .vuepress/dist 72 | 73 | # Serverless directories 74 | .serverless/ 75 | 76 | # FuseBox cache 77 | .fusebox/ 78 | 79 | # DynamoDB Local files 80 | .dynamodb/ 81 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Zsolt Czinege 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # worley-noise 2 | 3 | Worley noise in JavaScript. 4 | 5 | ![](img/noise3D.gif) 6 | 7 | ## What is it? 8 | Worley noise (also called Voronoi or Cell noise) is a type of noise where the value of a point is based on its distance to a set of previously placed points. By using the distance to the closest point it produces images like this: 9 | 10 | ![](img/e1.png) 11 | 12 | But we don't have to use the closest point, we can choose the second, third, etc. We can even combine these values by performing mathematical operations on them like addition and subtraction: 13 | 14 | ![](img/e2.png) ![](img/e3.png) 15 | 16 | The previous images were generated by using the Euclidean distance for the calculations. If we use Manhattan distance we get quite different results: 17 | 18 | ![](img/m1.png) ![](img/m2.png) 19 | 20 | The formula for generating these images can be found in the advanced example. 21 | 22 | ## Getting started 23 | `npm install worley-noise` 24 | 25 | Example usage: 26 | 27 | ```html 28 | 29 | 71 | ``` 72 | Canvas examples can be found in the project. 73 | 74 | ## Development 75 | 76 | Install dependencies: 77 | ``` 78 | npm install 79 | ``` 80 | Create a dev build: 81 | ``` 82 | npm run dev 83 | ``` 84 | 85 | Create a minified build: 86 | ``` 87 | npm run build 88 | ``` 89 | -------------------------------------------------------------------------------- /dist/worley-noise.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(); 4 | else if(typeof define === 'function' && define.amd) 5 | define([], factory); 6 | else if(typeof exports === 'object') 7 | exports["WorleyNoise"] = factory(); 8 | else 9 | root["WorleyNoise"] = factory(); 10 | })(typeof self !== "undefined" ? self : this, function() { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | /******/ 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | /******/ 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) { 20 | /******/ return installedModules[moduleId].exports; 21 | /******/ } 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ i: moduleId, 25 | /******/ l: false, 26 | /******/ exports: {} 27 | /******/ }; 28 | /******/ 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | /******/ 32 | /******/ // Flag the module as loaded 33 | /******/ module.l = true; 34 | /******/ 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | /******/ 39 | /******/ 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | /******/ 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | /******/ 46 | /******/ // define getter function for harmony exports 47 | /******/ __webpack_require__.d = function(exports, name, getter) { 48 | /******/ if(!__webpack_require__.o(exports, name)) { 49 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 50 | /******/ } 51 | /******/ }; 52 | /******/ 53 | /******/ // define __esModule on exports 54 | /******/ __webpack_require__.r = function(exports) { 55 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 56 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 57 | /******/ } 58 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 59 | /******/ }; 60 | /******/ 61 | /******/ // create a fake namespace object 62 | /******/ // mode & 1: value is a module id, require it 63 | /******/ // mode & 2: merge all properties of value into the ns 64 | /******/ // mode & 4: return value when already ns object 65 | /******/ // mode & 8|1: behave like require 66 | /******/ __webpack_require__.t = function(value, mode) { 67 | /******/ if(mode & 1) value = __webpack_require__(value); 68 | /******/ if(mode & 8) return value; 69 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 70 | /******/ var ns = Object.create(null); 71 | /******/ __webpack_require__.r(ns); 72 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 73 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 74 | /******/ return ns; 75 | /******/ }; 76 | /******/ 77 | /******/ // getDefaultExport function for compatibility with non-harmony modules 78 | /******/ __webpack_require__.n = function(module) { 79 | /******/ var getter = module && module.__esModule ? 80 | /******/ function getDefault() { return module['default']; } : 81 | /******/ function getModuleExports() { return module; }; 82 | /******/ __webpack_require__.d(getter, 'a', getter); 83 | /******/ return getter; 84 | /******/ }; 85 | /******/ 86 | /******/ // Object.prototype.hasOwnProperty.call 87 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 88 | /******/ 89 | /******/ // __webpack_public_path__ 90 | /******/ __webpack_require__.p = ""; 91 | /******/ 92 | /******/ 93 | /******/ // Load entry module and return exports 94 | /******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); 95 | /******/ }) 96 | /************************************************************************/ 97 | /******/ ({ 98 | 99 | /***/ "./node_modules/alea/alea.js": 100 | /*!***********************************!*\ 101 | !*** ./node_modules/alea/alea.js ***! 102 | \***********************************/ 103 | /*! no static exports found */ 104 | /***/ (function(module, exports, __webpack_require__) { 105 | 106 | eval("(function (root, factory) {\n if (true) {\n module.exports = factory();\n } else {}\n}(this, function () {\n\n 'use strict';\n\n // From http://baagoe.com/en/RandomMusings/javascript/\n\n // importState to sync generator states\n Alea.importState = function(i){\n var random = new Alea();\n random.importState(i);\n return random;\n };\n\n return Alea;\n\n function Alea() {\n return (function(args) {\n // Johannes Baagøe , 2010\n var s0 = 0;\n var s1 = 0;\n var s2 = 0;\n var c = 1;\n\n if (args.length == 0) {\n args = [+new Date];\n }\n var mash = Mash();\n s0 = mash(' ');\n s1 = mash(' ');\n s2 = mash(' ');\n\n for (var i = 0; i < args.length; i++) {\n s0 -= mash(args[i]);\n if (s0 < 0) {\n s0 += 1;\n }\n s1 -= mash(args[i]);\n if (s1 < 0) {\n s1 += 1;\n }\n s2 -= mash(args[i]);\n if (s2 < 0) {\n s2 += 1;\n }\n }\n mash = null;\n\n var random = function() {\n var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32\n s0 = s1;\n s1 = s2;\n return s2 = t - (c = t | 0);\n };\n random.uint32 = function() {\n return random() * 0x100000000; // 2^32\n };\n random.fract53 = function() {\n return random() + \n (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53\n };\n random.version = 'Alea 0.9';\n random.args = args;\n\n // my own additions to sync state between two generators\n random.exportState = function(){\n return [s0, s1, s2, c];\n };\n random.importState = function(i){\n s0 = +i[0] || 0;\n s1 = +i[1] || 0;\n s2 = +i[2] || 0;\n c = +i[3] || 0;\n };\n \n return random;\n\n } (Array.prototype.slice.call(arguments)));\n }\n\n function Mash() {\n var n = 0xefc8249d;\n\n var mash = function(data) {\n data = data.toString();\n for (var i = 0; i < data.length; i++) {\n n += data.charCodeAt(i);\n var h = 0.02519603282416938 * n;\n n = h >>> 0;\n h -= n;\n h *= n;\n n = h >>> 0;\n h -= n;\n n += h * 0x100000000; // 2^32\n }\n return (n >>> 0) * 2.3283064365386963e-10; // 2^-32\n };\n\n mash.version = 'Mash 0.9';\n return mash;\n }\n}));\n\n\n//# sourceURL=webpack://WorleyNoise/./node_modules/alea/alea.js?"); 107 | 108 | /***/ }), 109 | 110 | /***/ "./src/index.js": 111 | /*!**********************!*\ 112 | !*** ./src/index.js ***! 113 | \**********************/ 114 | /*! no static exports found */ 115 | /***/ (function(module, exports, __webpack_require__) { 116 | 117 | "use strict"; 118 | eval("\n\nvar _worleyNoise = _interopRequireDefault(__webpack_require__(/*! ./worley-noise */ \"./src/worley-noise.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nmodule.exports = _worleyNoise.default;\n\n//# sourceURL=webpack://WorleyNoise/./src/index.js?"); 119 | 120 | /***/ }), 121 | 122 | /***/ "./src/worley-noise.js": 123 | /*!*****************************!*\ 124 | !*** ./src/worley-noise.js ***! 125 | \*****************************/ 126 | /*! no static exports found */ 127 | /***/ (function(module, exports, __webpack_require__) { 128 | 129 | "use strict"; 130 | eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _alea = _interopRequireDefault(__webpack_require__(/*! alea */ \"./node_modules/alea/alea.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar WorleyNoise =\n/*#__PURE__*/\nfunction () {\n function WorleyNoise(config) {\n _classCallCheck(this, WorleyNoise);\n\n config = config || {};\n if (config.dim !== 2 && config.dim !== 3 && config.dim !== undefined) throw '\"dim\" can be 2 or 3';\n this._dim = config.dim || 2;\n this._rng = new _alea.default(config.seed || Math.random());\n this._points = [];\n\n for (var i = 0; i < config.numPoints; i++) {\n this._points.push({\n x: this._rng(),\n y: this._rng(),\n z: this._rng()\n });\n }\n }\n\n _createClass(WorleyNoise, [{\n key: \"addPoint\",\n value: function addPoint(coord) {\n this._points.push(coord);\n }\n }, {\n key: \"getEuclidean\",\n value: function getEuclidean(coord, k) {\n return Math.sqrt(this._calculateValue(coord, k, euclidean));\n }\n }, {\n key: \"getManhattan\",\n value: function getManhattan(coord, k) {\n return this._calculateValue(coord, k, manhattan);\n }\n }, {\n key: \"renderImage\",\n value: function renderImage(resolution, config) {\n var _this = this;\n\n config = config || {};\n var step = 1 / (resolution - 1);\n var img = [];\n\n var callback = config.callback || function (e, m) {\n return e(1);\n };\n\n var x, y;\n\n var e = function e(k) {\n return Math.sqrt(_this._calculateValue({\n x: x * step,\n y: y * step,\n z: config.z || 0\n }, k, euclidean));\n };\n\n var m = function m(k) {\n return _this._calculateValue({\n x: x * step,\n y: y * step,\n z: config.z || 0\n }, k, manhattan);\n };\n\n for (y = 0; y < resolution; ++y) {\n for (x = 0; x < resolution; ++x) {\n img[y * resolution + x] = callback(e, m);\n }\n }\n\n if (!config.normalize) return img;\n var min = Number.POSITIVE_INFINITY;\n var max = Number.NEGATIVE_INFINITY;\n img.forEach(function (v) {\n min = Math.min(min, v);\n max = Math.max(max, v);\n });\n var scale = 1 / (max - min);\n return img.map(function (v) {\n return (v - min) * scale;\n });\n }\n }, {\n key: \"_calculateValue\",\n value: function _calculateValue(coord, k, distFn) {\n var minDist;\n\n this._points.forEach(function (p) {\n p.selected = false;\n });\n\n for (var j = 0; j < k; ++j) {\n var minIdx = void 0;\n minDist = Number.POSITIVE_INFINITY;\n\n for (var i = 0; i < this._points.length; ++i) {\n var p = this._points[i];\n var dz = this._dim === 2 ? 0 : coord.z - p.z;\n var dist = distFn(coord.x - p.x, coord.y - p.y, dz);\n\n if (dist < minDist && !p.selected) {\n minDist = dist;\n minIdx = i;\n }\n }\n\n this._points[minIdx].selected = true;\n }\n\n return minDist;\n }\n }]);\n\n return WorleyNoise;\n}();\n\nvar euclidean = function euclidean(dx, dy, dz) {\n return dx * dx + dy * dy + dz * dz;\n};\n\nvar manhattan = function manhattan(dx, dy, dz) {\n return Math.abs(dx) + Math.abs(dy) + Math.abs(dz);\n};\n\nvar _default = WorleyNoise;\nexports.default = _default;\n\n//# sourceURL=webpack://WorleyNoise/./src/worley-noise.js?"); 131 | 132 | /***/ }) 133 | 134 | /******/ }); 135 | }); -------------------------------------------------------------------------------- /examples/advanced.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Advanced example 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /examples/anim.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Animation example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Basic example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /img/e1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsoltc/worley-noise/6410c3cc4bf1a7247e31ff6f76dd99821b8ae16c/img/e1.png -------------------------------------------------------------------------------- /img/e2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsoltc/worley-noise/6410c3cc4bf1a7247e31ff6f76dd99821b8ae16c/img/e2.png -------------------------------------------------------------------------------- /img/e3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsoltc/worley-noise/6410c3cc4bf1a7247e31ff6f76dd99821b8ae16c/img/e3.png -------------------------------------------------------------------------------- /img/m1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsoltc/worley-noise/6410c3cc4bf1a7247e31ff6f76dd99821b8ae16c/img/m1.png -------------------------------------------------------------------------------- /img/m2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsoltc/worley-noise/6410c3cc4bf1a7247e31ff6f76dd99821b8ae16c/img/m2.png -------------------------------------------------------------------------------- /img/noise3D.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsoltc/worley-noise/6410c3cc4bf1a7247e31ff6f76dd99821b8ae16c/img/noise3D.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "worley-noise", 3 | "version": "2.0.0", 4 | "description": "Worley noise in JavaScript", 5 | "main": "dist/worley-noise.js", 6 | "files": [ 7 | "src/*" 8 | ], 9 | "directories": { 10 | "example": "examples" 11 | }, 12 | "scripts": { 13 | "dev": "webpack --mode development --watch", 14 | "build": "webpack --mode production" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/zsoltc/worley-noise.git" 19 | }, 20 | "keywords": [ 21 | "worley", 22 | "noise", 23 | "javascript" 24 | ], 25 | "author": "Zsolt Czinege", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/zsoltc/worley-noise/issues" 29 | }, 30 | "homepage": "https://github.com/zsoltc/worley-noise#readme", 31 | "devDependencies": { 32 | "@babel/core": "^7.2.2", 33 | "@babel/plugin-transform-modules-commonjs": "^7.2.0", 34 | "@babel/preset-env": "^7.3.1", 35 | "babel-loader": "^8.0.5", 36 | "webpack": "^4.29.0", 37 | "webpack-cli": "^3.2.1" 38 | }, 39 | "dependencies": { 40 | "alea": "^1.0.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import WorleyNoise from './worley-noise'; 2 | 3 | 4 | module.exports = WorleyNoise; 5 | -------------------------------------------------------------------------------- /src/worley-noise.js: -------------------------------------------------------------------------------- 1 | import Alea from 'alea'; 2 | 3 | 4 | class WorleyNoise { 5 | constructor(config) { 6 | config = config || {}; 7 | if (config.dim !== 2 && config.dim !== 3 && config.dim !== undefined) 8 | throw '"dim" can be 2 or 3'; 9 | 10 | this._dim = config.dim || 2; 11 | this._rng = new Alea(config.seed || Math.random()); 12 | this._points = []; 13 | 14 | for (let i = 0; i < config.numPoints; i++) { 15 | this._points.push({ 16 | x: this._rng(), 17 | y: this._rng(), 18 | z: this._rng(), 19 | }); 20 | } 21 | } 22 | 23 | addPoint(coord) { 24 | this._points.push(coord); 25 | } 26 | 27 | getEuclidean(coord, k) { 28 | return Math.sqrt(this._calculateValue(coord, k, euclidean)); 29 | } 30 | 31 | getManhattan(coord, k) { 32 | return this._calculateValue(coord, k, manhattan); 33 | } 34 | 35 | renderImage(resolution, config) { 36 | config = config || {}; 37 | const step = 1 / (resolution - 1); 38 | const img = []; 39 | const callback = config.callback || ((e, m) => e(1)); 40 | let x, y; 41 | 42 | const e = k => Math.sqrt(this._calculateValue({ 43 | x: x * step, 44 | y: y * step, 45 | z: config.z || 0, 46 | }, k, euclidean)); 47 | 48 | const m = k => this._calculateValue({ 49 | x: x * step, 50 | y: y * step, 51 | z: config.z || 0, 52 | }, k, manhattan); 53 | 54 | for (y = 0; y < resolution; ++y) { 55 | for (x = 0; x < resolution; ++x) { 56 | img[y * resolution + x] = callback(e, m); 57 | } 58 | } 59 | 60 | if (!config.normalize) 61 | return img; 62 | 63 | let min = Number.POSITIVE_INFINITY; 64 | let max = Number.NEGATIVE_INFINITY; 65 | 66 | img.forEach(v => { 67 | min = Math.min(min, v); 68 | max = Math.max(max, v); 69 | }); 70 | 71 | let scale = 1 / (max - min); 72 | return img.map(v => (v - min) * scale); 73 | } 74 | 75 | _calculateValue(coord, k, distFn) { 76 | let minDist; 77 | this._points.forEach(p => { p.selected = false; }); 78 | 79 | for (let j = 0; j < k; ++j) { 80 | let minIdx; 81 | minDist = Number.POSITIVE_INFINITY; 82 | 83 | for (let i = 0; i < this._points.length; ++i) { 84 | const p = this._points[i]; 85 | const dz = this._dim === 2 ? 0 : coord.z - p.z; 86 | const dist = distFn(coord.x - p.x, coord.y - p.y, dz); 87 | 88 | if (dist < minDist && !p.selected) { 89 | minDist = dist; 90 | minIdx = i; 91 | } 92 | } 93 | 94 | this._points[minIdx].selected = true; 95 | } 96 | 97 | return minDist; 98 | } 99 | } 100 | 101 | const euclidean = (dx, dy, dz) => dx * dx + dy * dy + dz * dz; 102 | const manhattan = (dx, dy, dz) => Math.abs(dx) + Math.abs(dy) + Math.abs(dz); 103 | 104 | export default WorleyNoise; 105 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | 4 | module.exports = { 5 | entry: './src/index.js', 6 | output: { 7 | path: path.resolve(__dirname, 'dist'), 8 | filename: 'worley-noise.js', 9 | library: 'WorleyNoise', 10 | libraryTarget: 'umd', 11 | globalObject: 'typeof self !== "undefined" ? self : this', 12 | }, 13 | module: { 14 | rules: [{ 15 | test: /\.js$/, 16 | exclude: /node_modules/, 17 | use: { 18 | loader: 'babel-loader' 19 | } 20 | }] 21 | } 22 | }; 23 | --------------------------------------------------------------------------------