diff options
-rw-r--r-- | main.js | 21 | ||||
-rw-r--r-- | src/3rdparty/rhill-voronoi-core.js (renamed from modules/3rdparty/rhill-voronoi-core.js) | 0 | ||||
-rw-r--r-- | src/favicon.png (renamed from favicon.png) | bin | 215666 -> 215666 bytes | |||
-rw-r--r-- | src/index.html (renamed from index.html) | 0 | ||||
-rw-r--r-- | src/main.js | 42 | ||||
-rw-r--r-- | src/modules/Geometry.js (renamed from modules/Geometry.js) | 0 | ||||
-rw-r--r-- | src/modules/Geometry.test.js (renamed from modules/Geometry.test.js) | 0 | ||||
-rw-r--r-- | src/modules/Mouse.js | 53 | ||||
-rw-r--r-- | src/modules/Terrain.js (renamed from modules/Terrain.js) | 35 | ||||
-rw-r--r-- | src/modules/Util.js (renamed from modules/Util.js) | 0 | ||||
-rw-r--r-- | src/modules/Util.test.js (renamed from modules/Util.test.js) | 0 | ||||
-rw-r--r-- | src/modules/test-assert.js (renamed from modules/test-assert.js) | 0 | ||||
-rw-r--r-- | src/package.json (renamed from package.json) | 0 | ||||
-rw-r--r-- | src/test.js (renamed from test.js) | 2 |
14 files changed, 128 insertions, 25 deletions
diff --git a/main.js b/main.js deleted file mode 100644 index d02e0fb..0000000 --- a/main.js +++ /dev/null @@ -1,21 +0,0 @@ -import Voronoi from './modules/3rdparty/rhill-voronoi-core.js'; -import Terrain from './modules/Terrain.js'; - -const $ = id => document.getElementById(id) - -window.onload = () => { - let canvas = document.createElement('canvas'); - canvas.setAttribute('width', window.innerWidth); - canvas.setAttribute('height', window.innerHeight); - const ct = canvas.getContext('2d'); - - const scale = Math.min(window.innerWidth, window.innerHeight); - ct.scale(scale, scale); - - const terrain = new Terrain(); - terrain.renderGrid(ct); - - - const root = $('root'); - root.appendChild(canvas); -} diff --git a/modules/3rdparty/rhill-voronoi-core.js b/src/3rdparty/rhill-voronoi-core.js index 26dac8f..26dac8f 100644 --- a/modules/3rdparty/rhill-voronoi-core.js +++ b/src/3rdparty/rhill-voronoi-core.js diff --git a/favicon.png b/src/favicon.png Binary files differindex 181d8ea..181d8ea 100644 --- a/favicon.png +++ b/src/favicon.png diff --git a/index.html b/src/index.html index ce0739c..ce0739c 100644 --- a/index.html +++ b/src/index.html diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..ade4e27 --- /dev/null +++ b/src/main.js @@ -0,0 +1,42 @@ +import Voronoi from './modules/3rdparty/rhill-voronoi-core.js'; +import Terrain from './modules/Terrain.js'; +import Mouse from './modules/Mouse.js'; + +const $ = id => document.getElementById(id) + +window.onload = () => { + let canvas = document.createElement('canvas'); + const ct = canvas.getContext('2d'); + + let render; + + let mouse = new Mouse(ct); + + const setCanvasSize = () => { + canvas.setAttribute('width', window.innerWidth); + canvas.setAttribute('height', window.innerHeight); + const scale = Math.max(canvas.width, canvas.height); + ct.scale(scale, scale); + render(); + }; + window.addEventListener('resize', setCanvasSize); + + const terrain = new Terrain(); + render = () => { + ct.clearRect(0, 0, 1, 1); + terrain.renderGrid(ct); + mouse.render(ct); + }; + mouse.onMove = () => { + terrain.applyBrush(mouse.x, mouse.y, (pt, strength) => { + const lerp = (a, b, theta) => ((theta-1)*a) + (theta*b); + pt.height = lerp(pt.height, pt.height + 10, strength); + }, 1, mouse.radius); + render(); + } + + setCanvasSize(); + + const root = $('root'); + root.appendChild(canvas); +} diff --git a/modules/Geometry.js b/src/modules/Geometry.js index 628512b..628512b 100644 --- a/modules/Geometry.js +++ b/src/modules/Geometry.js diff --git a/modules/Geometry.test.js b/src/modules/Geometry.test.js index 925a53d..925a53d 100644 --- a/modules/Geometry.test.js +++ b/src/modules/Geometry.test.js diff --git a/src/modules/Mouse.js b/src/modules/Mouse.js new file mode 100644 index 0000000..0b8f922 --- /dev/null +++ b/src/modules/Mouse.js @@ -0,0 +1,53 @@ +class Mouse { + constructor(ct) { + this.ct = ct; + this.x = 0; + this.y = 0; + this.radius = 0.005; + this.show = false; + this.pressed = false; + this.onMove = null; + + window.addEventListener('mousemove', e => { + /* get current transform matrix */ + const matrix = this.ct.getTransform(); + matrix.invertSelf(); + + const x = e.offsetX; const y = e.offsetY; + this.x = matrix.a*x + matrix.b*y; + this.y = matrix.c*x + matrix.d*y; + + if (this.onMove) this.onMove(); + }); + + const root = document.getElementById('root'); + + root.addEventListener('mouseover', e => { + e = e ? e : window.event; + this.show = true; + }); + + root.addEventListener('mouseout', e => { + e = e ? e: window.event; + this.show = false; + }); + } + + render(ct) { + if (!this.show) return; + console.log(this.radius); + ct.save(); + + ct.strokeStyle = '#fff'; + + ct.beginPath(); + ct.arc(this.x, this.y, this.radius, 0, 2*Math.PI); + ct.closePath(); + ct.stroke(); + + ct.restore(); + } +} + + +export default Mouse; diff --git a/modules/Terrain.js b/src/modules/Terrain.js index ca0ab77..21908ac 100644 --- a/modules/Terrain.js +++ b/src/modules/Terrain.js @@ -3,7 +3,7 @@ import Voronoi from './3rdparty/rhill-voronoi-core.js'; import { useAverage } from './Util.js'; -import { QuadTree } from './Geometry.js'; +import { AABB, QuadTree } from './Geometry.js'; /* from here on up, we always assume that points live in the range [(0,0), (1,1)) */ @@ -47,11 +47,14 @@ function lloydRelax(point_set, density) { class Terrain { constructor() { - const N_SEED_POINTS = 2**14; + const N_SEED_POINTS = 2**12; const N_RELAX_ITERATIONS = 1; const RELAX_DENSITY = 400; const randomPoint = () => ({x: Math.random(), y: Math.random()}); + this.min_height = 0; + this.max_height = 0; + let seed_points = []; for (let i=0; i<N_SEED_POINTS; i++) seed_points.push(randomPoint()); @@ -62,19 +65,45 @@ class Terrain { this.graph = v.compute(seed_points, {xl: 0, xr: 1, yt: 0, yb: 1}); this.tree = new QuadTree(1,1); - for (let v of this.graph.vertices) this.tree.insert(v); + for (let v of this.graph.vertices) { + v.height = 0; + this.tree.insert(v); + } + } + + + applyBrush(x, y, f, strength, radius) { + const region = new AABB(x-radius, y-radius, 2*radius, 2*radius); + const points = this.tree.root.getPointsInRegion(region); + + const dist2 = (a, b) => (a.x - b.x)**2 + (a.y - b.y)**2; + + const sigma = radius/3; + const beta = 1/(2*sigma*sigma); + const center = { x, y }; + const power = pt => Math.exp(-beta * dist2(pt, center)); + + for (let pt of points) f(pt, strength * power(pt)); } renderGrid(ct) { + ct.save(); ct.lineWidth = 0.001; for (let edge of this.graph.edges) { + ct.fillStyle = `hsl(${edge.va.height}, 100%, 50%)`; + ct.beginPath(); + ct.arc(edge.va.x, edge.va.y, 0.005, 0, 2*Math.PI); + ct.closePath(); + ct.fill(); + ct.beginPath(); ct.moveTo(edge.va.x, edge.va.y); ct.lineTo(edge.vb.x, edge.vb.y); ct.closePath(); ct.stroke(); } + ct.restore(); } } diff --git a/modules/Util.js b/src/modules/Util.js index cbe466d..cbe466d 100644 --- a/modules/Util.js +++ b/src/modules/Util.js diff --git a/modules/Util.test.js b/src/modules/Util.test.js index 000d54e..000d54e 100644 --- a/modules/Util.test.js +++ b/src/modules/Util.test.js diff --git a/modules/test-assert.js b/src/modules/test-assert.js index 7be2989..7be2989 100644 --- a/modules/test-assert.js +++ b/src/modules/test-assert.js diff --git a/package.json b/src/package.json index bedb411..bedb411 100644 --- a/package.json +++ b/src/package.json @@ -13,7 +13,7 @@ function recursiveScanDir(path, f) } } -recursiveScanDir('./modules', fname => { +recursiveScanDir('.', fname => { if (fname.endsWith('.test.js')) { console.log(`======== ${fname} ========`); execSync(`node ${fname}`, { stdio: 'inherit' }); |