OSZAR »
` function clear () { emit('clear') } function up () { emit('floor-up') } function down () { emit('floor-down') } }) app.mount('body') },{"../":8,"choo":19,"choo/html":18,"regl":104,"regl-component":119}],8:[function(require,module,exports){ var mat4 = require('gl-mat4') var cylinder = require('primitive-cylinder') var fwgl = require('fwgl') module.exports = Component function Component (opts) { var self = this if (!(this instanceof Component)) return new Component(opts) this.app = fwgl({ emitter: opts.emitter, state: opts.state, extensions: opts.extensions, width: window.innerWidth, height: window.innerHeight }) this.app.use(require('./lib/store/camera.js')) this.app.use(require('./lib/store/cursor.js')) this.app.use(require('./lib/store/mesh.js')) this.app.draw(require('./lib/draw/grid.js')) this.app.draw(require('./lib/draw/cursor.js')) this.app.draw(require('./lib/draw/wall.js')) this.app.draw(require('./lib/draw/hole.js')) this.app.emitter.on('element', function (elem) { elem.addEventListener('mousemove', onmouse) elem.addEventListener('click', onmouse) elem.addEventListener('mousedown', onmouse) elem.addEventListener('mouseup', onmouse) }) function onmouse (ev) { self.app.emitter.emit('mouse', ev) } } Component.prototype.resize = function (width, height) { this.app.state.app.width = width this.app.state.app.height = height this.app.emitter.emit('resize') this.app.emitter.emit('frame') } },{"./lib/draw/cursor.js":9,"./lib/draw/grid.js":10,"./lib/draw/hole.js":11,"./lib/draw/wall.js":12,"./lib/store/camera.js":13,"./lib/store/cursor.js":14,"./lib/store/mesh.js":15,"fwgl":111,"gl-mat4":32,"primitive-cylinder":103}],9:[function(require,module,exports){ var cylinder = require('primitive-cylinder') module.exports = Cursor function Cursor (regl) { if (!(this instanceof Cursor)) return new Cursor(regl) var mesh = cylinder(1,1,1,16,1) this._draw = regl({ frag: ` precision highp float; void main () { gl_FragColor = vec4(1,0,1,1); } `, vert: ` precision highp float; uniform mat4 projection, view; uniform vec3 offset; attribute vec3 position; varying vec3 vpos; void main () { vpos = position*vec3(0.01,1,0.01) + (vec3(offset.x,0.75,offset.z)*2.0-1.0)+vec3(0,offset.y*0.5,0); gl_Position = projection * view * vec4(vpos,1); } `, uniforms: { offset: regl.prop('position') }, attributes: { position: mesh.positions }, elements: mesh.cells }) } Cursor.prototype.draw = function (state) { if (state.cursor.visible) { this._draw(state.cursor) } } },{"primitive-cylinder":103}],10:[function(require,module,exports){ var gridMesh = require('grid-mesh') module.exports = Grid function Grid (regl) { if (!(this instanceof Grid)) return new Grid(regl) var mesh = gridMesh(1,1) var res = 8.0 var drawOpts = { frag: ` precision highp float; varying vec2 vpos; float PI = ${Math.PI}; void main () { float q = ${res.toFixed(1)}; float p = q*PI, r = -PI*0.5; float x = 1.0-pow(1.0 - min(sin(vpos.x*p+r)*0.5+0.5,sin(vpos.y*p+r)*0.5+0.5),64.0); vec2 c = floor((vpos*0.5+0.5)*q)/q; float alpha = 1.0 - pow(x*0.8,2.0); gl_FragColor = vec4((c*0.3+0.7)*(x*0.2+0.8),x*0.2+0.8,alpha); } `, vert: ` precision highp float; uniform mat4 projection, view; uniform float floorIndex; attribute vec2 position; varying vec2 vpos; void main () { vpos = position*2.0-1.0; vec3 p = vec3(vpos.x,floorIndex*0.5,vpos.y); gl_Position = projection * view * vec4(p,1); } `, uniforms: { floorIndex: regl.prop('floor') }, attributes: { position: mesh.positions }, depth: { mask: false }, blend: { enable: true, func: { src: 'src alpha', dst: 'one minus src alpha' } }, elements: mesh.cells } this._draw = regl(drawOpts) this._pick = regl(Object.assign({}, drawOpts, { frag: ` precision highp float; varying vec2 vpos; void main () { float q = ${res.toFixed(1)}; vec2 c = floor((vpos*0.5+0.5)*q)/q; gl_FragColor = vec4(1,c.x,c.y,0); } `, blend: { enable: false } })) } Grid.prototype.postDraw = function (state) { this._draw({ floor: state.currentFloor }) } Grid.prototype.pick = function (state) { if (state.mode === 'walls') { this._pick({ floor: state.currentFloor }) } } },{"grid-mesh":86}],11:[function(require,module,exports){ module.exports = Hole function Hole (regl) { if (!(this instanceof Hole)) return new Hole(regl) var drawOpts = { frag: ` precision highp float; varying vec3 vwall; uniform vec2 visibleSize; uniform sampler2D visibleTexture; void main () { vec2 uv = vec2( floor(vwall.z)/(visibleSize.x-1.0), floor(vwall.x)/(visibleSize.y-1.0) ); float x = texture2D(visibleTexture,uv).w; if (x < 0.9) discard; gl_FragColor = vec4(1,1,1,0.1); } `, vert: ` precision highp float; uniform mat4 projection, view; attribute vec3 position; attribute vec3 wallCoord; uniform float floorIndex; varying vec3 vpos; varying vec3 vwall; void main () { vpos = position + vec3(0,floorIndex*0.5,0); vwall = wallCoord; gl_Position = projection * view * vec4(vpos,1); } `, uniforms: { visibleTexture: regl.prop('visible.texture'), visibleSize: regl.prop('visible.size'), floorIndex: regl.prop('floor') }, attributes: { position: regl.prop('positions'), wallCoord: regl.prop('wallCoords') }, blend: { enable: true, func: { src: 'src alpha', dst: 'one minus src alpha' } }, depth: { mask: false }, elements: regl.prop('cells'), count: function (context, props) { return props.cells.length*3 } } this._draw = regl(drawOpts) this._pick = regl(Object.assign({}, drawOpts, { frag: ` precision highp float; varying vec3 vpos; varying vec3 vwall; void main () { gl_FragColor = vec4(2,vwall); } `, blend: { enable: false } })) } Hole.prototype.postDraw = function (state) { this._draw(state.floors[state.currentFloor].holes) } Hole.prototype.pick = function (state) { var floor = state.floors[state.currentFloor] if (floor.holes.cells.length === 0) return if (state.mode === 'doors' || state.mode === 'windows' || state.mode === 'hand') { this._pick(floor.holes) } } },{}],12:[function(require,module,exports){ module.exports = Wall function Wall (regl) { if (!(this instanceof Wall)) return new Wall(regl) var drawOpts = { frag: ` precision highp float; #extension GL_OES_standard_derivatives: enable varying vec3 vpos; uniform float floorIndex, currentFloor; void main () { float current = floorIndex - currentFloor; vec3 N = normalize(cross(dFdx(vpos),dFdy(vpos))); float d = length(abs(N)-vec3(0,1,0)) * (1.0-step(0.99,mod(vpos.y,0.5))); if (d*current > 0.5) discard; gl_FragColor = vec4(N*0.5+0.5,1); } `, vert: ` precision highp float; uniform mat4 projection, view; uniform float floorIndex; attribute vec3 position; attribute vec2 wallCoord; varying vec3 vpos; varying vec2 vwall; void main () { vpos = position + vec3(0,floorIndex*0.5,0); vwall = wallCoord; gl_Position = projection * view * vec4(vpos,1); } `, uniforms: { floorIndex: regl.prop('floor') }, attributes: { position: regl.prop('positions'), wallCoord: regl.prop('wallCoords') }, elements: regl.prop('cells') } this._draw = regl(drawOpts) this._pick = regl(Object.assign({}, drawOpts, { frag: ` precision highp float; varying vec3 vpos; varying vec2 vwall; void main () { gl_FragColor = vec4(2,vwall,1); } `, blend: { enable: false } })) } Wall.prototype.draw = function (state) { var self = this var f = state.currentFloor for (var n = f; state.floors[n]; n++) show(n) for (var n = f-1; state.floors[n]; n--) show(n) function show (n) { var floor = state.floors[n] if (floor.mesh.cells.length > 0) self._draw(floor.mesh) } } Wall.prototype.pick = function (state) { var floor = state.floors[state.currentFloor] if (state.mode === 'doors' || state.mode === 'windows') { if (floor.mesh.cells.length > 0) { this._pick(floor.mesh) } } } },{}],13:[function(require,module,exports){ var mat4 = require('gl-mat4') var vec3 = require('gl-vec3') var m = new Float32Array(16) module.exports = function (state, emitter) { state.camera = { projection: new Float32Array(16), view: new Float32Array(16), distance: 3, theta: Math.PI/4, phi: 30/180*Math.PI, eye: Float32Array.from([+1,+1,+1]), center: Float32Array.from([0,0,0]), up: Float32Array.from([0,1,0]) } emitter.on('floor-set', function (n) { state.camera.center[1] = n*0.5 }) state.app.uniforms.projection = function (context) { var distance = state.camera.distance var aspect = context.viewportWidth/context.viewportHeight if (aspect > 1) { var dx = distance*0.5*aspect var dy = distance*0.5 } else { var dx = distance*0.5 var dy = distance*0.5/aspect } return mat4.ortho(state.camera.projection,-dx,+dx,-dy,+dy,0.1,1000.0) } state.app.uniforms.view = function () { var r = Math.exp(state.camera.distance) var theta = state.camera.theta var phi = Math.max(-Math.PI/2+0.001,Math.min(Math.PI/2-0.001, state.camera.phi)) state.camera.eye[0] = r*Math.cos(theta)*Math.cos(phi) state.camera.eye[1] = r*Math.sin(phi) state.camera.eye[2] = r*Math.sin(theta)*Math.cos(phi) state.camera.eye[0] += state.camera.center[0] state.camera.eye[1] += state.camera.center[1] state.camera.eye[2] += state.camera.center[2] return mat4.lookAt(state.camera.view, state.camera.eye, state.camera.center, state.camera.up) } emitter.on('mouse', function (ev) { if (state.mode === 'view' && (ev.buttons & 1) && ev.type === 'mousemove') { state.camera.theta += ev.movementX*0.01 state.camera.phi += ev.movementY*0.01 emitter.emit('frame') } }) } },{"gl-mat4":32,"gl-vec3":64}],14:[function(require,module,exports){ var normalize2 = require('gl-vec2/normalize') var length2 = require('gl-vec2/length') var calcNormals = require('polyline-normals') var earcut = require('earcut') var shapes = { door: [ -0.1, 0.8, +0.1, 0.8, +0.1, 0.01, -0.1, 0.01, -0.1, 0.8 ], window: [ -0.1, 0.7, +0.1, 0.7, +0.1, 0.3, -0.1, 0.3, -0.1, 0.7 ] } module.exports = function (state, emitter) { state.cursor = { visible: false, position: [0,0,0], active: -1, activeHole: [-1,0] } state.selected = { hover: [-1,0], dragStart: [-1,0,0], texture: null, data: new Float32Array(0) } emitter.on('floor-up', function () { updateFloor(state.currentFloor+1) }) emitter.on('floor-down', function () { updateFloor(state.currentFloor-1) }) function updateFloor (n) { state.currentFloor = n state.cursor.position[1] = state.currentFloor emitter.emit('floor-set', state.currentFloor) if (!state.floors[state.currentFloor]) { emitter.emit('create-floor', state.currentFloor) emitter.emit('build-floor', state.currentFloor) } emitter.emit('frame') } emitter.on('clear', function () { emitter.emit('remove-floor', 0) emitter.emit('create-floor', 0) state.cursor.active = -1 state.cursor.activeHole = [-1,0] emitter.emit('build-mesh') emitter.emit('frame') }) emitter.on('regl', function (regl) { state.selected.texture = regl.texture() }) emitter.on('mouse', function (ev) { if (state.mode === 'walls' || state.mode === 'doors' || state.mode === 'windows' || state.mode === 'hand') { emitter.emit('pick-event', ev) } }) emitter.on('pick', function (p) { if (state.mode === 'walls') { pickWalls(p) } else if (state.mode === 'doors') { pickDoors(p) } else if (state.mode === 'windows') { pickWindows(p) } else if (state.mode === 'hand') { pickHand(p) } }) function pickHand (p) { var floor = currentFloor() var lookup = floor.holes.visible.lookup if (p.data[0] === 2) { var shapeIx = Math.floor(p.data[1]) var holeIx = Math.floor(p.data[3]) if (!lookup[shapeIx]) lookup[shapeIx] = {} clear() lookup[shapeIx][holeIx] = 1 state.selected.hover[0] = shapeIx state.selected.hover[1] = holeIx if (p.event.type === 'mousedown') { state.selected.dragStart[0] = p.data[1] state.selected.dragStart[1] = p.data[2] state.selected.dragStart[2] = p.data[3] emitter.emit('build-hole-texture', state.currentFloor) } else if (shapeIx !== Math.floor(state.selected.dragStart[0])) { if (p.event.type === 'mouseup') { remove() } emitter.emit('build-hole-texture', state.currentFloor) } else if (p.event.buttons&1) { holeIx = state.selected.dragStart[2] var scale = wallScale(shapeIx) var hole = floor.shape[shapeIx].holes[holeIx] = floor.shape[shapeIx].shapes[holeIx].slice() for (var i = 0; i < hole.length; i+=2) { hole[i+0] = (p.data[1]%1.0) + hole[i+0]*scale } emitter.emit('build-mesh') } else { emitter.emit('build-hole-texture', state.currentFloor) } } else { if (p.event.type === 'mouseup' && state.selected.dragStart[0] >= 0) { remove() } clear() state.selected.hover[0] = -1 emitter.emit('build-hole-texture', state.currentFloor) } emitter.emit('frame') function clear () { var si = state.selected.hover[0] var hi = state.selected.hover[1] if (si >= 0 && lookup[si]) { lookup[si][hi] = 0 } } function remove () { var floor = currentFloor() var shapeIx = Math.floor(state.selected.dragStart[0]) var holeIx = Math.floor(state.selected.dragStart[2]) floor.shape[shapeIx].holes.splice(holeIx,1) floor.shape[shapeIx].shapes.splice(holeIx,1) emitter.emit('build-mesh') } } function pickWalls (p) { var floor = currentFloor() if (p.event.type === 'mousemove') { if (p.data[0] === 1) { state.cursor.visible = true state.cursor.position[0] = p.data[1] state.cursor.position[2] = p.data[2] } else { state.cursor.visible = false } if (state.cursor.active >= 0) { var k = state.cursor.active floor.footprint[k][0] = state.cursor.position[0]*2-1 floor.footprint[k][1] = state.cursor.position[2]*2-1 emitter.emit('build-mesh') } emitter.emit('frame') } else if (p.event.type === 'mousedown') { if (p.data[0] === 1 && state.cursor.active < 0) { state.cursor.active = floor.footprint.length+1 floor.footprint.push( [state.cursor.position[0]*2-1,state.cursor.position[2]*2-1], [state.cursor.position[0]*2-1,state.cursor.position[2]*2-1] ) floor.shape.push({ points: [ +0.0, +0.0, +0.0, +1.0, +1.0, +1.0, +1.0, +0.0, +0.0, +0.0 ], holes: [], shapes: [] }) emitter.emit('build-mesh') } else if (p.data[0] === 1 && state.cursor.active >= 0) { state.cursor.active = -1 } emitter.emit('frame') } } function pickShape (p, holeShape) { var floor = currentFloor() if (p.data[0] === 2) { var shapeIx = Math.floor(p.data[1]) var shape = floor.shape[shapeIx] var scale = wallScale(shapeIx) var w = 0.08*scale var x = clamp(w*1.5,1.0-w*1.5,p.data[1]%1) var y = p.data[2] var holeIx = shape.holes.length if (state.cursor.activeHole[0] === shapeIx) { holeIx = state.cursor.activeHole[1] } else { clearPrevious() } var hole = holeShape.slice() for (var i = 0; i < hole.length; i+=2) { hole[i+0] = x + hole[i+0]*scale } if (p.event.type === 'mousedown') { clearPrevious() shape.holes.push(hole) shape.shapes.push(holeShape) } else { state.cursor.activeHole[0] = shapeIx state.cursor.activeHole[1] = holeIx shape.holes[holeIx] = hole shape.shapes[holeIx] = holeShape } emitter.emit('build-mesh') emitter.emit('frame') } else { clearPrevious() emitter.emit('build-mesh') emitter.emit('frame') } } function pickDoors (p) { pickShape(p,shapes.door) } function pickWindows (p) { pickShape(p,shapes.window) } function clearPrevious () { var floor = currentFloor() if (state.cursor.activeHole[0] >= 0) { floor.shape[state.cursor.activeHole[0]].holes .splice(state.cursor.activeHole[1],1) state.cursor.activeHole[0] = -1 } } function wallScale (ix) { var floor = currentFloor() var p0 = floor.footprint[ix*2+0] var p1 = floor.footprint[ix*2+1] var dx = p0[0]-p1[0] var dy = p0[1]-p1[1] return 1.0 / Math.sqrt(dx*dx+dy*dy) } function currentFloor () { return state.floors[state.currentFloor] } } function clamp (a, b, x) { return Math.max(a,Math.min(b,x)) } },{"earcut":22,"gl-vec2/length":49,"gl-vec2/normalize":50,"polyline-normals":102}],15:[function(require,module,exports){ var calcNormals = require('polyline-normals') var earcut = require('earcut') module.exports = function (state, emitter) { state.floors = {} state.currentFloor = 0 state.app.uniforms.currentFloor = function () { return state.currentFloor } createFloor(0) emitter.on('create-floor', createFloor) function createFloor (n) { state.floors[n] = { footprint: [], shape: [], mesh: { positions: [], wallCoords: [], cells: [], floor: n }, holes: { positions: [], wallCoords: [], cells: [], visible: { texture: null, data: new Float32Array(0), rows: [], lookup: {}, size: [0,0] }, floor: n } } if (state.app.regl) { state.floors[n].holes.visible.texture = state.app.regl.texture() } } emitter.on('remove-floor', function (n) { delete state.floors[n] }) emitter.on('regl', function (regl) { Object.keys(state.floors).forEach(function (n) { state.floors[n].holes.visible.texture = regl.texture() }) }) emitter.on('build-mesh', function () { Object.keys(state.floors).forEach(function (n) { emitter.emit('build-floor', n) }) }) emitter.on('build-floor', function (floorIndex) { var floor = state.floors[floorIndex] var footprint = floor.footprint var pts = {}, pkeys = [] for (var i = 0; i < footprint.length; i++) { var str = footprint[i].join(',') pkeys.push(str) if (pts[str]) pts[str].push(i) else pts[str] = [i] } var groups = {}, gid = 0 var polylines = [] var shapeIndex = [] for (var n = 0; n < footprint.length; n++) { var labeled = 0 ;(function visit (i,gid) { var j = i+(i%2 ?-1:+1) if (groups[i] !== undefined && groups[j] !== undefined) return var pt0 = footprint[i] var str0 = pt0.join(',') var pt1 = footprint[j] var str1 = pt1.join(',') if (groups[i] === undefined) { groups[i] = gid if (!polylines[gid]) { polylines[gid] = [pt0] shapeIndex[gid] = [Math.floor(i/2)] } else { polylines[gid].push(pt0) shapeIndex[gid].push(Math.floor(i/2)) } labeled++ } if (groups[j] === undefined) { groups[j] = gid if (!polylines[gid]) { polylines[gid] = [pt1] shapeIndex[gid] = [Math.floor(i/2)] } else { polylines[gid].push(pt1) shapeIndex[gid].push(Math.floor(i/2)) } labeled++ } for (var k = 0; k < pts[str1].length; k++) { visit(pts[str1][k],gid) } for (var k = 0; k < pts[str0].length; k++) { visit(pts[str0][k],gid) } })(n,gid) if (labeled > 0) gid++ } // deduplicate var closed = [] for (var i = 0; i < polylines.length; i++) { closed.push(cmp(polylines[i][0],polylines[i][polylines[i].length-1])) for (var j = 0; j < polylines[i].length; j++) { var p0 = polylines[i][j] var p1 = polylines[i][(j+1)%polylines[i].length] if (cmp(p0,p1)) { polylines[i].splice(j,1) shapeIndex[i].splice(j,1) j-- } } } var mesh = floor.mesh mesh.positions = [] mesh.wallCoords = [] mesh.cells = [] var hmesh = floor.holes hmesh.positions = [] hmesh.wallCoords = [] hmesh.cells = [] var rows = floor.holes.visible.rows var lookup = floor.holes.visible.lookup var h = 0.5, w = 1.0/64 var N = [0,0] for (var i = 0; i < polylines.length; i++) { if (polylines[i].length <= 1) continue var normals = calcNormals(polylines[i],closed[i]) if (closed[i]) polylines[i].push(polylines[i][0]) for (var j = 0; j < polylines[i].length-1; j++) { var nx0 = normals[j%normals.length] var N0 = [nx0[0][0]*nx0[1],nx0[0][1]*nx0[1]] var nx1 = normals[(j+1)%normals.length] var N1 = [nx1[0][0]*nx1[1],nx1[0][1]*nx1[1]] var p0 = polylines[i][j] var p1 = polylines[i][(j+1)%polylines[i].length] var nm = mesh.positions.length var nh = hmesh.positions.length var shapeIx = shapeIndex[i][j] var wall = floor.shape[shapeIx] if (!wall) continue var row = rows[shapeIx] = [] for (var holeIx = 0; holeIx < wall.holes.length; holeIx++) { row.push(lookup[shapeIx] ? lookup[shapeIx][holeIx] || 0 : 0) } var wallpts = wall.points.concat.apply(wall.points,wall.holes) var holepts = [].concat.apply([],wall.holes) for (var sign = -1; sign <= +1; sign += 2) { for (var k = 0; k < wallpts.length; k+=2) { var isHole = k < wallpts.length - holepts.length var wx = wallpts[k+0] var x = mix(p0[0],p1[0],wx) var y = wallpts[k+1] var z = mix(p0[1],p1[1],wx) if (isHole) { var Nx = mix(N0[0],N1[0],wx)*-sign var Ny = mix(N0[1],N1[1],wx)*-sign } else { var Nx = p1[1]-p0[1] var Ny = p0[0]-p1[0] Nx /= Math.sqrt(Nx*Nx+Ny*Ny)*sign Ny /= Math.sqrt(Nx*Nx+Ny*Ny)*sign } mesh.positions.push([x+Nx*w,y*h,z+Ny*w]) mesh.wallCoords.push([wx+shapeIx,y]) } //for (var k = 0; k < holepts.length; k+=2) { for (var holeIx = 0; holeIx < wall.holes.length; holeIx++) { for (var k = 0; k < wall.holes[holeIx].length; k+=2) { var wx = wall.holes[holeIx][k+0] var x = mix(p0[0],p1[0],wx) var y = wall.holes[holeIx][k+1] var z = mix(p0[1],p1[1],wx) var Nx = p1[1]-p0[1] var Ny = p0[0]-p1[0] Nx /= Math.sqrt(Nx*Nx+Ny*Ny)*sign Ny /= Math.sqrt(Nx*Nx+Ny*Ny)*sign hmesh.positions.push([x+Nx*w,y*h,z+Ny*w]) hmesh.wallCoords.push([wx+shapeIx,y,holeIx]) } } } var z = wallpts.length/2 for (var k = 0; k < (wallpts.length-holepts.length)/2-1; k++) { mesh.cells.push( [nm+k,nm+k+z,nm+k+1], [nm+k+1,nm+k+z,nm+k+z+1] ) } var q = k+1 for (var k = 0; k < wall.holes.length; k++) { for (var m = 0; m < wall.holes[k].length-2; m+=2) { mesh.cells.push( [nm+q,nm+q+z,nm+q+1], [nm+q+1,nm+q+z,nm+q+z+1] ) q++ } q++ } var holes = [], hix = wall.points.length/2 for (var k = 0; k < wall.holes.length; k++) { holes.push(hix) hix += wall.holes[k].length/2 } var wcells = earcut(wallpts,holes) for (var k = 0; k < wcells.length; k+=3) { mesh.cells.push( [nm+wcells[k+0]+0,nm+wcells[k+1]+0,nm+wcells[k+2]+0], [nm+wcells[k+0]+z,nm+wcells[k+1]+z,nm+wcells[k+2]+z] ) } q = 0 z = holepts.length/2 for (var k = 0; k < wall.holes.length; k++) { var hcells = earcut(wall.holes[k],[]) for (var m = 0; m < hcells.length; m+=3) { hmesh.cells.push( [nh+q+hcells[m+0]+0,nh+q+hcells[m+1]+0,nh+q+hcells[m+2]+0], [nh+q+hcells[m+0]+z,nh+q+hcells[m+1]+z,nh+q+hcells[m+2]+z] ) } q += wall.holes[k].length/2 } } } emitter.emit('build-hole-texture', floorIndex) }) emitter.on('build-hole-texture', function (floorIndex) { var floor = state.floors[floorIndex] var ht = floor.holes.visible if (!ht.texture) return ht.size[1] = ht.rows.length for (var i = 0; i < ht.rows.length; i++) { ht.size[0] = Math.max(ht.size[0], ht.rows[i].length) } if (ht.data.length !== ht.size[0] * ht.size[1]) { ht.data = new Float32Array(ht.size[0] * ht.size[1]) } if (ht.size[0] * ht.size[1] === 0) return for (var y = 0; y < ht.rows.length; y++) { for (var x = 0; x < ht.rows[y].length; x++) { ht.rows[y][x] = ht.lookup[y] ? ht.lookup[y][x] || 0 : 0 } } for (var y = 0; y < ht.size[1]; y++) { for (var x = 0; x < ht.size[0]; x++) { ht.data[x+y*ht.size[0]] = ht.rows[y][x] || 0 } } ht.texture({ data: ht.data, format: 'alpha', // 1 channel type: 'float', width: ht.size[0], height: ht.size[1] }) }) } function cmp (a, b) { return a && b && a.length === b.length && a[0] === b[0] && a[1] === b[1] } function mix (a, b, x) { x = Math.max(-1.0,Math.min(+1.0,x)) return a*(1.0-x) + b*x } },{"earcut":22,"polyline-normals":102}],16:[function(require,module,exports){ var trailingNewlineRegex = /\n[\s]+$/ var leadingNewlineRegex = /^\n[\s]+/ var trailingSpaceRegex = /[\s]+$/ var leadingSpaceRegex = /^[\s]+/ var multiSpaceRegex = /[\n\s]+/g var TEXT_TAGS = [ 'a', 'abbr', 'b', 'bdi', 'bdo', 'br', 'cite', 'data', 'dfn', 'em', 'i', 'kbd', 'mark', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'amp', 'small', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr' ] var VERBATIM_TAGS = [ 'code', 'pre', 'textarea' ] module.exports = function appendChild (el, childs) { if (!Array.isArray(childs)) return var nodeName = el.nodeName.toLowerCase() var hadText = false var value, leader for (var i = 0, len = childs.length; i < len; i++) { var node = childs[i] if (Array.isArray(node)) { appendChild(el, node) continue } if (typeof node === 'number' || typeof node === 'boolean' || typeof node === 'function' || node instanceof Date || node instanceof RegExp) { node = node.toString() } var lastChild = el.childNodes[el.childNodes.length - 1] // Iterate over text nodes if (typeof node === 'string') { hadText = true // If we already had text, append to the existing text if (lastChild && lastChild.nodeName === '#text') { lastChild.nodeValue += node // We didn't have a text node yet, create one } else { node = document.createTextNode(node) el.appendChild(node) lastChild = node } // If this is the last of the child nodes, make sure we close it out // right if (i === len - 1) { hadText = false // Trim the child text nodes if the current node isn't a // node where whitespace matters. if (TEXT_TAGS.indexOf(nodeName) === -1 && VERBATIM_TAGS.indexOf(nodeName) === -1) { value = lastChild.nodeValue .replace(leadingNewlineRegex, '') .replace(trailingSpaceRegex, '') .replace(trailingNewlineRegex, '') .replace(multiSpaceRegex, ' ') if (value === '') { el.removeChild(lastChild) } else { lastChild.nodeValue = value } } else if (VERBATIM_TAGS.indexOf(nodeName) === -1) { // The very first node in the list should not have leading // whitespace. Sibling text nodes should have whitespace if there // was any. leader = i === 0 ? '' : ' ' value = lastChild.nodeValue .replace(leadingNewlineRegex, leader) .replace(leadingSpaceRegex, ' ') .replace(trailingSpaceRegex, '') .replace(trailingNewlineRegex, '') .replace(multiSpaceRegex, ' ') lastChild.nodeValue = value } } // Iterate over DOM nodes } else if (node && node.nodeType) { // If the last node was a text node, make sure it is properly closed out if (hadText) { hadText = false // Trim the child text nodes if the current node isn't a // text node or a code node if (TEXT_TAGS.indexOf(nodeName) === -1 && VERBATIM_TAGS.indexOf(nodeName) === -1) { value = lastChild.nodeValue .replace(leadingNewlineRegex, '') .replace(trailingNewlineRegex, '') .replace(multiSpaceRegex, ' ') // Remove empty text nodes, append otherwise if (value === '') { el.removeChild(lastChild) } else { lastChild.nodeValue = value } // Trim the child nodes if the current node is not a node // where all whitespace must be preserved } else if (VERBATIM_TAGS.indexOf(nodeName) === -1) { value = lastChild.nodeValue .replace(leadingSpaceRegex, ' ') .replace(leadingNewlineRegex, '') .replace(trailingNewlineRegex, '') .replace(multiSpaceRegex, ' ') lastChild.nodeValue = value } } // Store the last nodename var _nodeName = node.nodeName if (_nodeName) nodeName = _nodeName.toLowerCase() // Append the node to the DOM el.appendChild(node) } } } },{}],17:[function(require,module,exports){ var hyperx = require('hyperx') var appendChild = require('./appendChild') var SVGNS = 'http://www.w3.org/2000/svg' var XLINKNS = 'http://www.w3.org/1999/xlink' var BOOL_PROPS = [ 'autofocus', 'checked', 'defaultchecked', 'disabled', 'formnovalidate', 'indeterminate', 'readonly', 'required', 'selected', 'willvalidate' ] var COMMENT_TAG = '!--' var SVG_TAGS = [ 'svg', 'altGlyph', 'altGlyphDef', 'altGlyphItem', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle', 'clipPath', 'color-profile', 'cursor', 'defs', 'desc', 'ellipse', 'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence', 'filter', 'font', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignObject', 'g', 'glyph', 'glyphRef', 'hkern', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'missing-glyph', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'set', 'stop', 'switch', 'symbol', 'text', 'textPath', 'title', 'tref', 'tspan', 'use', 'view', 'vkern' ] function belCreateElement (tag, props, children) { var el // If an svg tag, it needs a namespace if (SVG_TAGS.indexOf(tag) !== -1) { props.namespace = SVGNS } // If we are using a namespace var ns = false if (props.namespace) { ns = props.namespace delete props.namespace } // Create the element if (ns) { el = document.createElementNS(ns, tag) } else if (tag === COMMENT_TAG) { return document.createComment(props.comment) } else { el = document.createElement(tag) } // Create the properties for (var p in props) { if (props.hasOwnProperty(p)) { var key = p.toLowerCase() var val = props[p] // Normalize className if (key === 'classname') { key = 'class' p = 'class' } // The for attribute gets transformed to htmlFor, but we just set as for if (p === 'htmlFor') { p = 'for' } // If a property is boolean, set itself to the key if (BOOL_PROPS.indexOf(key) !== -1) { if (val === 'true') val = key else if (val === 'false') continue } // If a property prefers being set directly vs setAttribute if (key.slice(0, 2) === 'on') { el[p] = val } else { if (ns) { if (p === 'xlink:href') { el.setAttributeNS(XLINKNS, p, val) } else if (/^xmlns($|:)/i.test(p)) { // skip xmlns definitions } else { el.setAttributeNS(null, p, val) } } else { el.setAttribute(p, val) } } } } appendChild(el, children) return el } module.exports = hyperx(belCreateElement, {comments: true}) module.exports.default = module.exports module.exports.createElement = belCreateElement },{"./appendChild":16,"hyperx":88}],18:[function(require,module,exports){ module.exports = require('bel') },{"bel":17}],19:[function(require,module,exports){ var scrollToAnchor = require('scroll-to-anchor') var documentReady = require('document-ready') var nanolocation = require('nanolocation') var nanotiming = require('nanotiming') var nanorouter = require('nanorouter') var nanomorph = require('nanomorph') var nanoquery = require('nanoquery') var nanohref = require('nanohref') var nanoraf = require('nanoraf') var nanobus = require('nanobus') var assert = require('assert') var xtend = require('xtend') module.exports = Choo var HISTORY_OBJECT = {} function Choo (opts) { if (!(this instanceof Choo)) return new Choo(opts) opts = opts || {} assert.equal(typeof opts, 'object', 'choo: opts should be type object') var self = this // define events used by choo this._events = { DOMCONTENTLOADED: 'DOMContentLoaded', DOMTITLECHANGE: 'DOMTitleChange', REPLACESTATE: 'replaceState', PUSHSTATE: 'pushState', NAVIGATE: 'navigate', POPSTATE: 'popState', RENDER: 'render' } // properties for internal use only this._historyEnabled = opts.history === undefined ? true : opts.history this._hrefEnabled = opts.href === undefined ? true : opts.href this._hasWindow = typeof window !== 'undefined' this._createLocation = nanolocation this._loaded = false this._tree = null // properties that are part of the API this.router = nanorouter() this.emitter = nanobus('choo.emit') this.emit = this.emitter.emit.bind(this.emitter) var events = { events: this._events } if (this._hasWindow) { this.state = window.initialState ? xtend(window.initialState, events) : events delete window.initialState } else { this.state = events } // listen for title changes; available even when calling .toString() if (this._hasWindow) this.state.title = document.title this.emitter.prependListener(this._events.DOMTITLECHANGE, function (title) { assert.equal(typeof title, 'string', 'events.DOMTitleChange: title should be type string') self.state.title = title if (self._hasWindow) document.title = title }) } Choo.prototype.route = function (route, handler) { assert.equal(typeof route, 'string', 'choo.route: route should be type string') assert.equal(typeof handler, 'function', 'choo.handler: route should be type function') this.router.on(route, handler) } Choo.prototype.use = function (cb) { assert.equal(typeof cb, 'function', 'choo.use: cb should be type function') var msg = 'choo.use' msg = cb.storeName ? msg + '(' + cb.storeName + ')' : msg var endTiming = nanotiming(msg) cb(this.state, this.emitter, this) endTiming() } Choo.prototype.start = function () { assert.equal(typeof window, 'object', 'choo.start: window was not found. .start() must be called in a browser, use .toString() if running in Node') var self = this if (this._historyEnabled) { this.emitter.prependListener(this._events.NAVIGATE, function () { self._matchRoute() if (self._loaded) { self.emitter.emit(self._events.RENDER) setTimeout(scrollToAnchor.bind(null, window.location.hash), 0) } }) this.emitter.prependListener(this._events.POPSTATE, function () { self.emitter.emit(self._events.NAVIGATE) }) this.emitter.prependListener(this._events.PUSHSTATE, function (href) { assert.equal(typeof href, 'string', 'events.pushState: href should be type string') window.history.pushState(HISTORY_OBJECT, null, href) self.emitter.emit(self._events.NAVIGATE) }) this.emitter.prependListener(this._events.REPLACESTATE, function (href) { assert.equal(typeof href, 'string', 'events.replaceState: href should be type string') window.history.replaceState(HISTORY_OBJECT, null, href) self.emitter.emit(self._events.NAVIGATE) }) window.onpopstate = function () { self.emitter.emit(self._events.POPSTATE) } if (self._hrefEnabled) { nanohref(function (location) { var href = location.href var currHref = window.location.href if (href === currHref) return self.emitter.emit(self._events.PUSHSTATE, href) }) } } this._matchRoute() this._tree = this._prerender(this.state) assert.ok(this._tree, 'choo.start: no valid DOM node returned for location ' + this.state.href) this.emitter.prependListener(self._events.RENDER, nanoraf(function () { var renderTiming = nanotiming('choo.render') var newTree = self._prerender(self.state) assert.ok(newTree, 'choo.render: no valid DOM node returned for location ' + self.state.href) assert.equal(self._tree.nodeName, newTree.nodeName, 'choo.render: The target node <' + self._tree.nodeName.toLowerCase() + '> is not the same type as the new node <' + newTree.nodeName.toLowerCase() + '>.') var morphTiming = nanotiming('choo.morph') nanomorph(self._tree, newTree) morphTiming() renderTiming() })) documentReady(function () { self.emitter.emit(self._events.DOMCONTENTLOADED) self._loaded = true }) return this._tree } Choo.prototype.mount = function mount (selector) { if (typeof window !== 'object') { assert.ok(typeof selector === 'string', 'choo.mount: selector should be type String') this.selector = selector return this } assert.ok(typeof selector === 'string' || typeof selector === 'object', 'choo.mount: selector should be type String or HTMLElement') var self = this documentReady(function () { var renderTiming = nanotiming('choo.render') var newTree = self.start() if (typeof selector === 'string') { self._tree = document.querySelector(selector) } else { self._tree = selector } assert.ok(self._tree, 'choo.mount: could not query selector: ' + selector) assert.equal(self._tree.nodeName, newTree.nodeName, 'choo.mount: The target node <' + self._tree.nodeName.toLowerCase() + '> is not the same type as the new node <' + newTree.nodeName.toLowerCase() + '>.') var morphTiming = nanotiming('choo.morph') nanomorph(self._tree, newTree) morphTiming() renderTiming() }) } Choo.prototype.toString = function (location, state) { this.state = xtend(this.state, state || {}) assert.notEqual(typeof window, 'object', 'choo.mount: window was found. .toString() must be called in Node, use .start() or .mount() if running in the browser') assert.equal(typeof location, 'string', 'choo.toString: location should be type string') assert.equal(typeof this.state, 'object', 'choo.toString: state should be type object') this._matchRoute(location) var html = this._prerender(this.state) assert.ok(html, 'choo.toString: no valid value returned for the route ' + location) return html.toString() } Choo.prototype._matchRoute = function (locationOverride) { var location, queryString if (locationOverride) { location = locationOverride.replace(/\?.+$/, '') queryString = locationOverride } else { location = this._createLocation() queryString = window.location.search } var matched = this.router.match(location) this.state.href = location this.state.query = nanoquery(queryString) this.state.route = matched.route this.state.params = matched.params this.state._handler = matched.cb return this.state } Choo.prototype._prerender = function (state) { var routeTiming = nanotiming("choo.prerender('" + state.route + "')") var res = state._handler(state, this.emit) routeTiming() return res } },{"assert":1,"document-ready":20,"nanobus":90,"nanohref":91,"nanolocation":92,"nanomorph":93,"nanoquery":96,"nanoraf":97,"nanorouter":98,"nanotiming":100,"scroll-to-anchor":106,"xtend":109}],20:[function(require,module,exports){ 'use strict' var assert = require('assert') module.exports = ready function ready (callback) { assert.notEqual(typeof document, 'undefined', 'document-ready only runs in the browser') var state = document.readyState if (state === 'complete' || state === 'interactive') { return setTimeout(callback, 0) } document.addEventListener('DOMContentLoaded', function onLoad () { callback() }) } },{"assert":1}],21:[function(require,module,exports){ "use strict" function dupe_array(count, value, i) { var c = count[i]|0 if(c <= 0) { return [] } var result = new Array(c), j if(i === count.length-1) { for(j=0; j 0) { return dupe_number(count|0, value) } break case "object": if(typeof (count.length) === "number") { return dupe_array(count, value, 0) } break } return [] } module.exports = dupe },{}],22:[function(require,module,exports){ 'use strict'; module.exports = earcut; module.exports.default = earcut; function earcut(data, holeIndices, dim) { dim = dim || 2; var hasHoles = holeIndices && holeIndices.length, outerLen = hasHoles ? holeIndices[0] * dim : data.length, outerNode = linkedList(data, 0, outerLen, dim, true), triangles = []; if (!outerNode) return triangles; var minX, minY, maxX, maxY, x, y, invSize; if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox if (data.length > 80 * dim) { minX = maxX = data[0]; minY = maxY = data[1]; for (var i = dim; i < outerLen; i += dim) { x = data[i]; y = data[i + 1]; if (x < minX) minX = x; if (y < minY) minY = y; if (x > maxX) maxX = x; if (y > maxY) maxY = y; } // minX, minY and invSize are later used to transform coords into integers for z-order calculation invSize = Math.max(maxX - minX, maxY - minY); invSize = invSize !== 0 ? 1 / invSize : 0; } earcutLinked(outerNode, triangles, dim, minX, minY, invSize); return triangles; } // create a circular doubly linked list from polygon points in the specified winding order function linkedList(data, start, end, dim, clockwise) { var i, last; if (clockwise === (signedArea(data, start, end, dim) > 0)) { for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); } else { for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); } if (last && equals(last, last.next)) { removeNode(last); last = last.next; } return last; } // eliminate colinear or duplicate points function filterPoints(start, end) { if (!start) return start; if (!end) end = start; var p = start, again; do { again = false; if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { removeNode(p); p = end = p.prev; if (p === p.next) break; again = true; } else { p = p.next; } } while (again || p !== end); return end; } // main ear slicing loop which triangulates a polygon (given as a linked list) function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) { if (!ear) return; // interlink polygon nodes in z-order if (!pass && invSize) indexCurve(ear, minX, minY, invSize); var stop = ear, prev, next; // iterate through ears, slicing them one by one while (ear.prev !== ear.next) { prev = ear.prev; next = ear.next; if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) { // cut off the triangle triangles.push(prev.i / dim); triangles.push(ear.i / dim); triangles.push(next.i / dim); removeNode(ear); // skipping the next vertice leads to less sliver triangles ear = next.next; stop = next.next; continue; } ear = next; // if we looped through the whole remaining polygon and can't find any more ears if (ear === stop) { // try filtering points and slicing again if (!pass) { earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1); // if this didn't work, try curing all small self-intersections locally } else if (pass === 1) { ear = cureLocalIntersections(ear, triangles, dim); earcutLinked(ear, triangles, dim, minX, minY, invSize, 2); // as a last resort, try splitting the remaining polygon into two } else if (pass === 2) { splitEarcut(ear, triangles, dim, minX, minY, invSize); } break; } } } // check whether a polygon node forms a valid ear with adjacent nodes function isEar(ear) { var a = ear.prev, b = ear, c = ear.next; if (area(a, b, c) >= 0) return false; // reflex, can't be an ear // now make sure we don't have other points inside the potential ear var p = ear.next.next; while (p !== ear.prev) { if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false; p = p.next; } return true; } function isEarHashed(ear, minX, minY, invSize) { var a = ear.prev, b = ear, c = ear.next; if (area(a, b, c) >= 0) return false; // reflex, can't be an ear // triangle bbox; min & max are calculated like this for speed var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); // z-order range for the current triangle bbox; var minZ = zOrder(minTX, minTY, minX, minY, invSize), maxZ = zOrder(maxTX, maxTY, minX, minY, invSize); var p = ear.prevZ, n = ear.nextZ; // look for points inside the triangle in both directions while (p && p.z >= minZ && n && n.z <= maxZ) { if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false; p = p.prevZ; if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false; n = n.nextZ; } // look for remaining points in decreasing z-order while (p && p.z >= minZ) { if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false; p = p.prevZ; } // look for remaining points in increasing z-order while (n && n.z <= maxZ) { if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false; n = n.nextZ; } return true; } // go through all polygon nodes and cure small local self-intersections function cureLocalIntersections(start, triangles, dim) { var p = start; do { var a = p.prev, b = p.next.next; if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { triangles.push(a.i / dim); triangles.push(p.i / dim); triangles.push(b.i / dim); // remove two nodes involved removeNode(p); removeNode(p.next); p = start = b; } p = p.next; } while (p !== start); return p; } // try splitting polygon into two and triangulate them independently function splitEarcut(start, triangles, dim, minX, minY, invSize) { // look for a valid diagonal that divides the polygon into two var a = start; do { var b = a.next.next; while (b !== a.prev) { if (a.i !== b.i && isValidDiagonal(a, b)) { // split the polygon in two by the diagonal var c = splitPolygon(a, b); // filter colinear points around the cuts a = filterPoints(a, a.next); c = filterPoints(c, c.next); // run earcut on each half earcutLinked(a, triangles, dim, minX, minY, invSize); earcutLinked(c, triangles, dim, minX, minY, invSize); return; } b = b.next; } a = a.next; } while (a !== start); } // link every hole into the outer loop, producing a single-ring polygon without holes function eliminateHoles(data, holeIndices, outerNode, dim) { var queue = [], i, len, start, end, list; for (i = 0, len = holeIndices.length; i < len; i++) { start = holeIndices[i] * dim; end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; list = linkedList(data, start, end, dim, false); if (list === list.next) list.steiner = true; queue.push(getLeftmost(list)); } queue.sort(compareX); // process holes from left to right for (i = 0; i < queue.length; i++) { eliminateHole(queue[i], outerNode); outerNode = filterPoints(outerNode, outerNode.next); } return outerNode; } function compareX(a, b) { return a.x - b.x; } // find a bridge between vertices that connects hole with an outer ring and and link it function eliminateHole(hole, outerNode) { outerNode = findHoleBridge(hole, outerNode); if (outerNode) { var b = splitPolygon(outerNode, hole); filterPoints(b, b.next); } } // David Eberly's algorithm for finding a bridge between hole and outer polygon function findHoleBridge(hole, outerNode) { var p = outerNode, hx = hole.x, hy = hole.y, qx = -Infinity, m; // find a segment intersected by a ray from the hole's leftmost point to the left; // segment's endpoint with lesser x will be potential connection point do { if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) { var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); if (x <= hx && x > qx) { qx = x; if (x === hx) { if (hy === p.y) return p; if (hy === p.next.y) return p.next; } m = p.x < p.next.x ? p : p.next; } } p = p.next; } while (p !== outerNode); if (!m) return null; if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint // look for points inside the triangle of hole point, segment intersection and endpoint; // if there are no points found, we have a valid connection; // otherwise choose the point of the minimum angle with the ray as connection point var stop = m, mx = m.x, my = m.y, tanMin = Infinity, tan; p = m.next; while (p !== stop) { if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { tan = Math.abs(hy - p.y) / (hx - p.x); // tangential if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { m = p; tanMin = tan; } } p = p.next; } return m; } // interlink polygon nodes in z-order function indexCurve(start, minX, minY, invSize) { var p = start; do { if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize); p.prevZ = p.prev; p.nextZ = p.next; p = p.next; } while (p !== start); p.prevZ.nextZ = null; p.prevZ = null; sortLinked(p); } // Simon Tatham's linked list merge sort algorithm // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html function sortLinked(list) { var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1; do { p = list; list = null; tail = null; numMerges = 0; while (p) { numMerges++; q = p; pSize = 0; for (i = 0; i < inSize; i++) { pSize++; q = q.nextZ; if (!q) break; } qSize = inSize; while (pSize > 0 || (qSize > 0 && q)) { if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) { e = p; p = p.nextZ; pSize--; } else { e = q; q = q.nextZ; qSize--; } if (tail) tail.nextZ = e; else list = e; e.prevZ = tail; tail = e; } p = q; } tail.nextZ = null; inSize *= 2; } while (numMerges > 1); return list; } // z-order of a point given coords and inverse of the longer side of data bbox function zOrder(x, y, minX, minY, invSize) { // coords are transformed into non-negative 15-bit integer range x = 32767 * (x - minX) * invSize; y = 32767 * (y - minY) * invSize; x = (x | (x << 8)) & 0x00FF00FF; x = (x | (x << 4)) & 0x0F0F0F0F; x = (x | (x << 2)) & 0x33333333; x = (x | (x << 1)) & 0x55555555; y = (y | (y << 8)) & 0x00FF00FF; y = (y | (y << 4)) & 0x0F0F0F0F; y = (y | (y << 2)) & 0x33333333; y = (y | (y << 1)) & 0x55555555; return x | (y << 1); } // find the leftmost node of a polygon ring function getLeftmost(start) { var p = start, leftmost = start; do { if (p.x < leftmost.x) leftmost = p; p = p.next; } while (p !== start); return leftmost; } // check if a point lies within a convex triangle function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; } // check if a diagonal between two polygon nodes is valid (lies in polygon interior) function isValidDiagonal(a, b) { return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); } // signed area of a triangle function area(p, q, r) { return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); } // check if two points are equal function equals(p1, p2) { return p1.x === p2.x && p1.y === p2.y; } // check if two segments intersect function intersects(p1, q1, p2, q2) { if ((equals(p1, q1) && equals(p2, q2)) || (equals(p1, q2) && equals(p2, q1))) return true; return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; } // check if a polygon diagonal intersects any polygon segments function intersectsPolygon(a, b) { var p = a; do { if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b)) return true; p = p.next; } while (p !== a); return false; } // check if a polygon diagonal is locally inside the polygon function locallyInside(a, b) { return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; } // check if the middle point of a polygon diagonal is inside the polygon function middleInside(a, b) { var p = a, inside = false, px = (a.x + b.x) / 2, py = (a.y + b.y) / 2; do { if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) inside = !inside; p = p.next; } while (p !== a); return inside; } // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; // if one belongs to the outer ring and another to a hole, it merges it into a single ring function splitPolygon(a, b) { var a2 = new Node(a.i, a.x, a.y), b2 = new Node(b.i, b.x, b.y), an = a.next, bp = b.prev; a.next = b; b.prev = a; a2.next = an; an.prev = a2; b2.next = a2; a2.prev = b2; bp.next = b2; b2.prev = bp; return b2; } // create a node and optionally link it with previous one (in a circular doubly linked list) function insertNode(i, x, y, last) { var p = new Node(i, x, y); if (!last) { p.prev = p; p.next = p; } else { p.next = last.next; p.prev = last; last.next.prev = p; last.next = p; } return p; } function removeNode(p) { p.next.prev = p.prev; p.prev.next = p.next; if (p.prevZ) p.prevZ.nextZ = p.nextZ; if (p.nextZ) p.nextZ.prevZ = p.prevZ; } function Node(i, x, y) { // vertice index in coordinates array this.i = i; // vertex coordinates this.x = x; this.y = y; // previous and next vertice nodes in a polygon ring this.prev = null; this.next = null; // z-order curve value this.z = null; // previous and next nodes in z-order this.prevZ = null; this.nextZ = null; // indicates whether this is a steiner point this.steiner = false; } // return a percentage difference between the polygon area and its triangulation area; // used to verify correctness of triangulation earcut.deviation = function (data, holeIndices, dim, triangles) { var hasHoles = holeIndices && holeIndices.length; var outerLen = hasHoles ? holeIndices[0] * dim : data.length; var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim)); if (hasHoles) { for (var i = 0, len = holeIndices.length; i < len; i++) { var start = holeIndices[i] * dim; var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; polygonArea -= Math.abs(signedArea(data, start, end, dim)); } } var trianglesArea = 0; for (i = 0; i < triangles.length; i += 3) { var a = triangles[i] * dim; var b = triangles[i + 1] * dim; var c = triangles[i + 2] * dim; trianglesArea += Math.abs( (data[a] - data[c]) * (data[b + 1] - data[a + 1]) - (data[a] - data[b]) * (data[c + 1] - data[a + 1])); } return polygonArea === 0 && trianglesArea === 0 ? 0 : Math.abs((trianglesArea - polygonArea) / polygonArea); }; function signedArea(data, start, end, dim) { var sum = 0; for (var i = start, j = end - dim; i < end; i += dim) { sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); j = i; } return sum; } // turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts earcut.flatten = function (data) { var dim = data[0][0].length, result = {vertices: [], holes: [], dimensions: dim}, holeIndex = 0; for (var i = 0; i < data.length; i++) { for (var j = 0; j < data[i].length; j++) { for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]); } if (i > 0) { holeIndex += data[i - 1].length; result.holes.push(holeIndex); } } return result; }; },{}],23:[function(require,module,exports){ module.exports = adjoint; /** * Calculates the adjugate of a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ function adjoint(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); return out; }; },{}],24:[function(require,module,exports){ module.exports = clone; /** * Creates a new mat4 initialized with values from an existing matrix * * @param {mat4} a matrix to clone * @returns {mat4} a new 4x4 matrix */ function clone(a) { var out = new Float32Array(16); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; },{}],25:[function(require,module,exports){ module.exports = copy; /** * Copy the values from one mat4 to another * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ function copy(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; },{}],26:[function(require,module,exports){ module.exports = create; /** * Creates a new identity mat4 * * @returns {mat4} a new 4x4 matrix */ function create() { var out = new Float32Array(16); out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; },{}],27:[function(require,module,exports){ module.exports = determinant; /** * Calculates the determinant of a mat4 * * @param {mat4} a the source matrix * @returns {Number} determinant of a */ function determinant(a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32; // Calculate the determinant return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; }; },{}],28:[function(require,module,exports){ module.exports = fromQuat; /** * Creates a matrix from a quaternion rotation. * * @param {mat4} out mat4 receiving operation result * @param {quat4} q Rotation quaternion * @returns {mat4} out */ function fromQuat(out, q) { var x = q[0], y = q[1], z = q[2], w = q[3], x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, yx = y * x2, yy = y * y2, zx = z * x2, zy = z * y2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; out[0] = 1 - yy - zz; out[1] = yx + wz; out[2] = zx - wy; out[3] = 0; out[4] = yx - wz; out[5] = 1 - xx - zz; out[6] = zy + wx; out[7] = 0; out[8] = zx + wy; out[9] = zy - wx; out[10] = 1 - xx - yy; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; },{}],29:[function(require,module,exports){ module.exports = fromRotationTranslation; /** * Creates a matrix from a quaternion rotation and vector translation * This is equivalent to (but much faster than): * * mat4.identity(dest); * mat4.translate(dest, vec); * var quatMat = mat4.create(); * quat4.toMat4(quat, quatMat); * mat4.multiply(dest, quatMat); * * @param {mat4} out mat4 receiving operation result * @param {quat4} q Rotation quaternion * @param {vec3} v Translation vector * @returns {mat4} out */ function fromRotationTranslation(out, q, v) { // Quaternion math var x = q[0], y = q[1], z = q[2], w = q[3], x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; out[0] = 1 - (yy + zz); out[1] = xy + wz; out[2] = xz - wy; out[3] = 0; out[4] = xy - wz; out[5] = 1 - (xx + zz); out[6] = yz + wx; out[7] = 0; out[8] = xz + wy; out[9] = yz - wx; out[10] = 1 - (xx + yy); out[11] = 0; out[12] = v[0]; out[13] = v[1]; out[14] = v[2]; out[15] = 1; return out; }; },{}],30:[function(require,module,exports){ module.exports = frustum; /** * Generates a frustum matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {Number} left Left bound of the frustum * @param {Number} right Right bound of the frustum * @param {Number} bottom Bottom bound of the frustum * @param {Number} top Top bound of the frustum * @param {Number} near Near bound of the frustum * @param {Number} far Far bound of the frustum * @returns {mat4} out */ function frustum(out, left, right, bottom, top, near, far) { var rl = 1 / (right - left), tb = 1 / (top - bottom), nf = 1 / (near - far); out[0] = (near * 2) * rl; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = (near * 2) * tb; out[6] = 0; out[7] = 0; out[8] = (right + left) * rl; out[9] = (top + bottom) * tb; out[10] = (far + near) * nf; out[11] = -1; out[12] = 0; out[13] = 0; out[14] = (far * near * 2) * nf; out[15] = 0; return out; }; },{}],31:[function(require,module,exports){ module.exports = identity; /** * Set a mat4 to the identity matrix * * @param {mat4} out the receiving matrix * @returns {mat4} out */ function identity(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; }; },{}],32:[function(require,module,exports){ module.exports = { create: require('./create') , clone: require('./clone') , copy: require('./copy') , identity: require('./identity') , transpose: require('./transpose') , invert: require('./invert') , adjoint: require('./adjoint') , determinant: require('./determinant') , multiply: require('./multiply') , translate: require('./translate') , scale: require('./scale') , rotate: require('./rotate') , rotateX: require('./rotateX') , rotateY: require('./rotateY') , rotateZ: require('./rotateZ') , fromRotationTranslation: require('./fromRotationTranslation') , fromQuat: require('./fromQuat') , frustum: require('./frustum') , perspective: require('./perspective') , perspectiveFromFieldOfView: require('./perspectiveFromFieldOfView') , ortho: require('./ortho') , lookAt: require('./lookAt') , str: require('./str') } },{"./adjoint":23,"./clone":24,"./copy":25,"./create":26,"./determinant":27,"./fromQuat":28,"./fromRotationTranslation":29,"./frustum":30,"./identity":31,"./invert":33,"./lookAt":34,"./multiply":35,"./ortho":36,"./perspective":37,"./perspectiveFromFieldOfView":38,"./rotate":39,"./rotateX":40,"./rotateY":41,"./rotateZ":42,"./scale":43,"./str":44,"./translate":45,"./transpose":46}],33:[function(require,module,exports){ module.exports = invert; /** * Inverts a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ function invert(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32, // Calculate the determinant det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; if (!det) { return null; } det = 1.0 / det; out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; return out; }; },{}],34:[function(require,module,exports){ var identity = require('./identity'); module.exports = lookAt; /** * Generates a look-at matrix with the given eye position, focal point, and up axis * * @param {mat4} out mat4 frustum matrix will be written into * @param {vec3} eye Position of the viewer * @param {vec3} center Point the viewer is looking at * @param {vec3} up vec3 pointing up * @returns {mat4} out */ function lookAt(out, eye, center, up) { var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, eyex = eye[0], eyey = eye[1], eyez = eye[2], upx = up[0], upy = up[1], upz = up[2], centerx = center[0], centery = center[1], centerz = center[2]; if (Math.abs(eyex - centerx) < 0.000001 && Math.abs(eyey - centery) < 0.000001 && Math.abs(eyez - centerz) < 0.000001) { return identity(out); } z0 = eyex - centerx; z1 = eyey - centery; z2 = eyez - centerz; len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); z0 *= len; z1 *= len; z2 *= len; x0 = upy * z2 - upz * z1; x1 = upz * z0 - upx * z2; x2 = upx * z1 - upy * z0; len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); if (!len) { x0 = 0; x1 = 0; x2 = 0; } else { len = 1 / len; x0 *= len; x1 *= len; x2 *= len; } y0 = z1 * x2 - z2 * x1; y1 = z2 * x0 - z0 * x2; y2 = z0 * x1 - z1 * x0; len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); if (!len) { y0 = 0; y1 = 0; y2 = 0; } else { len = 1 / len; y0 *= len; y1 *= len; y2 *= len; } out[0] = x0; out[1] = y0; out[2] = z0; out[3] = 0; out[4] = x1; out[5] = y1; out[6] = z1; out[7] = 0; out[8] = x2; out[9] = y2; out[10] = z2; out[11] = 0; out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); out[15] = 1; return out; }; },{"./identity":31}],35:[function(require,module,exports){ module.exports = multiply; /** * Multiplies two mat4's * * @param {mat4} out the receiving matrix * @param {mat4} a the first operand * @param {mat4} b the second operand * @returns {mat4} out */ function multiply(out, a, b) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; // Cache only the current line of the second matrix var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; return out; }; },{}],36:[function(require,module,exports){ module.exports = ortho; /** * Generates a orthogonal projection matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {number} left Left bound of the frustum * @param {number} right Right bound of the frustum * @param {number} bottom Bottom bound of the frustum * @param {number} top Top bound of the frustum * @param {number} near Near bound of the frustum * @param {number} far Far bound of the frustum * @returns {mat4} out */ function ortho(out, left, right, bottom, top, near, far) { var lr = 1 / (left - right), bt = 1 / (bottom - top), nf = 1 / (near - far); out[0] = -2 * lr; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = -2 * bt; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 2 * nf; out[11] = 0; out[12] = (left + right) * lr; out[13] = (top + bottom) * bt; out[14] = (far + near) * nf; out[15] = 1; return out; }; },{}],37:[function(require,module,exports){ module.exports = perspective; /** * Generates a perspective projection matrix with the given bounds * * @param {mat4} out mat4 frustum matrix will be written into * @param {number} fovy Vertical field of view in radians * @param {number} aspect Aspect ratio. typically viewport width/height * @param {number} near Near bound of the frustum * @param {number} far Far bound of the frustum * @returns {mat4} out */ function perspective(out, fovy, aspect, near, far) { var f = 1.0 / Math.tan(fovy / 2), nf = 1 / (near - far); out[0] = f / aspect; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = f; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = (far + near) * nf; out[11] = -1; out[12] = 0; out[13] = 0; out[14] = (2 * far * near) * nf; out[15] = 0; return out; }; },{}],38:[function(require,module,exports){ module.exports = perspectiveFromFieldOfView; /** * Generates a perspective projection matrix with the given field of view. * This is primarily useful for generating projection matrices to be used * with the still experiemental WebVR API. * * @param {mat4} out mat4 frustum matrix will be written into * @param {number} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees * @param {number} near Near bound of the frustum * @param {number} far Far bound of the frustum * @returns {mat4} out */ function perspectiveFromFieldOfView(out, fov, near, far) { var upTan = Math.tan(fov.upDegrees * Math.PI/180.0), downTan = Math.tan(fov.downDegrees * Math.PI/180.0), leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0), rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0), xScale = 2.0 / (leftTan + rightTan), yScale = 2.0 / (upTan + downTan); out[0] = xScale; out[1] = 0.0; out[2] = 0.0; out[3] = 0.0; out[4] = 0.0; out[5] = yScale; out[6] = 0.0; out[7] = 0.0; out[8] = -((leftTan - rightTan) * xScale * 0.5); out[9] = ((upTan - downTan) * yScale * 0.5); out[10] = far / (near - far); out[11] = -1.0; out[12] = 0.0; out[13] = 0.0; out[14] = (far * near) / (near - far); out[15] = 0.0; return out; } },{}],39:[function(require,module,exports){ module.exports = rotate; /** * Rotates a mat4 by the given angle * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @param {vec3} axis the axis to rotate around * @returns {mat4} out */ function rotate(out, a, rad, axis) { var x = axis[0], y = axis[1], z = axis[2], len = Math.sqrt(x * x + y * y + z * z), s, c, t, a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, b00, b01, b02, b10, b11, b12, b20, b21, b22; if (Math.abs(len) < 0.000001) { return null; } len = 1 / len; x *= len; y *= len; z *= len; s = Math.sin(rad); c = Math.cos(rad); t = 1 - c; a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; // Construct the elements of the rotation matrix b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; // Perform rotation-specific matrix multiplication out[0] = a00 * b00 + a10 * b01 + a20 * b02; out[1] = a01 * b00 + a11 * b01 + a21 * b02; out[2] = a02 * b00 + a12 * b01 + a22 * b02; out[3] = a03 * b00 + a13 * b01 + a23 * b02; out[4] = a00 * b10 + a10 * b11 + a20 * b12; out[5] = a01 * b10 + a11 * b11 + a21 * b12; out[6] = a02 * b10 + a12 * b11 + a22 * b12; out[7] = a03 * b10 + a13 * b11 + a23 * b12; out[8] = a00 * b20 + a10 * b21 + a20 * b22; out[9] = a01 * b20 + a11 * b21 + a21 * b22; out[10] = a02 * b20 + a12 * b21 + a22 * b22; out[11] = a03 * b20 + a13 * b21 + a23 * b22; if (a !== out) { // If the source and destination differ, copy the unchanged last row out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } return out; }; },{}],40:[function(require,module,exports){ module.exports = rotateX; /** * Rotates a matrix by the given angle around the X axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ function rotateX(out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; if (a !== out) { // If the source and destination differ, copy the unchanged rows out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[4] = a10 * c + a20 * s; out[5] = a11 * c + a21 * s; out[6] = a12 * c + a22 * s; out[7] = a13 * c + a23 * s; out[8] = a20 * c - a10 * s; out[9] = a21 * c - a11 * s; out[10] = a22 * c - a12 * s; out[11] = a23 * c - a13 * s; return out; }; },{}],41:[function(require,module,exports){ module.exports = rotateY; /** * Rotates a matrix by the given angle around the Y axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ function rotateY(out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; if (a !== out) { // If the source and destination differ, copy the unchanged rows out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[0] = a00 * c - a20 * s; out[1] = a01 * c - a21 * s; out[2] = a02 * c - a22 * s; out[3] = a03 * c - a23 * s; out[8] = a00 * s + a20 * c; out[9] = a01 * s + a21 * c; out[10] = a02 * s + a22 * c; out[11] = a03 * s + a23 * c; return out; }; },{}],42:[function(require,module,exports){ module.exports = rotateZ; /** * Rotates a matrix by the given angle around the Z axis * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat4} out */ function rotateZ(out, a, rad) { var s = Math.sin(rad), c = Math.cos(rad), a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; if (a !== out) { // If the source and destination differ, copy the unchanged last row out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } // Perform axis-specific matrix multiplication out[0] = a00 * c + a10 * s; out[1] = a01 * c + a11 * s; out[2] = a02 * c + a12 * s; out[3] = a03 * c + a13 * s; out[4] = a10 * c - a00 * s; out[5] = a11 * c - a01 * s; out[6] = a12 * c - a02 * s; out[7] = a13 * c - a03 * s; return out; }; },{}],43:[function(require,module,exports){ module.exports = scale; /** * Scales the mat4 by the dimensions in the given vec3 * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to scale * @param {vec3} v the vec3 to scale the matrix by * @returns {mat4} out **/ function scale(out, a, v) { var x = v[0], y = v[1], z = v[2]; out[0] = a[0] * x; out[1] = a[1] * x; out[2] = a[2] * x; out[3] = a[3] * x; out[4] = a[4] * y; out[5] = a[5] * y; out[6] = a[6] * y; out[7] = a[7] * y; out[8] = a[8] * z; out[9] = a[9] * z; out[10] = a[10] * z; out[11] = a[11] * z; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; }; },{}],44:[function(require,module,exports){ module.exports = str; /** * Returns a string representation of a mat4 * * @param {mat4} mat matrix to represent as a string * @returns {String} string representation of the matrix */ function str(a) { return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')'; }; },{}],45:[function(require,module,exports){ module.exports = translate; /** * Translate a mat4 by the given vector * * @param {mat4} out the receiving matrix * @param {mat4} a the matrix to translate * @param {vec3} v vector to translate by * @returns {mat4} out */ function translate(out, a, v) { var x = v[0], y = v[1], z = v[2], a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23; if (a === out) { out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; } else { a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; out[12] = a00 * x + a10 * y + a20 * z + a[12]; out[13] = a01 * x + a11 * y + a21 * z + a[13]; out[14] = a02 * x + a12 * y + a22 * z + a[14]; out[15] = a03 * x + a13 * y + a23 * z + a[15]; } return out; }; },{}],46:[function(require,module,exports){ module.exports = transpose; /** * Transpose the values of a mat4 * * @param {mat4} out the receiving matrix * @param {mat4} a the source matrix * @returns {mat4} out */ function transpose(out, a) { // If we are transposing ourselves we can skip a few steps but have to cache some values if (out === a) { var a01 = a[1], a02 = a[2], a03 = a[3], a12 = a[6], a13 = a[7], a23 = a[11]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a01; out[6] = a[9]; out[7] = a[13]; out[8] = a02; out[9] = a12; out[11] = a[14]; out[12] = a03; out[13] = a13; out[14] = a23; } else { out[0] = a[0]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a[1]; out[5] = a[5]; out[6] = a[9]; out[7] = a[13]; out[8] = a[2]; out[9] = a[6]; out[10] = a[10]; out[11] = a[14]; out[12] = a[3]; out[13] = a[7]; out[14] = a[11]; out[15] = a[15]; } return out; }; },{}],47:[function(require,module,exports){ module.exports = add /** * Adds two vec2's * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ function add(out, a, b) { out[0] = a[0] + b[0] out[1] = a[1] + b[1] return out } },{}],48:[function(require,module,exports){ module.exports = dot /** * Calculates the dot product of two vec2's * * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {Number} dot product of a and b */ function dot(a, b) { return a[0] * b[0] + a[1] * b[1] } },{}],49:[function(require,module,exports){ module.exports = length /** * Calculates the length of a vec2 * * @param {vec2} a vector to calculate length of * @returns {Number} length of a */ function length(a) { var x = a[0], y = a[1] return Math.sqrt(x*x + y*y) } },{}],50:[function(require,module,exports){ module.exports = normalize /** * Normalize a vec2 * * @param {vec2} out the receiving vector * @param {vec2} a vector to normalize * @returns {vec2} out */ function normalize(out, a) { var x = a[0], y = a[1] var len = x*x + y*y if (len > 0) { //TODO: evaluate use of glm_invsqrt here? len = 1 / Math.sqrt(len) out[0] = a[0] * len out[1] = a[1] * len } return out } },{}],51:[function(require,module,exports){ module.exports = set /** * Set the components of a vec2 to the given values * * @param {vec2} out the receiving vector * @param {Number} x X component * @param {Number} y Y component * @returns {vec2} out */ function set(out, x, y) { out[0] = x out[1] = y return out } },{}],52:[function(require,module,exports){ module.exports = subtract /** * Subtracts vector b from vector a * * @param {vec2} out the receiving vector * @param {vec2} a the first operand * @param {vec2} b the second operand * @returns {vec2} out */ function subtract(out, a, b) { out[0] = a[0] - b[0] out[1] = a[1] - b[1] return out } },{}],53:[function(require,module,exports){ module.exports = add; /** * Adds two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ function add(out, a, b) { out[0] = a[0] + b[0] out[1] = a[1] + b[1] out[2] = a[2] + b[2] return out } },{}],54:[function(require,module,exports){ module.exports = angle var fromValues = require('./fromValues') var normalize = require('./normalize') var dot = require('./dot') /** * Get the angle between two 3D vectors * @param {vec3} a The first operand * @param {vec3} b The second operand * @returns {Number} The angle in radians */ function angle(a, b) { var tempA = fromValues(a[0], a[1], a[2]) var tempB = fromValues(b[0], b[1], b[2]) normalize(tempA, tempA) normalize(tempB, tempB) var cosine = dot(tempA, tempB) if(cosine > 1.0){ return 0 } else { return Math.acos(cosine) } } },{"./dot":61,"./fromValues":63,"./normalize":72}],55:[function(require,module,exports){ module.exports = clone; /** * Creates a new vec3 initialized with values from an existing vector * * @param {vec3} a vector to clone * @returns {vec3} a new 3D vector */ function clone(a) { var out = new Float32Array(3) out[0] = a[0] out[1] = a[1] out[2] = a[2] return out } },{}],56:[function(require,module,exports){ module.exports = copy; /** * Copy the values from one vec3 to another * * @param {vec3} out the receiving vector * @param {vec3} a the source vector * @returns {vec3} out */ function copy(out, a) { out[0] = a[0] out[1] = a[1] out[2] = a[2] return out } },{}],57:[function(require,module,exports){ module.exports = create; /** * Creates a new, empty vec3 * * @returns {vec3} a new 3D vector */ function create() { var out = new Float32Array(3) out[0] = 0 out[1] = 0 out[2] = 0 return out } },{}],58:[function(require,module,exports){ module.exports = cross; /** * Computes the cross product of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ function cross(out, a, b) { var ax = a[0], ay = a[1], az = a[2], bx = b[0], by = b[1], bz = b[2] out[0] = ay * bz - az * by out[1] = az * bx - ax * bz out[2] = ax * by - ay * bx return out } },{}],59:[function(require,module,exports){ module.exports = distance; /** * Calculates the euclidian distance between two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} distance between a and b */ function distance(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2] return Math.sqrt(x*x + y*y + z*z) } },{}],60:[function(require,module,exports){ module.exports = divide; /** * Divides two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ function divide(out, a, b) { out[0] = a[0] / b[0] out[1] = a[1] / b[1] out[2] = a[2] / b[2] return out } },{}],61:[function(require,module,exports){ module.exports = dot; /** * Calculates the dot product of two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} dot product of a and b */ function dot(a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] } },{}],62:[function(require,module,exports){ module.exports = forEach; var vec = require('./create')() /** * Perform some operation over an array of vec3s. * * @param {Array} a the array of vectors to iterate over * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed * @param {Number} offset Number of elements to skip at the beginning of the array * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array * @param {Function} fn Function to call for each vector in the array * @param {Object} [arg] additional argument to pass to fn * @returns {Array} a * @function */ function forEach(a, stride, offset, count, fn, arg) { var i, l if(!stride) { stride = 3 } if(!offset) { offset = 0 } if(count) { l = Math.min((count * stride) + offset, a.length) } else { l = a.length } for(i = offset; i < l; i += stride) { vec[0] = a[i] vec[1] = a[i+1] vec[2] = a[i+2] fn(vec, vec, arg) a[i] = vec[0] a[i+1] = vec[1] a[i+2] = vec[2] } return a } },{"./create":57}],63:[function(require,module,exports){ module.exports = fromValues; /** * Creates a new vec3 initialized with the given values * * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @returns {vec3} a new 3D vector */ function fromValues(x, y, z) { var out = new Float32Array(3) out[0] = x out[1] = y out[2] = z return out } },{}],64:[function(require,module,exports){ module.exports = { create: require('./create') , clone: require('./clone') , angle: require('./angle') , fromValues: require('./fromValues') , copy: require('./copy') , set: require('./set') , add: require('./add') , subtract: require('./subtract') , multiply: require('./multiply') , divide: require('./divide') , min: require('./min') , max: require('./max') , scale: require('./scale') , scaleAndAdd: require('./scaleAndAdd') , distance: require('./distance') , squaredDistance: require('./squaredDistance') , length: require('./length') , squaredLength: require('./squaredLength') , negate: require('./negate') , inverse: require('./inverse') , normalize: require('./normalize') , dot: require('./dot') , cross: require('./cross') , lerp: require('./lerp') , random: require('./random') , transformMat4: require('./transformMat4') , transformMat3: require('./transformMat3') , transformQuat: require('./transformQuat') , rotateX: require('./rotateX') , rotateY: require('./rotateY') , rotateZ: require('./rotateZ') , forEach: require('./forEach') } },{"./add":53,"./angle":54,"./clone":55,"./copy":56,"./create":57,"./cross":58,"./distance":59,"./divide":60,"./dot":61,"./forEach":62,"./fromValues":63,"./inverse":65,"./length":66,"./lerp":67,"./max":68,"./min":69,"./multiply":70,"./negate":71,"./normalize":72,"./random":73,"./rotateX":74,"./rotateY":75,"./rotateZ":76,"./scale":77,"./scaleAndAdd":78,"./set":79,"./squaredDistance":80,"./squaredLength":81,"./subtract":82,"./transformMat3":83,"./transformMat4":84,"./transformQuat":85}],65:[function(require,module,exports){ module.exports = inverse; /** * Returns the inverse of the components of a vec3 * * @param {vec3} out the receiving vector * @param {vec3} a vector to invert * @returns {vec3} out */ function inverse(out, a) { out[0] = 1.0 / a[0] out[1] = 1.0 / a[1] out[2] = 1.0 / a[2] return out } },{}],66:[function(require,module,exports){ module.exports = length; /** * Calculates the length of a vec3 * * @param {vec3} a vector to calculate length of * @returns {Number} length of a */ function length(a) { var x = a[0], y = a[1], z = a[2] return Math.sqrt(x*x + y*y + z*z) } },{}],67:[function(require,module,exports){ module.exports = lerp; /** * Performs a linear interpolation between two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @param {Number} t interpolation amount between the two inputs * @returns {vec3} out */ function lerp(out, a, b, t) { var ax = a[0], ay = a[1], az = a[2] out[0] = ax + t * (b[0] - ax) out[1] = ay + t * (b[1] - ay) out[2] = az + t * (b[2] - az) return out } },{}],68:[function(require,module,exports){ module.exports = max; /** * Returns the maximum of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ function max(out, a, b) { out[0] = Math.max(a[0], b[0]) out[1] = Math.max(a[1], b[1]) out[2] = Math.max(a[2], b[2]) return out } },{}],69:[function(require,module,exports){ module.exports = min; /** * Returns the minimum of two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ function min(out, a, b) { out[0] = Math.min(a[0], b[0]) out[1] = Math.min(a[1], b[1]) out[2] = Math.min(a[2], b[2]) return out } },{}],70:[function(require,module,exports){ module.exports = multiply; /** * Multiplies two vec3's * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ function multiply(out, a, b) { out[0] = a[0] * b[0] out[1] = a[1] * b[1] out[2] = a[2] * b[2] return out } },{}],71:[function(require,module,exports){ module.exports = negate; /** * Negates the components of a vec3 * * @param {vec3} out the receiving vector * @param {vec3} a vector to negate * @returns {vec3} out */ function negate(out, a) { out[0] = -a[0] out[1] = -a[1] out[2] = -a[2] return out } },{}],72:[function(require,module,exports){ module.exports = normalize; /** * Normalize a vec3 * * @param {vec3} out the receiving vector * @param {vec3} a vector to normalize * @returns {vec3} out */ function normalize(out, a) { var x = a[0], y = a[1], z = a[2] var len = x*x + y*y + z*z if (len > 0) { //TODO: evaluate use of glm_invsqrt here? len = 1 / Math.sqrt(len) out[0] = a[0] * len out[1] = a[1] * len out[2] = a[2] * len } return out } },{}],73:[function(require,module,exports){ module.exports = random; /** * Generates a random vector with the given scale * * @param {vec3} out the receiving vector * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec3} out */ function random(out, scale) { scale = scale || 1.0 var r = Math.random() * 2.0 * Math.PI var z = (Math.random() * 2.0) - 1.0 var zScale = Math.sqrt(1.0-z*z) * scale out[0] = Math.cos(r) * zScale out[1] = Math.sin(r) * zScale out[2] = z * scale return out } },{}],74:[function(require,module,exports){ module.exports = rotateX; /** * Rotate a 3D vector around the x-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ function rotateX(out, a, b, c){ var p = [], r=[] //Translate point to the origin p[0] = a[0] - b[0] p[1] = a[1] - b[1] p[2] = a[2] - b[2] //perform rotation r[0] = p[0] r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c) r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c) //translate to correct position out[0] = r[0] + b[0] out[1] = r[1] + b[1] out[2] = r[2] + b[2] return out } },{}],75:[function(require,module,exports){ module.exports = rotateY; /** * Rotate a 3D vector around the y-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ function rotateY(out, a, b, c){ var p = [], r=[] //Translate point to the origin p[0] = a[0] - b[0] p[1] = a[1] - b[1] p[2] = a[2] - b[2] //perform rotation r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c) r[1] = p[1] r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c) //translate to correct position out[0] = r[0] + b[0] out[1] = r[1] + b[1] out[2] = r[2] + b[2] return out } },{}],76:[function(require,module,exports){ module.exports = rotateZ; /** * Rotate a 3D vector around the z-axis * @param {vec3} out The receiving vec3 * @param {vec3} a The vec3 point to rotate * @param {vec3} b The origin of the rotation * @param {Number} c The angle of rotation * @returns {vec3} out */ function rotateZ(out, a, b, c){ var p = [], r=[] //Translate point to the origin p[0] = a[0] - b[0] p[1] = a[1] - b[1] p[2] = a[2] - b[2] //perform rotation r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c) r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c) r[2] = p[2] //translate to correct position out[0] = r[0] + b[0] out[1] = r[1] + b[1] out[2] = r[2] + b[2] return out } },{}],77:[function(require,module,exports){ module.exports = scale; /** * Scales a vec3 by a scalar number * * @param {vec3} out the receiving vector * @param {vec3} a the vector to scale * @param {Number} b amount to scale the vector by * @returns {vec3} out */ function scale(out, a, b) { out[0] = a[0] * b out[1] = a[1] * b out[2] = a[2] * b return out } },{}],78:[function(require,module,exports){ module.exports = scaleAndAdd; /** * Adds two vec3's after scaling the second operand by a scalar value * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @param {Number} scale the amount to scale b by before adding * @returns {vec3} out */ function scaleAndAdd(out, a, b, scale) { out[0] = a[0] + (b[0] * scale) out[1] = a[1] + (b[1] * scale) out[2] = a[2] + (b[2] * scale) return out } },{}],79:[function(require,module,exports){ module.exports = set; /** * Set the components of a vec3 to the given values * * @param {vec3} out the receiving vector * @param {Number} x X component * @param {Number} y Y component * @param {Number} z Z component * @returns {vec3} out */ function set(out, x, y, z) { out[0] = x out[1] = y out[2] = z return out } },{}],80:[function(require,module,exports){ module.exports = squaredDistance; /** * Calculates the squared euclidian distance between two vec3's * * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {Number} squared distance between a and b */ function squaredDistance(a, b) { var x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2] return x*x + y*y + z*z } },{}],81:[function(require,module,exports){ module.exports = squaredLength; /** * Calculates the squared length of a vec3 * * @param {vec3} a vector to calculate squared length of * @returns {Number} squared length of a */ function squaredLength(a) { var x = a[0], y = a[1], z = a[2] return x*x + y*y + z*z } },{}],82:[function(require,module,exports){ module.exports = subtract; /** * Subtracts vector b from vector a * * @param {vec3} out the receiving vector * @param {vec3} a the first operand * @param {vec3} b the second operand * @returns {vec3} out */ function subtract(out, a, b) { out[0] = a[0] - b[0] out[1] = a[1] - b[1] out[2] = a[2] - b[2] return out } },{}],83:[function(require,module,exports){ module.exports = transformMat3; /** * Transforms the vec3 with a mat3. * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {mat4} m the 3x3 matrix to transform with * @returns {vec3} out */ function transformMat3(out, a, m) { var x = a[0], y = a[1], z = a[2] out[0] = x * m[0] + y * m[3] + z * m[6] out[1] = x * m[1] + y * m[4] + z * m[7] out[2] = x * m[2] + y * m[5] + z * m[8] return out } },{}],84:[function(require,module,exports){ module.exports = transformMat4; /** * Transforms the vec3 with a mat4. * 4th vector component is implicitly '1' * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {mat4} m matrix to transform with * @returns {vec3} out */ function transformMat4(out, a, m) { var x = a[0], y = a[1], z = a[2], w = m[3] * x + m[7] * y + m[11] * z + m[15] w = w || 1.0 out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w return out } },{}],85:[function(require,module,exports){ module.exports = transformQuat; /** * Transforms the vec3 with a quat * * @param {vec3} out the receiving vector * @param {vec3} a the vector to transform * @param {quat} q quaternion to transform with * @returns {vec3} out */ function transformQuat(out, a, q) { // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations var x = a[0], y = a[1], z = a[2], qx = q[0], qy = q[1], qz = q[2], qw = q[3], // calculate quat * vec ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z // calculate result * inverse quat out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx return out } },{}],86:[function(require,module,exports){ "use strict" var dup = require("dup") function p(x,y,nx) { return x + (nx+1)*y; }; //Creates a grid mesh function gridMesh(nx, ny, origin, dx, dy) { //Unpack default arguments origin = origin || [0,0] if(!dx || dx.length < origin.length) { dx = dup(origin.length) if(origin.length > 0) { dx[0] = 1 } } if(!dy || dy.length < origin.length) { dy = dup(origin.length) if(origin.length > 1) { dy[1] = 1 } } //Initialize cells var cells = [] , positions = dup([(nx+1) * (ny+1), origin.length]) , i, j, k, q, d = origin.length for(j=0; j 1) { stack.pop() stack[stack.length-1][0][2][ix] = h( cur[0], cur[1], cur[2].length ? cur[2] : undefined ) } } else if (s === OPEN) { var c = [p[1],{},[]] cur[2].push(c) stack.push([c,cur[2].length-1]) } else if (s === ATTR_KEY || (s === VAR && p[1] === ATTR_KEY)) { var key = '' var copyKey for (; i < parts.length; i++) { if (parts[i][0] === ATTR_KEY) { key = concat(key, parts[i][1]) } else if (parts[i][0] === VAR && parts[i][1] === ATTR_KEY) { if (typeof parts[i][2] === 'object' && !key) { for (copyKey in parts[i][2]) { if (parts[i][2].hasOwnProperty(copyKey) && !cur[1][copyKey]) { cur[1][copyKey] = parts[i][2][copyKey] } } } else { key = concat(key, parts[i][2]) } } else break } if (parts[i][0] === ATTR_EQ) i++ var j = i for (; i < parts.length; i++) { if (parts[i][0] === ATTR_VALUE || parts[i][0] === ATTR_KEY) { if (!cur[1][key]) cur[1][key] = strfn(parts[i][1]) else parts[i][1]==="" || (cur[1][key] = concat(cur[1][key], parts[i][1])); } else if (parts[i][0] === VAR && (parts[i][1] === ATTR_VALUE || parts[i][1] === ATTR_KEY)) { if (!cur[1][key]) cur[1][key] = strfn(parts[i][2]) else parts[i][2]==="" || (cur[1][key] = concat(cur[1][key], parts[i][2])); } else { if (key.length && !cur[1][key] && i === j && (parts[i][0] === CLOSE || parts[i][0] === ATTR_BREAK)) { // https://html.spec.whatwg.org/multipage/infrastructure.html#boolean-attributes // empty string is falsy, not well behaved value in browser cur[1][key] = key.toLowerCase() } if (parts[i][0] === CLOSE) { i-- } break } } } else if (s === ATTR_KEY) { cur[1][p[1]] = true } else if (s === VAR && p[1] === ATTR_KEY) { cur[1][p[2]] = true } else if (s === CLOSE) { if (selfClosing(cur[0]) && stack.length) { var ix = stack[stack.length-1][1] stack.pop() stack[stack.length-1][0][2][ix] = h( cur[0], cur[1], cur[2].length ? cur[2] : undefined ) } } else if (s === VAR && p[1] === TEXT) { if (p[2] === undefined || p[2] === null) p[2] = '' else if (!p[2]) p[2] = concat('', p[2]) if (Array.isArray(p[2][0])) { cur[2].push.apply(cur[2], p[2]) } else { cur[2].push(p[2]) } } else if (s === TEXT) { cur[2].push(p[1]) } else if (s === ATTR_EQ || s === ATTR_BREAK) { // no-op } else { throw new Error('unhandled: ' + s) } } if (tree[2].length > 1 && /^\s*$/.test(tree[2][0])) { tree[2].shift() } if (tree[2].length > 2 || (tree[2].length === 2 && /\S/.test(tree[2][1]))) { throw new Error( 'multiple root elements must be wrapped in an enclosing tag' ) } if (Array.isArray(tree[2][0]) && typeof tree[2][0][0] === 'string' && Array.isArray(tree[2][0][2])) { tree[2][0] = h(tree[2][0][0], tree[2][0][1], tree[2][0][2]) } return tree[2][0] function parse (str) { var res = [] if (state === ATTR_VALUE_W) state = ATTR for (var i = 0; i < str.length; i++) { var c = str.charAt(i) if (state === TEXT && c === '<') { if (reg.length) res.push([TEXT, reg]) reg = '' state = OPEN } else if (c === '>' && !quot(state) && state !== COMMENT) { if (state === OPEN) { res.push([OPEN,reg]) } else if (state === ATTR_KEY) { res.push([ATTR_KEY,reg]) } else if (state === ATTR_VALUE && reg.length) { res.push([ATTR_VALUE,reg]) } res.push([CLOSE]) reg = '' state = TEXT } else if (state === COMMENT && /-$/.test(reg) && c === '-') { if (opts.comments) { res.push([ATTR_VALUE,reg.substr(0, reg.length - 1)],[CLOSE]) } reg = '' state = TEXT } else if (state === OPEN && /^!--$/.test(reg)) { if (opts.comments) { res.push([OPEN, reg],[ATTR_KEY,'comment'],[ATTR_EQ]) } reg = c state = COMMENT } else if (state === TEXT || state === COMMENT) { reg += c } else if (state === OPEN && c === '/' && reg.length) { // no-op, self closing tag without a space
} else if (state === OPEN && /\s/.test(c)) { res.push([OPEN, reg]) reg = '' state = ATTR } else if (state === OPEN) { reg += c } else if (state === ATTR && /[^\s"'=/]/.test(c)) { state = ATTR_KEY reg = c } else if (state === ATTR && /\s/.test(c)) { if (reg.length) res.push([ATTR_KEY,reg]) res.push([ATTR_BREAK]) } else if (state === ATTR_KEY && /\s/.test(c)) { res.push([ATTR_KEY,reg]) reg = '' state = ATTR_KEY_W } else if (state === ATTR_KEY && c === '=') { res.push([ATTR_KEY,reg],[ATTR_EQ]) reg = '' state = ATTR_VALUE_W } else if (state === ATTR_KEY) { reg += c } else if ((state === ATTR_KEY_W || state === ATTR) && c === '=') { res.push([ATTR_EQ]) state = ATTR_VALUE_W } else if ((state === ATTR_KEY_W || state === ATTR) && !/\s/.test(c)) { res.push([ATTR_BREAK]) if (/[\w-]/.test(c)) { reg += c state = ATTR_KEY } else state = ATTR } else if (state === ATTR_VALUE_W && c === '"') { state = ATTR_VALUE_DQ } else if (state === ATTR_VALUE_W && c === "'") { state = ATTR_VALUE_SQ } else if (state === ATTR_VALUE_DQ && c === '"') { res.push([ATTR_VALUE,reg],[ATTR_BREAK]) reg = '' state = ATTR } else if (state === ATTR_VALUE_SQ && c === "'") { res.push([ATTR_VALUE,reg],[ATTR_BREAK]) reg = '' state = ATTR } else if (state === ATTR_VALUE_W && !/\s/.test(c)) { state = ATTR_VALUE i-- } else if (state === ATTR_VALUE && /\s/.test(c)) { res.push([ATTR_VALUE,reg],[ATTR_BREAK]) reg = '' state = ATTR } else if (state === ATTR_VALUE || state === ATTR_VALUE_SQ || state === ATTR_VALUE_DQ) { reg += c } } if (state === TEXT && reg.length) { res.push([TEXT,reg]) reg = '' } else if (state === ATTR_VALUE && reg.length) { res.push([ATTR_VALUE,reg]) reg = '' } else if (state === ATTR_VALUE_DQ && reg.length) { res.push([ATTR_VALUE,reg]) reg = '' } else if (state === ATTR_VALUE_SQ && reg.length) { res.push([ATTR_VALUE,reg]) reg = '' } else if (state === ATTR_KEY) { res.push([ATTR_KEY,reg]) reg = '' } return res } } function strfn (x) { if (typeof x === 'function') return x else if (typeof x === 'string') return x else if (x && typeof x === 'object') return x else return concat('', x) } } function quot (state) { return state === ATTR_VALUE_SQ || state === ATTR_VALUE_DQ } var hasOwn = Object.prototype.hasOwnProperty function has (obj, key) { return hasOwn.call(obj, key) } var closeRE = RegExp('^(' + [ 'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr', '!--', // SVG TAGS 'animate', 'animateTransform', 'circle', 'cursor', 'desc', 'ellipse', 'feBlend', 'feColorMatrix', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence', 'font-face-format', 'font-face-name', 'font-face-uri', 'glyph', 'glyphRef', 'hkern', 'image', 'line', 'missing-glyph', 'mpath', 'path', 'polygon', 'polyline', 'rect', 'set', 'stop', 'tref', 'use', 'view', 'vkern' ].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$') function selfClosing (tag) { return closeRE.test(tag) } },{"hyperscript-attribute-to-property":87}],89:[function(require,module,exports){ assert.notEqual = notEqual assert.notOk = notOk assert.equal = equal assert.ok = assert module.exports = assert function equal (a, b, m) { assert(a == b, m) // eslint-disable-line eqeqeq } function notEqual (a, b, m) { assert(a != b, m) // eslint-disable-line eqeqeq } function notOk (t, m) { assert(!t, m) } function assert (t, m) { if (!t) throw new Error(m || 'AssertionError') } },{}],90:[function(require,module,exports){ var splice = require('remove-array-items') var nanotiming = require('nanotiming') var assert = require('assert') module.exports = Nanobus function Nanobus (name) { if (!(this instanceof Nanobus)) return new Nanobus(name) this._name = name || 'nanobus' this._starListeners = [] this._listeners = {} } Nanobus.prototype.emit = function (eventName) { assert.equal(typeof eventName, 'string', 'nanobus.emit: eventName should be type string') var data = [] for (var i = 1, len = arguments.length; i < len; i++) { data.push(arguments[i]) } var emitTiming = nanotiming(this._name + "('" + eventName + "')") var listeners = this._listeners[eventName] if (listeners && listeners.length > 0) { this._emit(this._listeners[eventName], data) } if (this._starListeners.length > 0) { this._emit(this._starListeners, eventName, data, emitTiming.uuid) } emitTiming() return this } Nanobus.prototype.on = Nanobus.prototype.addListener = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.on: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.on: listener should be type function') if (eventName === '*') { this._starListeners.push(listener) } else { if (!this._listeners[eventName]) this._listeners[eventName] = [] this._listeners[eventName].push(listener) } return this } Nanobus.prototype.prependListener = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.prependListener: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.prependListener: listener should be type function') if (eventName === '*') { this._starListeners.unshift(listener) } else { if (!this._listeners[eventName]) this._listeners[eventName] = [] this._listeners[eventName].unshift(listener) } return this } Nanobus.prototype.once = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.once: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.once: listener should be type function') var self = this this.on(eventName, once) function once () { listener.apply(self, arguments) self.removeListener(eventName, once) } return this } Nanobus.prototype.prependOnceListener = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.prependOnceListener: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.prependOnceListener: listener should be type function') var self = this this.prependListener(eventName, once) function once () { listener.apply(self, arguments) self.removeListener(eventName, once) } return this } Nanobus.prototype.removeListener = function (eventName, listener) { assert.equal(typeof eventName, 'string', 'nanobus.removeListener: eventName should be type string') assert.equal(typeof listener, 'function', 'nanobus.removeListener: listener should be type function') if (eventName === '*') { this._starListeners = this._starListeners.slice() return remove(this._starListeners, listener) } else { if (typeof this._listeners[eventName] !== 'undefined') { this._listeners[eventName] = this._listeners[eventName].slice() } return remove(this._listeners[eventName], listener) } function remove (arr, listener) { if (!arr) return var index = arr.indexOf(listener) if (index !== -1) { splice(arr, index, 1) return true } } } Nanobus.prototype.removeAllListeners = function (eventName) { if (eventName) { if (eventName === '*') { this._starListeners = [] } else { this._listeners[eventName] = [] } } else { this._starListeners = [] this._listeners = {} } return this } Nanobus.prototype.listeners = function (eventName) { var listeners = eventName !== '*' ? this._listeners[eventName] : this._starListeners var ret = [] if (listeners) { var ilength = listeners.length for (var i = 0; i < ilength; i++) ret.push(listeners[i]) } return ret } Nanobus.prototype._emit = function (arr, eventName, data, uuid) { if (typeof arr === 'undefined') return if (arr.length === 0) return if (data === undefined) { data = eventName eventName = null } if (eventName) { if (uuid !== undefined) { data = [eventName].concat(data, uuid) } else { data = [eventName].concat(data) } } var length = arr.length for (var i = 0; i < length; i++) { var listener = arr[i] listener.apply(listener, data) } } },{"assert":1,"nanotiming":100,"remove-array-items":105}],91:[function(require,module,exports){ var assert = require('assert') var safeExternalLink = /(noopener|noreferrer) (noopener|noreferrer)/ var protocolLink = /^[\w-_]+:/ module.exports = href function href (cb, root) { assert.notEqual(typeof window, 'undefined', 'nanohref: expected window to exist') root = root || window.document assert.equal(typeof cb, 'function', 'nanohref: cb should be type function') assert.equal(typeof root, 'object', 'nanohref: root should be type object') window.addEventListener('click', function (e) { if ((e.button && e.button !== 0) || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.defaultPrevented) return var anchor = (function traverse (node) { if (!node || node === root) return if (node.localName !== 'a' || node.href === undefined) { return traverse(node.parentNode) } return node })(e.target) if (!anchor) return if (window.location.origin !== anchor.origin || anchor.hasAttribute('download') || (anchor.getAttribute('target') === '_blank' && safeExternalLink.test(anchor.getAttribute('rel'))) || protocolLink.test(anchor.getAttribute('href'))) return e.preventDefault() cb(anchor) }) } },{"assert":1}],92:[function(require,module,exports){ var assert = require('assert') module.exports = nanolocation function nanolocation () { assert.notEqual(typeof window, 'undefined', 'nanolocation: expected window to exist') var pathname = window.location.pathname.replace(/\/$/, '') var hash = window.location.hash.replace(/^#/, '/') return pathname + hash } },{"assert":1}],93:[function(require,module,exports){ var assert = require('assert') var morph = require('./lib/morph') var TEXT_NODE = 3 // var DEBUG = false module.exports = nanomorph // Morph one tree into another tree // // no parent // -> same: diff and walk children // -> not same: replace and return // old node doesn't exist // -> insert new node // new node doesn't exist // -> delete old node // nodes are not the same // -> diff nodes and apply patch to old node // nodes are the same // -> walk all child nodes and append to old node function nanomorph (oldTree, newTree) { // if (DEBUG) { // console.log( // 'nanomorph\nold\n %s\nnew\n %s', // oldTree && oldTree.outerHTML, // newTree && newTree.outerHTML // ) // } assert.equal(typeof oldTree, 'object', 'nanomorph: oldTree should be an object') assert.equal(typeof newTree, 'object', 'nanomorph: newTree should be an object') var tree = walk(newTree, oldTree) // if (DEBUG) console.log('=> morphed\n %s', tree.outerHTML) return tree } // Walk and morph a dom tree function walk (newNode, oldNode) { // if (DEBUG) { // console.log( // 'walk\nold\n %s\nnew\n %s', // oldNode && oldNode.outerHTML, // newNode && newNode.outerHTML // ) // } if (!oldNode) { return newNode } else if (!newNode) { return null } else if (newNode.isSameNode && newNode.isSameNode(oldNode)) { return oldNode } else if (newNode.tagName !== oldNode.tagName) { return newNode } else { morph(newNode, oldNode) updateChildren(newNode, oldNode) return oldNode } } // Update the children of elements // (obj, obj) -> null function updateChildren (newNode, oldNode) { // if (DEBUG) { // console.log( // 'updateChildren\nold\n %s\nnew\n %s', // oldNode && oldNode.outerHTML, // newNode && newNode.outerHTML // ) // } var oldChild, newChild, morphed, oldMatch // The offset is only ever increased, and used for [i - offset] in the loop var offset = 0 for (var i = 0; ; i++) { oldChild = oldNode.childNodes[i] newChild = newNode.childNodes[i - offset] // if (DEBUG) { // console.log( // '===\n- old\n %s\n- new\n %s', // oldChild && oldChild.outerHTML, // newChild && newChild.outerHTML // ) // } // Both nodes are empty, do nothing if (!oldChild && !newChild) { break // There is no new child, remove old } else if (!newChild) { oldNode.removeChild(oldChild) i-- // There is no old child, add new } else if (!oldChild) { oldNode.appendChild(newChild) offset++ // Both nodes are the same, morph } else if (same(newChild, oldChild)) { morphed = walk(newChild, oldChild) if (morphed !== oldChild) { oldNode.replaceChild(morphed, oldChild) offset++ } // Both nodes do not share an ID or a placeholder, try reorder } else { oldMatch = null // Try and find a similar node somewhere in the tree for (var j = i; j < oldNode.childNodes.length; j++) { if (same(oldNode.childNodes[j], newChild)) { oldMatch = oldNode.childNodes[j] break } } // If there was a node with the same ID or placeholder in the old list if (oldMatch) { morphed = walk(newChild, oldMatch) if (morphed !== oldMatch) offset++ oldNode.insertBefore(morphed, oldChild) // It's safe to morph two nodes in-place if neither has an ID } else if (!newChild.id && !oldChild.id) { morphed = walk(newChild, oldChild) if (morphed !== oldChild) { oldNode.replaceChild(morphed, oldChild) offset++ } // Insert the node at the index if we couldn't morph or find a matching node } else { oldNode.insertBefore(newChild, oldChild) offset++ } } } } function same (a, b) { if (a.id) return a.id === b.id if (a.isSameNode) return a.isSameNode(b) if (a.tagName !== b.tagName) return false if (a.type === TEXT_NODE) return a.nodeValue === b.nodeValue return false } },{"./lib/morph":95,"assert":89}],94:[function(require,module,exports){ module.exports = [ // attribute events (can be set with attributes) 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onmouseenter', 'onmouseleave', 'ontouchcancel', 'ontouchend', 'ontouchmove', 'ontouchstart', 'ondragstart', 'ondrag', 'ondragenter', 'ondragleave', 'ondragover', 'ondrop', 'ondragend', 'onkeydown', 'onkeypress', 'onkeyup', 'onunload', 'onabort', 'onerror', 'onresize', 'onscroll', 'onselect', 'onchange', 'onsubmit', 'onreset', 'onfocus', 'onblur', 'oninput', // other common events 'oncontextmenu', 'onfocusin', 'onfocusout' ] },{}],95:[function(require,module,exports){ var events = require('./events') var eventsLength = events.length var ELEMENT_NODE = 1 var TEXT_NODE = 3 var COMMENT_NODE = 8 module.exports = morph // diff elements and apply the resulting patch to the old node // (obj, obj) -> null function morph (newNode, oldNode) { var nodeType = newNode.nodeType var nodeName = newNode.nodeName if (nodeType === ELEMENT_NODE) { copyAttrs(newNode, oldNode) } if (nodeType === TEXT_NODE || nodeType === COMMENT_NODE) { if (oldNode.nodeValue !== newNode.nodeValue) { oldNode.nodeValue = newNode.nodeValue } } // Some DOM nodes are weird // https://github.com/patrick-steele-idem/morphdom/blob/master/src/specialElHandlers.js if (nodeName === 'INPUT') updateInput(newNode, oldNode) else if (nodeName === 'OPTION') updateOption(newNode, oldNode) else if (nodeName === 'TEXTAREA') updateTextarea(newNode, oldNode) copyEvents(newNode, oldNode) } function copyAttrs (newNode, oldNode) { var oldAttrs = oldNode.attributes var newAttrs = newNode.attributes var attrNamespaceURI = null var attrValue = null var fromValue = null var attrName = null var attr = null for (var i = newAttrs.length - 1; i >= 0; --i) { attr = newAttrs[i] attrName = attr.name attrNamespaceURI = attr.namespaceURI attrValue = attr.value if (attrNamespaceURI) { attrName = attr.localName || attrName fromValue = oldNode.getAttributeNS(attrNamespaceURI, attrName) if (fromValue !== attrValue) { oldNode.setAttributeNS(attrNamespaceURI, attrName, attrValue) } } else { if (!oldNode.hasAttribute(attrName)) { oldNode.setAttribute(attrName, attrValue) } else { fromValue = oldNode.getAttribute(attrName) if (fromValue !== attrValue) { // apparently values are always cast to strings, ah well if (attrValue === 'null' || attrValue === 'undefined') { oldNode.removeAttribute(attrName) } else { oldNode.setAttribute(attrName, attrValue) } } } } } // Remove any extra attributes found on the original DOM element that // weren't found on the target element. for (var j = oldAttrs.length - 1; j >= 0; --j) { attr = oldAttrs[j] if (attr.specified !== false) { attrName = attr.name attrNamespaceURI = attr.namespaceURI if (attrNamespaceURI) { attrName = attr.localName || attrName if (!newNode.hasAttributeNS(attrNamespaceURI, attrName)) { oldNode.removeAttributeNS(attrNamespaceURI, attrName) } } else { if (!newNode.hasAttributeNS(null, attrName)) { oldNode.removeAttribute(attrName) } } } } } function copyEvents (newNode, oldNode) { for (var i = 0; i < eventsLength; i++) { var ev = events[i] if (newNode[ev]) { // if new element has a whitelisted attribute oldNode[ev] = newNode[ev] // update existing element } else if (oldNode[ev]) { // if existing element has it and new one doesnt oldNode[ev] = undefined // remove it from existing element } } } function updateOption (newNode, oldNode) { updateAttribute(newNode, oldNode, 'selected') } // The "value" attribute is special for the element since it sets the // initial value. Changing the "value" attribute without changing the "value" // property will have no effect since it is only used to the set the initial // value. Similar for the "checked" attribute, and "disabled". function updateInput (newNode, oldNode) { var newValue = newNode.value var oldValue = oldNode.value updateAttribute(newNode, oldNode, 'checked') updateAttribute(newNode, oldNode, 'disabled') if (newValue !== oldValue) { oldNode.setAttribute('value', newValue) oldNode.value = newValue } if (newValue === 'null') { oldNode.value = '' oldNode.removeAttribute('value') } if (!newNode.hasAttributeNS(null, 'value')) { oldNode.removeAttribute('value') } else if (oldNode.type === 'range') { // this is so elements like slider move their UI thingy oldNode.value = newValue } } function updateTextarea (newNode, oldNode) { var newValue = newNode.value if (newValue !== oldNode.value) { oldNode.value = newValue } if (oldNode.firstChild && oldNode.firstChild.nodeValue !== newValue) { // Needed for IE. Apparently IE sets the placeholder as the // node value and vise versa. This ignores an empty update. if (newValue === '' && oldNode.firstChild.nodeValue === oldNode.placeholder) { return } oldNode.firstChild.nodeValue = newValue } } function updateAttribute (newNode, oldNode, name) { if (newNode[name] !== oldNode[name]) { oldNode[name] = newNode[name] if (newNode[name]) { oldNode.setAttribute(name, '') } else { oldNode.removeAttribute(name) } } } },{"./events":94}],96:[function(require,module,exports){ var reg = /([^?=&]+)(=([^&]*))?/g var assert = require('assert') module.exports = qs function qs (url) { assert.equal(typeof url, 'string', 'nanoquery: url should be type string') var obj = {} url.replace(/^.*\?/, '').replace(reg, function (a0, a1, a2, a3) { obj[decodeURIComponent(a1)] = decodeURIComponent(a3) }) return obj } },{"assert":89}],97:[function(require,module,exports){ 'use strict' var assert = require('assert') module.exports = nanoraf // Only call RAF when needed // (fn, fn?) -> fn function nanoraf (render, raf) { assert.equal(typeof render, 'function', 'nanoraf: render should be a function') assert.ok(typeof raf === 'function' || typeof raf === 'undefined', 'nanoraf: raf should be a function or undefined') if (!raf) raf = window.requestAnimationFrame var redrawScheduled = false var args = null return function frame () { if (args === null && !redrawScheduled) { redrawScheduled = true raf(function redraw () { redrawScheduled = false var length = args.length var _args = new Array(length) for (var i = 0; i < length; i++) _args[i] = args[i] render.apply(render, _args) args = null }) } args = arguments } } },{"assert":1}],98:[function(require,module,exports){ var assert = require('assert') var wayfarer = require('wayfarer') // electron support var isLocalFile = (/file:\/\//.test( typeof window === 'object' && window.location && window.location.origin )) /* eslint-disable no-useless-escape */ var electron = '^(file:\/\/|\/)(.*\.html?\/?)?' var protocol = '^(http(s)?(:\/\/))?(www\.)?' var domain = '[a-zA-Z0-9-_\.]+(:[0-9]{1,5})?(\/{1})?' var qs = '[\?].*$' /* eslint-enable no-useless-escape */ var stripElectron = new RegExp(electron) var prefix = new RegExp(protocol + domain) var normalize = new RegExp('#') var suffix = new RegExp(qs) module.exports = Nanorouter function Nanorouter (opts) { if (!(this instanceof Nanorouter)) return new Nanorouter(opts) opts = opts || {} this.router = wayfarer(opts.default || '/404') } Nanorouter.prototype.on = function (routename, listener) { assert.equal(typeof routename, 'string') routename = routename.replace(/^[#/]/, '') this.router.on(routename, listener) } Nanorouter.prototype.emit = function (routename) { assert.equal(typeof routename, 'string') routename = pathname(routename, isLocalFile) return this.router.emit(routename) } Nanorouter.prototype.match = function (routename) { assert.equal(typeof routename, 'string') routename = pathname(routename, isLocalFile) return this.router.match(routename) } // replace everything in a route but the pathname and hash function pathname (routename, isElectron) { if (isElectron) routename = routename.replace(stripElectron, '') else routename = routename.replace(prefix, '') return routename.replace(suffix, '').replace(normalize, '/') } },{"assert":1,"wayfarer":107}],99:[function(require,module,exports){ var assert = require('assert') var hasWindow = typeof window !== 'undefined' function createScheduler () { var scheduler if (hasWindow) { if (!window._nanoScheduler) window._nanoScheduler = new NanoScheduler(true) scheduler = window._nanoScheduler } else { scheduler = new NanoScheduler() } return scheduler } function NanoScheduler (hasWindow) { this.hasWindow = hasWindow this.hasIdle = this.hasWindow && window.requestIdleCallback this.method = this.hasIdle ? window.requestIdleCallback.bind(window) : this.setTimeout this.scheduled = false this.queue = [] } NanoScheduler.prototype.push = function (cb) { assert.equal(typeof cb, 'function', 'nanoscheduler.push: cb should be type function') if (!this.hasWindow) return this.queue.push(cb) this.schedule() } NanoScheduler.prototype.schedule = function () { if (this.scheduled) return this.scheduled = true var self = this this.method(function (idleDeadline) { var cb while (self.queue.length && idleDeadline.timeRemaining() > 0) { cb = self.queue.shift() cb(idleDeadline) } self.scheduled = false if (self.queue.length) self.schedule() }) } NanoScheduler.prototype.setTimeout = function (cb) { setTimeout(cb, 0, { timeRemaining: function () { return 1 } }) } module.exports = createScheduler },{"assert":89}],100:[function(require,module,exports){ var scheduler = require('nanoscheduler')() var assert = require('assert') var perf nanotiming.disabled = true try { perf = window.performance nanotiming.disabled = window.localStorage.DISABLE_NANOTIMING === 'true' || !perf.mark } catch (e) { } module.exports = nanotiming function nanotiming (name) { assert.equal(typeof name, 'string', 'nanotiming: name should be type string') if (nanotiming.disabled) return noop var uuid = (perf.now() * 10000).toFixed() % Number.MAX_SAFE_INTEGER var startName = 'start-' + uuid + '-' + name perf.mark(startName) function end (cb) { var endName = 'end-' + uuid + '-' + name perf.mark(endName) scheduler.push(function () { var err = null try { var measureName = name + ' [' + uuid + ']' perf.measure(measureName, startName, endName) perf.clearMarks(startName) perf.clearMarks(endName) } catch (e) { err = e } if (cb) cb(err, name) }) } end.uuid = uuid return end } function noop (cb) { if (cb) { scheduler.push(function () { cb(new Error('nanotiming: performance API unavailable')) }) } } },{"assert":1,"nanoscheduler":99}],101:[function(require,module,exports){ var add = require('gl-vec2/add') var set = require('gl-vec2/set') var normalize = require('gl-vec2/normalize') var subtract = require('gl-vec2/subtract') var dot = require('gl-vec2/dot') var tmp = [0, 0] module.exports.computeMiter = function computeMiter(tangent, miter, lineA, lineB, halfThick) { //get tangent line add(tangent, lineA, lineB) normalize(tangent, tangent) //get miter as a unit vector set(miter, -tangent[1], tangent[0]) set(tmp, -lineA[1], lineA[0]) //get the necessary length of our miter return halfThick / dot(miter, tmp) } module.exports.normal = function normal(out, dir) { //get perpendicular set(out, -dir[1], dir[0]) return out } module.exports.direction = function direction(out, a, b) { //get unit dir of two lines subtract(out, a, b) normalize(out, out) return out } },{"gl-vec2/add":47,"gl-vec2/dot":48,"gl-vec2/normalize":50,"gl-vec2/set":51,"gl-vec2/subtract":52}],102:[function(require,module,exports){ var util = require('polyline-miter-util') var lineA = [0, 0] var lineB = [0, 0] var tangent = [0, 0] var miter = [0, 0] module.exports = function(points, closed) { var curNormal = null var out = [] if (closed) { points = points.slice() points.push(points[0]) } var total = points.length for (var i=1; i 2 && closed) { var last2 = points[total-2] var cur2 = points[0] var next2 = points[1] util.direction(lineA, cur2, last2) util.direction(lineB, next2, cur2) util.normal(curNormal, lineA) var miterLen2 = util.computeMiter(tangent, miter, lineA, lineB, 1) out[0][0] = miter.slice() out[total-1][0] = miter.slice() out[0][1] = miterLen2 out[total-1][1] = miterLen2 out.pop() } return out } function addNext(out, normal, length) { out.push([[normal[0], normal[1]], length]) } },{"polyline-miter-util":101}],103:[function(require,module,exports){ function createCylinderMesh( radiusTop, radiusBottom, height, radialSegments, heightSegments ) { var index = 0 var indexOffset = 0 var indexArray = [] var capCount = 0 if (radiusTop > 0) { capCount++ } if (radiusBottom > 0) { capCount++ } var vertexCount = ((radialSegments + 1) * (heightSegments + 1)) + ((radialSegments + 2) * capCount) var cellCount = (radialSegments * heightSegments * 2) + (radialSegments * capCount) var normals = new Array(vertexCount) var vertices = new Array(vertexCount) var uvs = new Array(vertexCount) var cells = new Array(cellCount) var slope = (radiusBottom - radiusTop) / height var thetaLength = 2.0 * Math.PI for (var y = 0; y <= heightSegments; y++) { var indexRow = [] var v = y / heightSegments var radius = v * (radiusBottom - radiusTop) + radiusTop for (var x = 0; x <= radialSegments; x++) { var u = x / radialSegments var theta = u * thetaLength var sinTheta = Math.sin(theta) var cosTheta = Math.cos(theta) vertices[index] = [radius * sinTheta, -v * height + (height / 2), radius * cosTheta] normals[index] = [sinTheta, slope, cosTheta] uvs[index] = [u, 1 - v] indexRow.push(index) index++ } indexArray.push(indexRow) } for (var x = 0; x < radialSegments; x++) { for (var y = 0; y < heightSegments; y++) { var i1 = indexArray[y][x] var i2 = indexArray[y + 1][x] var i3 = indexArray[y + 1][x + 1] var i4 = indexArray[y][x + 1] // face one cells[indexOffset] = [i1, i2, i4] indexOffset++ // face two cells[indexOffset] = [i2, i3, i4] indexOffset++ } } var generateCap = function (top) { var vertex = new Array(3).fill(0) var radius = (top === true) ? radiusTop : radiusBottom var sign = (top === true) ? 1 : -1 var centerIndexStart = index for (var x = 1; x <= radialSegments; x++) { vertices[index] = [0, height * sign / 2, 0] normals[index] = [0, sign, 0] uvs[index] = [0.5, 0.5] index++ } var centerIndexEnd = index for (var x = 0; x <= radialSegments; x++) { var u = x / radialSegments var theta = u * thetaLength var cosTheta = Math.cos(theta) var sinTheta = Math.sin(theta) vertices[index] = [radius * sinTheta, height * sign / 2, radius * cosTheta] normals[index] = [0, sign, 0] uvs[index] = [(cosTheta * 0.5) + 0.5, (sinTheta * 0.5 * sign) + 0.5] index++ } for (var x = 0; x < radialSegments; x++) { var c = centerIndexStart + x var i = centerIndexEnd + x if ( top === true ) { // face top cells[indexOffset] = [i, i + 1, c] indexOffset++ } else { // face bottom cells[indexOffset] = [i + 1, i, c] indexOffset++ } } } if (radiusTop > 0) { generateCap(true) } if (radiusBottom > 0) { generateCap(false) } return { uvs: uvs, cells: cells, normals: normals, positions: vertices } } module.exports = createCylinderMesh },{}],104:[function(require,module,exports){ (function(da,ea){"object"===typeof exports&&"undefined"!==typeof module?module.exports=ea():"function"===typeof define&&define.amd?define(ea):da.createREGL=ea()})(this,function(){function da(a,b){this.id=vb++;this.type=a;this.data=b}function ea(a){if(0===a.length)return[];var b=a.charAt(0),c=a.charAt(a.length-1);if(1>>=b;c=(255>>=c; b|=c;c=(15>>=c;b|=c;c=(3>>c>>1}function fa(a){a:{for(var b=16;268435456>=b;b*=16)if(a<=b){a=b;break a}a=0}b=$a[Za(a)>>2];return 0>2].push(a)}function bb(a,b,c,d,f,k){for(var p=0;pg&&(g=d.buffer.byteLength,5123===t?g>>=1:5125===t&&(g>>=2));d.vertCount= g;g=e;0>e&&(g=4,e=d.buffer.dimension,1===e&&(g=0),2===e&&(g=1),3===e&&(g=4));d.primType=g}function p(a){d.elementsCount--;delete h[a.id];a.buffer.destroy();a.buffer=null}var h={},g=0,r={uint8:5121,uint16:5123};b.oes_element_index_uint&&(r.uint32=5125);f.prototype.bind=function(){this.buffer.bind()};var v=[];return{create:function(a,b){function g(a){if(a)if("number"===typeof a)e(a),n.primType=4,n.vertCount=a|0,n.type=5121;else{var b=null,c=35044,d=-1,f=-1,l=0,p=0;if(Array.isArray(a)||O(a)||ja(a))b= a;else if("data"in a&&(b=a.data),"usage"in a&&(c=hb[a.usage]),"primitive"in a&&(d=Ra[a.primitive]),"count"in a&&(f=a.count|0),"type"in a&&(p=r[a.type]),"length"in a)l=a.length|0;else if(l=f,5123===p||5122===p)l*=2;else if(5125===p||5124===p)l*=4;k(n,b,c,d,f,l,p)}else e(),n.primType=4,n.vertCount=0,n.type=5121;return g}var e=c.create(null,34963,!0),n=new f(e._buffer);d.elementsCount++;g(a);g._reglType="elements";g._elements=n;g.subdata=function(a,b){e.subdata(a,b);return g};g.destroy=function(){p(n)}; return g},createStream:function(a){var b=v.pop();b||(b=new f(c.create(null,34963,!0,!1)._buffer));k(b,a,35040,-1,-1,0,0);return b},destroyStream:function(a){v.push(a)},getElements:function(a){return"function"===typeof a&&a._elements instanceof f?a._elements:null},clear:function(){H(h).forEach(p)}}}function ib(a){for(var b=x.allocType(5123,a.length),c=0;c>> 31<<15,k=(d<<1>>>24)-127,d=d>>13&1023;b[c]=-24>k?f:-14>k?f+(d+1024>>-14-k):15>=f,c.height>>=f,u(c,d[f]),a.mipmask|=1<b;++b)a.images[b]=null;return a}function gb(a){for(var b= a.images,c=0;cb){for(var c=0;c=--this.refCount&&z(this)}});p.profile&&(k.getTotalTextureSize=function(){var a=0;Object.keys(V).forEach(function(b){a+= V[b].stats.size});return a});return{create2D:function(b,c){function d(a,b){var c=f.texInfo;C.call(c);var e=B();"number"===typeof a?"number"===typeof b?w(e,a|0,b|0):w(e,a|0,a|0):a?(M(c,a),t(e,a)):w(e,1,1);c.genMipmaps&&(e.mipmask=(e.width<<1)-1);f.mipmask=e.mipmask;g(f,e);f.internalformat=e.internalformat;d.width=e.width;d.height=e.height;Q(f);Z(e,3553);P(c,3553);Aa();gb(e);p.profile&&(f.stats.size=Ia(f.internalformat,f.type,e.width,e.height,c.genMipmaps,!1));d.format=J[f.internalformat];d.type=W[f.type]; d.mag=la[c.magFilter];d.min=ya[c.minFilter];d.wrapS=ha[c.wrapS];d.wrapT=ha[c.wrapT];return d}var f=new G(3553);V[f.id]=f;k.textureCount++;d(b,c);d.subimage=function(a,b,c,l){b|=0;c|=0;l|=0;var q=e();g(q,f);q.width=0;q.height=0;u(q,a);q.width=q.width||(f.width>>l)-b;q.height=q.height||(f.height>>l)-c;Q(f);m(q,3553,b,c,l);Aa();n(q);return d};d.resize=function(b,c){var e=b|0,g=c|0||e;if(e===f.width&&g===f.height)return d;d.width=f.width=e;d.height=f.height=g;Q(f);for(var q=0;f.mipmask>>q;++q)a.texImage2D(3553, q,f.format,e>>q,g>>q,0,f.format,f.type,null);Aa();p.profile&&(f.stats.size=Ia(f.internalformat,f.type,e,g,!1,!1));return d};d._reglType="texture2d";d._texture=f;p.profile&&(d.stats=f.stats);d.destroy=function(){f.decRef()};return d},createCube:function(b,c,d,f,l,sa){function z(a,b,c,e,d,f){var F,X=h.texInfo;C.call(X);for(F=0;6>F;++F)q[F]=B();if("number"===typeof a||!a)for(a=a|0||1,F=0;6>F;++F)w(q[F],a,a);else if("object"===typeof a)if(b)t(q[0],a),t(q[1],b),t(q[2],c),t(q[3],e),t(q[4],d),t(q[5],f); else if(M(X,a),r(h,a),"faces"in a)for(a=a.faces,F=0;6>F;++F)g(q[F],h),t(q[F],a[F]);else for(F=0;6>F;++F)t(q[F],a);g(h,q[0]);h.mipmask=X.genMipmaps?(q[0].width<<1)-1:q[0].mipmask;h.internalformat=q[0].internalformat;z.width=q[0].width;z.height=q[0].height;Q(h);for(F=0;6>F;++F)Z(q[F],34069+F);P(X,34067);Aa();p.profile&&(h.stats.size=Ia(h.internalformat,h.type,z.width,z.height,X.genMipmaps,!0));z.format=J[h.internalformat];z.type=W[h.type];z.mag=la[X.magFilter];z.min=ya[X.minFilter];z.wrapS=ha[X.wrapS]; z.wrapT=ha[X.wrapT];for(F=0;6>F;++F)gb(q[F]);return z}var h=new G(34067);V[h.id]=h;k.cubeCount++;var q=Array(6);z(b,c,d,f,l,sa);z.subimage=function(a,b,c,q,d){c|=0;q|=0;d|=0;var f=e();g(f,h);f.width=0;f.height=0;u(f,b);f.width=f.width||(h.width>>d)-c;f.height=f.height||(h.height>>d)-q;Q(h);m(f,34069+a,c,q,d);Aa();n(f);return z};z.resize=function(b){b|=0;if(b!==h.width){z.width=h.width=b;z.height=h.height=b;Q(h);for(var c=0;6>c;++c)for(var q=0;h.mipmask>>q;++q)a.texImage2D(34069+c,q,h.format,b>>q, b>>q,0,h.format,h.type,null);Aa();p.profile&&(h.stats.size=Ia(h.internalformat,h.type,z.width,z.height,!1,!0));return z}};z._reglType="textureCube";z._texture=h;p.profile&&(z.stats=h.stats);z.destroy=function(){h.decRef()};return z},clear:function(){for(var b=0;bc;++c)if(0!==(b.mipmask&1<>c,b.height>>c,0,b.internalformat,b.type,null);else for(var e=0;6>e;++e)a.texImage2D(34069+e,c,b.internalformat,b.width>>c,b.height>>c,0,b.internalformat,b.type,null);P(b.texInfo,b.target)})}}}function Jb(a,b,c,d,f,k){function p(a,b,c){this.target=a;this.texture=b;this.renderbuffer=c;var e=a=0;b?(a=b.width,e=b.height):c&&(a=c.width,e=c.height);this.width=a;this.height=e}function h(a){a&& (a.texture&&a.texture._texture.decRef(),a.renderbuffer&&a.renderbuffer._renderbuffer.decRef())}function g(a,b,c){a&&(a.texture?a.texture._texture.refCount+=1:a.renderbuffer._renderbuffer.refCount+=1)}function r(b,c){c&&(c.texture?a.framebufferTexture2D(36160,b,c.target,c.texture._texture.texture,0):a.framebufferRenderbuffer(36160,b,36161,c.renderbuffer._renderbuffer.renderbuffer))}function v(a){var b=3553,c=null,e=null,g=a;"object"===typeof a&&(g=a.data,"target"in a&&(b=a.target|0));a=g._reglType; "texture2d"===a?c=g:"textureCube"===a?c=g:"renderbuffer"===a&&(e=g,b=36161);return new p(b,c,e)}function l(a,b,c,e,g){if(c)return a=d.create2D({width:a,height:b,format:e,type:g}),a._texture.refCount=0,new p(3553,a,null);a=f.create({width:a,height:b,format:e});a._renderbuffer.refCount=0;return new p(36161,null,a)}function u(a){return a&&(a.texture||a.renderbuffer)}function m(a,b,c){a&&(a.texture?a.texture.resize(b,c):a.renderbuffer&&a.renderbuffer.resize(b,c))}function e(){this.id=M++;P[this.id]=this; this.framebuffer=a.createFramebuffer();this.height=this.width=0;this.colorAttachments=[];this.depthStencilAttachment=this.stencilAttachment=this.depthAttachment=null}function n(a){a.colorAttachments.forEach(h);h(a.depthAttachment);h(a.stencilAttachment);h(a.depthStencilAttachment)}function D(b){a.deleteFramebuffer(b.framebuffer);b.framebuffer=null;k.framebufferCount--;delete P[b.id]}function w(b){var e;a.bindFramebuffer(36160,b.framebuffer);var g=b.colorAttachments;for(e=0;ee;++e){for(n=0;na;++a)c[a].resize(e);b.width=b.height=e;return b},_reglType:"framebufferCube",destroy:function(){c.forEach(function(a){a.destroy()})}})},clear:function(){H(P).forEach(D)},restore:function(){H(P).forEach(function(b){b.framebuffer=a.createFramebuffer();w(b)})}})}function pb(){this.w= this.z=this.y=this.x=this.state=0;this.buffer=null;this.size=0;this.normalized=!1;this.type=5126;this.divisor=this.stride=this.offset=0}function Kb(a,b,c,d,f){a=c.maxAttributes;b=Array(a);for(c=0;ca&&(a=b.stats.uniformsCount)});return a},c.getMaxAttributesCount=function(){var a=0;u.forEach(function(b){b.stats.attributesCount>a&&(a=b.stats.attributesCount)});return a});return{clear:function(){var b=a.deleteShader.bind(a);H(r).forEach(b);r={};H(v).forEach(b);v={};u.forEach(function(b){a.deleteProgram(b.program)});u.length=0;l={};c.shaderCount=0},program:function(a,b,f){var d=l[b];d||(d=l[b]={});var m=d[a];m||(m=new h(b,a),c.shaderCount++,g(m,f),d[a]= m,u.push(m));return m},restore:function(){r={};v={};for(var a=0;a="+b+"?"+d+".constant["+b+"]:0;"}).join(""), "}}else{","if(",q,"(",d,".buffer)){",h,"=",g,".createStream(",34962,",",d,".buffer);","}else{",h,"=",g,".getBuffer(",d,".buffer);","}",K,'="type" in ',d,"?",f.glTypes,"[",d,".type]:",h,".dtype;",y.normalized,"=!!",d,".normalized;");e("size");e("offset");e("stride");e("divisor");c("}}");c.exit("if(",y.isStream,"){",g,".destroyStream(",h,");","}");return y})});return g}function O(a){var b=a["static"],c=a.dynamic,e={};Object.keys(b).forEach(function(a){var c=b[a];e[a]=B(function(a,b){return"number"=== typeof c||"boolean"===typeof c?""+c:a.link(c)})});Object.keys(c).forEach(function(a){var b=c[a];e[a]=N(b,function(a,c){return a.invoke(c,b)})});return e}function z(a,b,c,e,d){var f=A(a,d),g=x(a,f,d),l=M(a,d),h=P(a,d),k=C(a,d),m=g.viewport;m&&(h.viewport=m);m=n("scissor.box");(g=g[m])&&(h[m]=g);g=0>1)",u],");")}function b(){c(w,".drawArraysInstancedANGLE(",[p,r,t,u],");")}n?v?a():(c("if(",n,"){"),a(),c("}else{"),b(),c("}")):b()}function g(){function a(){c(l+".drawElements("+[p,t,W,r+"<<(("+W+"-5121)>>1)"]+");")}function b(){c(l+".drawArrays("+[p,r,t]+");")}n?v?a():(c("if(",n,"){"),a(),c("}else{"),b(),c("}")): b()}var h=a.shared,l=h.gl,k=h.draw,m=e.draw,n=function(){var d=m.elements,f=b;if(d){if(d.contextDep&&e.contextDynamic||d.propDep)f=c;d=d.append(a,f)}else d=f.def(k,".","elements");d&&f("if("+d+")"+l+".bindBuffer(34963,"+d+".buffer.buffer);");return d}(),p=d("primitive"),r=d("offset"),t=function(){var d=m.count,f=b;if(d){if(d.contextDep&&e.contextDynamic||d.propDep)f=c;d=d.append(a,f)}else d=f.def(k,".","count");return d}();if("number"===typeof t){if(0===t)return}else c("if(",t,"){"),c.exit("}");var u, w;ma&&(u=d("instances"),w=a.instancing);var W=n+".type",v=m.elements&&ta(m.elements);ma&&("number"!==typeof u||0<=u)?"string"===typeof u?(c("if(",u,">0){"),f(),c("}else if(",u,"<0){"),g(),c("}")):f():g()}function ba(a,b,c,e,d){b=t();d=b.proc("body",d);ma&&(b.instancing=d.def(b.shared.extensions,".angle_instanced_arrays"));a(b,d,c,e);return b.compile().body}function R(a,b,c,e){ua(a,b);S(a,b,c,e.attributes,function(){return!0});U(a,b,c,e.uniforms,function(){return!0});H(a,b,b,c)}function W(a,b){var c= a.proc("draw",1);ua(a,c);sa(a,c,b.context);I(a,c,b.framebuffer);T(a,c,b);L(a,c,b.state);E(a,c,b,!1,!0);var e=b.shader.progVar.append(a,c);c(a.shared.gl,".useProgram(",e,".program);");if(b.shader.program)R(a,c,b,b.shader.program);else{var d=a.global.def("{}"),f=c.def(e,".id"),g=c.def(d,"[",f,"]");c(a.cond(g).then(g,".call(this,a0);")["else"](g,"=",d,"[",f,"]=",a.link(function(c){return ba(R,a,b,c,1)}),"(",e,");",g,".call(this,a0);"))}0=--this.refCount&&p(this)};f.profile&&(d.getTotalRenderbufferSize=function(){var a=0;Object.keys(v).forEach(function(b){a+=v[b].stats.size}); return a});return{create:function(b,c){function m(b,c){var d=0,l=0,k=32854;"object"===typeof b&&b?("shape"in b?(l=b.shape,d=l[0]|0,l=l[1]|0):("radius"in b&&(d=l=b.radius|0),"width"in b&&(d=b.width|0),"height"in b&&(l=b.height|0)),"format"in b&&(k=h[b.format])):"number"===typeof b?(d=b|0,l="number"===typeof c?c|0:d):b||(d=l=1);if(d!==e.width||l!==e.height||k!==e.format)return m.width=e.width=d,m.height=e.height=l,e.format=k,a.bindRenderbuffer(36161,e.renderbuffer),a.renderbufferStorage(36161,k,d,l), f.profile&&(e.stats.size=L[e.format]*e.width*e.height),m.format=g[e.format],m}var e=new k(a.createRenderbuffer());v[e.id]=e;d.renderbufferCount++;m(b,c);m.resize=function(b,c){var d=b|0,g=c|0||d;if(d===e.width&&g===e.height)return m;m.width=e.width=d;m.height=e.height=g;a.bindRenderbuffer(36161,e.renderbuffer);a.renderbufferStorage(36161,e.format,d,g);f.profile&&(e.stats.size=L[e.format]*e.width*e.height);return m};m._reglType="renderbuffer";m._renderbuffer=e;f.profile&&(m.stats=e.stats);m.destroy= function(){e.decRef()};return m},clear:function(){H(v).forEach(p)},restore:function(){H(v).forEach(function(b){b.renderbuffer=a.createRenderbuffer();a.bindRenderbuffer(36161,b.renderbuffer);a.renderbufferStorage(36161,b.format,b.width,b.height)});a.bindRenderbuffer(36161,null)}}},ob=[];ob[6408]=4;var Ma=[];Ma[5121]=1;Ma[5126]=4;Ma[36193]=2;var Da=["x","y","z","w"],Pb="blend.func blend.equation stencil.func stencil.opFront stencil.opBack sample.coverage viewport scissor.box polygonOffset.offset".split(" "), Fa={0:0,1:1,zero:0,one:1,"src color":768,"one minus src color":769,"src alpha":770,"one minus src alpha":771,"dst color":774,"one minus dst color":775,"dst alpha":772,"one minus dst alpha":773,"constant color":32769,"one minus constant color":32770,"constant alpha":32771,"one minus constant alpha":32772,"src alpha saturate":776},Ua={never:512,less:513,"<":513,equal:514,"=":514,"==":514,"===":514,lequal:515,"<=":515,greater:516,">":516,notequal:517,"!=":517,"!==":517,gequal:518,">=":518,always:519}, Oa={0:0,zero:0,keep:7680,replace:7681,increment:7682,decrement:7683,"increment wrap":34055,"decrement wrap":34056,invert:5386},rb={cw:2304,ccw:2305},sb=new Y(!1,!1,!1,function(){}),Sb=function(a,b){function c(){this.endQueryIndex=this.startQueryIndex=-1;this.sum=0;this.stats=null}function d(a,b,d){var e=h.pop()||new c;e.startQueryIndex=a;e.endQueryIndex=b;e.sum=0;e.stats=d;g.push(e)}var f=b.ext_disjoint_timer_query;if(!f)return null;var k=[],p=[],h=[],g=[],r=[],v=[];return{beginQuery:function(a){var b= k.pop()||f.createQueryEXT();f.beginQueryEXT(35007,b);p.push(b);d(p.length-1,p.length,a)},endQuery:function(){f.endQueryEXT(35007)},pushScopeStats:d,update:function(){var a,b;a=p.length;if(0!==a){v.length=Math.max(v.length,a+1);r.length=Math.max(r.length,a+1);r[0]=0;var c=v[0]=0;for(b=a=0;b=E.length&&d()}var c=tb(E,a);E[c]=b}}}function r(){var a=O.viewport,b=O.scissor_box;a[0]=a[1]=b[0]=b[1]=0;M.viewportWidth=M.framebufferWidth=M.drawingBufferWidth= a[2]=b[2]=m.drawingBufferWidth;M.viewportHeight=M.framebufferHeight=M.drawingBufferHeight=a[3]=b[3]=m.drawingBufferHeight}function v(){M.tick+=1;M.time=u();r();T.procs.poll()}function l(){r();T.procs.refresh();x&&x.update()}function u(){return(ub()-C)/1E3}a=zb(a);if(!a)return null;var m=a.gl,e=m.getContextAttributes();m.isContextLost();var n=Ab(m,a);if(!n)return null;var D=wb(),w={bufferCount:0,elementsCount:0,framebufferCount:0,shaderCount:0,textureCount:0,cubeCount:0,renderbufferCount:0,maxTextureUnits:0}, t=n.extensions,x=Sb(m,t),C=ub(),B=m.drawingBufferWidth,J=m.drawingBufferHeight,M={tick:0,time:0,viewportWidth:B,viewportHeight:J,framebufferWidth:B,framebufferHeight:J,drawingBufferWidth:B,drawingBufferHeight:J,pixelRatio:a.pixelRatio},P=Qb(m,t),G=Bb(m,w,a),Q=Cb(m,t,G,w),B=Kb(m,t,P,G,D),N=Lb(m,D,w,a),z=Fb(m,t,P,function(){T.procs.poll()},M,w,a),L=Rb(m,t,P,w,a),I=Jb(m,t,P,z,L,w),T=Ob(m,D,t,P,G,Q,z,I,{},B,N,{elements:null,primitive:4,count:-1,offset:0,instances:-1},M,x,a),D=Mb(m,I,T.procs.poll,M,e, t),O=T.next,H=m.canvas,E=[],S=[],U=[],R=[a.onDestroy],ba=null;H&&(H.addEventListener("webglcontextlost",f,!1),H.addEventListener("webglcontextrestored",k,!1));var Y=I.setFBO=p({framebuffer:ia.define.call(null,1,"framebuffer")});l();e=A(p,{clear:function(a){if("framebuffer"in a)if(a.framebuffer&&"framebufferCube"===a.framebuffer_reglType)for(var b=0;6>b;++b)Y(A({framebuffer:a.framebuffer.faces[b]},a),h);else Y(a,h);else h(null,a)},prop:ia.define.bind(null,1),context:ia.define.bind(null,2),"this":ia.define.bind(null, 3),draw:p({}),buffer:function(a){return G.create(a,34962,!1,!1)},elements:function(a){return Q.create(a,!1)},texture:z.create2D,cube:z.createCube,renderbuffer:L.create,framebuffer:I.create,framebufferCube:I.createCube,attributes:e,frame:g,on:function(a,b){var c;switch(a){case "frame":return g(b);case "lost":c=S;break;case "restore":c=U;break;case "destroy":c=R}c.push(b);return{cancel:function(){for(var a=0;a} arr The target array * @param {number} startIdx The index to begin removing from (inclusive) * @param {number} removeCount How many items to remove */ module.exports = function removeItems(arr, startIdx, removeCount) { var i, length = arr.length if (startIdx >= length || removeCount === 0) { return } removeCount = (startIdx + removeCount > length ? length - startIdx : removeCount) var len = length - removeCount for (i = startIdx; i < len; ++i) { arr[i] = arr[i + removeCount] } arr.length = len } },{}],106:[function(require,module,exports){ module.exports = scrollToAnchor function scrollToAnchor (anchor, options) { if (anchor) { try { var el = document.querySelector(anchor) if (el) el.scrollIntoView(options) } catch (e) {} } } },{}],107:[function(require,module,exports){ var assert = require('assert') var trie = require('./trie') module.exports = Wayfarer // create a router // str -> obj function Wayfarer (dft) { if (!(this instanceof Wayfarer)) return new Wayfarer(dft) var _default = (dft || '').replace(/^\//, '') var _trie = trie() emit._trie = _trie emit.on = on emit.emit = emit emit.match = match emit._wayfarer = true return emit // define a route // (str, fn) -> obj function on (route, cb) { assert.equal(typeof route, 'string') assert.equal(typeof cb, 'function') route = route || '/' cb.route = route if (cb && cb._wayfarer && cb._trie) { _trie.mount(route, cb._trie.trie) } else { var node = _trie.create(route) node.cb = cb } return emit } // match and call a route // (str, obj?) -> null function emit (route) { var matched = match(route) var args = new Array(arguments.length) args[0] = matched.params for (var i = 1; i < args.length; i++) { args[i] = arguments[i] } return matched.cb.apply(matched.cb, args) } function match (route) { assert.notEqual(route, undefined, "'route' must be defined") var matched = _trie.match(route) if (matched && matched.cb) return new Route(matched) var dft = _trie.match(_default) if (dft && dft.cb) return new Route(dft) throw new Error("route '" + route + "' did not match") } function Route (matched) { this.cb = matched.cb this.route = matched.cb.route this.params = matched.params } } },{"./trie":108,"assert":1}],108:[function(require,module,exports){ var mutate = require('xtend/mutable') var assert = require('assert') var xtend = require('xtend') module.exports = Trie // create a new trie // null -> obj function Trie () { if (!(this instanceof Trie)) return new Trie() this.trie = { nodes: {} } } // create a node on the trie at route // and return a node // str -> null Trie.prototype.create = function (route) { assert.equal(typeof route, 'string', 'route should be a string') // strip leading '/' and split routes var routes = route.replace(/^\//, '').split('/') function createNode (index, trie) { var thisRoute = (routes.hasOwnProperty(index) && routes[index]) if (thisRoute === false) return trie var node = null if (/^:|^\*/.test(thisRoute)) { // if node is a name match, set name and append to ':' node if (!trie.nodes.hasOwnProperty('$$')) { node = { nodes: {} } trie.nodes['$$'] = node } else { node = trie.nodes['$$'] } if (thisRoute[0] === '*') { trie.wildcard = true } trie.name = thisRoute.replace(/^:|^\*/, '') } else if (!trie.nodes.hasOwnProperty(thisRoute)) { node = { nodes: {} } trie.nodes[thisRoute] = node } else { node = trie.nodes[thisRoute] } // we must recurse deeper return createNode(index + 1, node) } return createNode(0, this.trie) } // match a route on the trie // and return the node // str -> obj Trie.prototype.match = function (route) { assert.equal(typeof route, 'string', 'route should be a string') var routes = route.replace(/^\//, '').split('/') var params = {} function search (index, trie) { // either there's no match, or we're done searching if (trie === undefined) return undefined var thisRoute = routes[index] if (thisRoute === undefined) return trie if (trie.nodes.hasOwnProperty(thisRoute)) { // match regular routes first return search(index + 1, trie.nodes[thisRoute]) } else if (trie.name) { // match named routes try { params[trie.name] = decodeURIComponent(thisRoute) } catch (e) { return search(index, undefined) } return search(index + 1, trie.nodes['$$']) } else if (trie.wildcard) { // match wildcards try { params['wildcard'] = decodeURIComponent(routes.slice(index).join('/')) } catch (e) { return search(index, undefined) } // return early, or else search may keep recursing through the wildcard return trie.nodes['$$'] } else { // no matches found return search(index + 1) } } var node = search(0, this.trie) if (!node) return undefined node = xtend(node) node.params = params return node } // mount a trie onto a node at route // (str, obj) -> null Trie.prototype.mount = function (route, trie) { assert.equal(typeof route, 'string', 'route should be a string') assert.equal(typeof trie, 'object', 'trie should be a object') var split = route.replace(/^\//, '').split('/') var node = null var key = null if (split.length === 1) { key = split[0] node = this.create(key) } else { var head = split.join('/') key = split[0] node = this.create(head) } mutate(node.nodes, trie.nodes) if (trie.name) node.name = trie.name // delegate properties from '/' to the new node // '/' cannot be reached once mounted if (node.nodes['']) { Object.keys(node.nodes['']).forEach(function (key) { if (key === 'nodes') return node[key] = node.nodes[''][key] }) mutate(node.nodes, node.nodes[''].nodes) delete node.nodes[''].nodes } } },{"assert":1,"xtend":109,"xtend/mutable":110}],109:[function(require,module,exports){ module.exports = extend var hasOwnProperty = Object.prototype.hasOwnProperty; function extend() { var target = {} for (var i = 0; i < arguments.length; i++) { var source = arguments[i] for (var key in source) { if (hasOwnProperty.call(source, key)) { target[key] = source[key] } } } return target } },{}],110:[function(require,module,exports){ module.exports = extend var hasOwnProperty = Object.prototype.hasOwnProperty; function extend(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] for (var key in source) { if (hasOwnProperty.call(source, key)) { target[key] = source[key] } } } return target } },{}],111:[function(require,module,exports){ var nanobus = require('nanobus') module.exports = App function App (opts) { var self = this if (!(this instanceof App)) return new App(opts) this.emitter = opts.emitter || new nanobus() this.state = opts.state || {} if (!this.state.app) this.state.app = {} if (!this.state.app.uniforms) this.state.app.uniforms = {} if (this.state.app.width === undefined) { this.state.app.width = window.innerWidth } if (this.state.app.height === undefined) { this.state.app.height = window.innerHeight } this.emitter.on('regl', function (regl) { self.state.app.regl = regl }) this.use(require('./lib/frame.js')) this.use(require('./lib/pick.js')) } App.prototype.use = function (fn) { fn(this.state, this.emitter) } App.prototype.draw = function (fn) { this.emitter.emit('app-add-draw', fn) } },{"./lib/frame.js":112,"./lib/pick.js":113,"nanobus":115}],112:[function(require,module,exports){ module.exports = function (state, emitter) { if (!state.app) state.app = {} state.app.draw = { instances: [], constructors: [] } state.app.frame = { withUniforms: null, waiting: false } emitter.on('app-add-draw', function (F) { if (typeof F === 'function') { state.app.draw.constructors.push(F) } else { emitter.emit('error', new Error('non-function draw constructor: ' + F)) } }) emitter.on('regl', function (regl) { var cons = state.app.draw.constructors state.app.draw.instances = cons.map(function (F) { return new F(regl) }) state.app.frame.withUniforms = regl({ uniforms: state.app.uniforms }) emitter.emit('frame') }) emitter.on('frame', function () { if (state.app.frame.waiting === false) { state.app.frame.waiting = true window.requestAnimationFrame(frame) } }) function frame () { if (!state.app.regl) return state.app.regl.poll() state.app.frame.waiting = false state.app.frame.withUniforms(function () { emitter.emit('pre-frame') var draws = state.app.draw.instances for (var i = 0; i < draws.length; i++) { var d = draws[i] if (typeof d.preDraw === 'function') d.preDraw(state) } for (var i = 0; i < draws.length; i++) { var d = draws[i] if (typeof d.draw === 'function') d.draw(state) } for (var i = 0; i < draws.length; i++) { var d = draws[i] if (typeof d.postDraw === 'function') d.postDraw(state) } emitter.emit('post-frame') }) } } },{}],113:[function(require,module,exports){ module.exports = function (state, emitter) { state.app.pick = { picking: false, fb: null, usingFB: null } emitter.on('regl', function (regl) { state.app.pick.fb = regl.framebuffer({ colorFormat: 'rgba', colorType: 'float32', width: state.app.width, height: state.app.height }) state.app.pick.usingFB = regl({ framebuffer: state.app.pick.fb }) }) emitter.on('resize', function () { if (state.app.pick.fb) { state.app.pick.fb.resize(state.app.width, state.app.height) } }) emitter.on('pick-event', function (ev) { if (!state.app.pick.fb) return if (!state.app.pick.usingFB) return state.app.pick.fb.use(function () { state.app.pick.usingFB(function () { state.app.frame.withUniforms(function () { pick(ev) }) }) }) }) function pick (ev) { var regl = state.app.regl var fb = state.app.pick.fb if (!regl || !fb) return regl.clear({ color: [0,0,0,0], depth: true, framebuffer: fb }) var draws = state.app.draw.instances for (var i = 0; i < draws.length; i++) { var d = draws[i] if (typeof d.prePick === 'function') d.prePick(state) } for (var i = 0; i < draws.length; i++) { var d = draws[i] if (typeof d.pick === 'function') d.pick(state) } for (var i = 0; i < draws.length; i++) { var d = draws[i] if (typeof d.postPick === 'function') d.postPick(state) } var x = Math.max(0, Math.min(state.app.width-1, ev.offsetX)) var y = Math.max(0, Math.min(state.app.height-1, state.app.height - ev.offsetY)) var data = regl.read({ x: x, y: y, width: 1, height: 1 }) emitter.emit('pick', { data: data, x: x, y: y, event: ev }) } } },{}],114:[function(require,module,exports){ arguments[4][89][0].apply(exports,arguments) },{"dup":89}],115:[function(require,module,exports){ arguments[4][90][0].apply(exports,arguments) },{"assert":1,"dup":90,"nanotiming":117,"remove-array-items":118}],116:[function(require,module,exports){ arguments[4][99][0].apply(exports,arguments) },{"assert":114,"dup":99}],117:[function(require,module,exports){ arguments[4][100][0].apply(exports,arguments) },{"assert":1,"dup":100,"nanoscheduler":116}],118:[function(require,module,exports){ arguments[4][105][0].apply(exports,arguments) },{"dup":105}],119:[function(require,module,exports){ var Nano = require('nanocomponent') var nanobus = require('nanobus') var mregl = require('./multi.js') module.exports = Root function Root (regl, opts) { if (!(this instanceof Root)) return new Root(regl, opts) Nano.call(this) this.components = [] this._regl = regl this._opts = opts } Root.prototype = Object.create(Nano.prototype) Root.prototype.create = function () { var c = new Component() this.components.push(c) if (this._mregl) c._setMregl(this._mregl) return c } Root.prototype.createElement = function () { var self = this if (!this._element) { this._element = document.createElement('div') this.canvas = document.createElement('canvas') this._element.appendChild(this.canvas) } return this._element } Root.prototype.update = function () { return false } Root.prototype.load = function () { this._mregl = mregl(this._regl, this.canvas, this._opts) for (var i = 0; i < this.components.length; i++) { this.components[i]._setMregl(this._mregl) } } Root.prototype.unload = function () { this._mregl.destroy() this._element = null this.canvas = null for (var i = 0; i < this.components.length; i++) { this.components[i]._setMregl(null) } this._mregl = null } function Component (opts) { var self = this if (!(self instanceof Component)) return new Component(opts) Nano.call(self) if (!opts) opts = {} self._name = 'nanobus' self._listeners = {} self._starListeners = [] self._elwidth = null self._elheight = null self._opts = opts self._element = document.createElement('div') self._element.style.display = 'inline-block' if (opts.width) { self._element.style.width = opts.width + 'px' self._elwidth = opts.width } if (opts.height) { self._element.style.height = opts.height + 'px' self._elheight = opts.height } self._regl = null self._mregl = null self._mreglqueue = [] } Component.prototype = Object.create(Nano.prototype) Component.prototype.emit = nanobus.prototype.emit Component.prototype._emit = nanobus.prototype._emit Component.prototype.on = nanobus.prototype.on Component.prototype.addListener = nanobus.prototype.addListener Component.prototype.prependListener = nanobus.prototype.prependListener Component.prototype.once = nanobus.prototype.once Component.prototype.prependOnceListener = nanobus.prototype.prependOnceListener Component.prototype.removeListener = nanobus.prototype.removeListener Component.prototype.removeAllListeners = nanobus.prototype.removeAllListeners Component.prototype.listeners = nanobus.prototype.listeners Component.prototype._getMregl = function (fn) { if (this._mregl) fn(this._mregl) else { if (!this._mreglqueue) this._mreglqueue = [] this._mreglqueue.push(fn) } } Component.prototype._setMregl = function (mr) { this._mregl = mr if (this._mreglqueue) { for (var i = 0; i < this._mreglqueue.length; i++) { this._mreglqueue[i](this._mregl) } } this._mreglqueue = null } Component.prototype.update = function (props) { return this._elwidth !== props.width || this._elheight !== props.height } Component.prototype.createElement = function (props) { var self = this if (props.width !== this._elwidth) { this._element.style.width = props.width + 'px' this._elwidth = props.width } if (props.height !== this._elheight) { this._element.style.height = props.height + 'px' this._elheight = props.height } this.emit('element', this._element) return this._element } Component.prototype.load = function () { var self = this if (self._regl) return self._getMregl(function (mregl) { self._regl = mregl(self._element) self.emit('regl', self._regl) }) } Component.prototype.unload = function () { if (this._regl) { this._regl.destroy() this._regl = null } } },{"./multi.js":120,"nanobus":124,"nanocomponent":125}],120:[function(require,module,exports){ // copied from multi-regl module.exports = function createMultiplexor (createREGL, canvas, inputs) { var reglInput = {} if (inputs) { Object.keys(inputs).forEach(function (input) { reglInput[input] = inputs[input] }) } var pixelRatio = reglInput.pixelRatio || window.devicePixelRatio reglInput.pixelRatio = pixelRatio var canvasStyle = canvas.style canvasStyle.position = 'fixed' canvasStyle.left = canvasStyle.top = '0px' canvasStyle.width = canvasStyle.height = '100%' canvasStyle['pointer-events'] = 'none' canvasStyle['touch-action'] = 'none' canvasStyle['z-index'] = '1000' function resize () { canvas.width = pixelRatio * window.innerWidth canvas.height = pixelRatio * window.innerHeight if (!setRAF && regl) regl.draw(frame) } resize() window.addEventListener('resize', resize, false) window.addEventListener('scroll', function () { if (!setRAF) regl.draw(frame) }, false) reglInput.canvas = canvas delete reglInput.gl delete reglInput.container var regl = createREGL(reglInput) var subcontexts = [] var viewBox = { x: 0, y: 0, width: 0, height: 0 } function createSubContext (input) { var element if (typeof input === 'object' && input) { if (typeof input.getBoundingClientRect === 'function') { element = input } else if (input.element) { element = input.element } } else if (typeof input === 'string') { element = document.querySelector(element) } if (!element) { element = document.body } var subcontext = { tick: 0, element: element, callbacks: [] } subcontexts.push(subcontext) function wrapBox (boxDesc) { return boxDesc } var drawing = false window.requestAnimationFrame(function () { regl.draw(frame) }) function schedule (cb) { subcontext.callbacks.push(cb) cb() } function subREGL (options) { if ('viewport' in options) { options.viewport = wrapBox(options.viewport) } if ('scissor' in options) { if ('box' in options) { options.scissor.box = wrapBox(options.scissor.box) } if ('enable' in options) { options.scissor.box = true } } var draw = regl.apply(regl, Array.prototype.slice.call(arguments)) if (!setRAF) { return function () { if (setRAF) return draw.apply(this, arguments) var args = arguments schedule(function () { draw.apply(null, args) }) } } else return draw } Object.keys(regl).forEach(function (option) { if (option === 'clear') { subREGL.clear = function (opts) { if (setRAF) return regl[option].apply(this, arguments) subcontext.callbacks = [] var args = arguments schedule(function () { regl.clear.apply(null, args) }) } } else if (option === 'draw') { subREGL.draw = function () { if (setRAF) return regl[option].apply(this, arguments) var args = arguments schedule(function () { regl.draw.apply(null, args) }) } } else subREGL[option] = regl[option] }) subREGL.frame = function subFrame (cb) { setRAF = true subcontext.callbacks.push(cb) regl.frame(frame) return { cancel: function () { subcontext.callbacks.splice(subcontext.callbacks.indexOf(cb), 1) } } } subREGL.destroy = function () { subcontexts.splice(subcontexts.indexOf(subcontext), 1) } subREGL.container = element return subREGL } createSubContext.destroy = function () { regl.destroy() } createSubContext.regl = regl var setViewport = regl({ context: { tick: regl.prop('subcontext.tick') }, viewport: regl.prop('viewbox'), scissor: { enable: true, box: regl.prop('scissorbox') } }) function executeCallbacks (context, props) { var callbacks = props.subcontext.callbacks for (var i = 0; i < callbacks.length; ++i) { callbacks[i](context) } } var setRAF = false function frame (context) { regl.clear({ color: [0, 0, 0, 0] }) var width = window.innerWidth var height = window.innerHeight var pixelRatio = context.pixelRatio for (var i = 0; i < subcontexts.length; ++i) { var sc = subcontexts[i] var rect = sc.element.getBoundingClientRect() if (rect.right < 0 || rect.bottom < 0 || width < rect.left || height < rect.top) { continue } viewBox.x = pixelRatio * (rect.left) viewBox.y = pixelRatio * (height - rect.bottom) viewBox.width = pixelRatio * (rect.right - rect.left) viewBox.height = pixelRatio * (rect.bottom - rect.top) setViewport({ subcontext: sc, viewbox: viewBox, scissorbox: viewBox }, executeCallbacks) sc.tick += 1 } } return createSubContext } },{}],121:[function(require,module,exports){ (function (global){ var topLevel = typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : {} var minDoc = require('min-document'); var doccy; if (typeof document !== 'undefined') { doccy = document; } else { doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; if (!doccy) { doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; } } module.exports = doccy; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"min-document":2}],122:[function(require,module,exports){ (function (global){ var win; if (typeof window !== "undefined") { win = window; } else if (typeof global !== "undefined") { win = global; } else if (typeof self !== "undefined"){ win = self; } else { win = {}; } module.exports = win; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],123:[function(require,module,exports){ arguments[4][89][0].apply(exports,arguments) },{"dup":89}],124:[function(require,module,exports){ arguments[4][90][0].apply(exports,arguments) },{"assert":1,"dup":90,"nanotiming":133,"remove-array-items":134}],125:[function(require,module,exports){ var document = require('global/document') var nanotiming = require('nanotiming') var morph = require('nanomorph') var onload = require('on-load') var OL_KEY_ID = onload.KEY_ID var OL_ATTR_ID = onload.KEY_ATTR var assert = require('assert') module.exports = Nanocomponent function makeID () { return 'ncid-' + Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1) } function Nanocomponent (name) { this._hasWindow = typeof window !== 'undefined' this._id = null // represents the id of the root node this._ncID = null // internal nanocomponent id this._olID = null this._proxy = null this._loaded = false // Used to debounce on-load when child-reordering this._rootNodeName = null this._name = name || 'nanocomponent' this._rerender = false this._handleLoad = this._handleLoad.bind(this) this._handleUnload = this._handleUnload.bind(this) this._arguments = [] var self = this Object.defineProperty(this, 'element', { get: function () { var el = document.getElementById(self._id) if (el) return el.dataset.nanocomponent === self._ncID ? el : undefined } }) } Nanocomponent.prototype.render = function () { var renderTiming = nanotiming(this._name + '.render') var self = this var args = new Array(arguments.length) var el for (var i = 0; i < arguments.length; i++) args[i] = arguments[i] if (!this._hasWindow) { var createTiming = nanotiming(this._name + '.create') el = this.createElement.apply(this, args) createTiming() renderTiming() return el } else if (this.element) { el = this.element // retain reference, as the ID might change on render var updateTiming = nanotiming(this._name + '.update') var shouldUpdate = this._rerender || this.update.apply(this, args) updateTiming() if (this._rerender) this._rerender = false if (shouldUpdate) { var desiredHtml = this._handleRender(args) var morphTiming = nanotiming(this._name + '.morph') morph(el, desiredHtml) morphTiming() if (this.afterupdate) this.afterupdate(el) } if (!this._proxy) { this._proxy = this._createProxy() } renderTiming() return this._proxy } else { this._reset() el = this._handleRender(args) if (this.beforerender) this.beforerender(el) if (this.load || this.unload || this.afterreorder) { onload(el, self._handleLoad, self._handleUnload, self._ncID) this._olID = el.dataset[OL_KEY_ID] } renderTiming() return el } } Nanocomponent.prototype.rerender = function () { assert(this.element, 'nanocomponent: cant rerender on an unmounted dom node') this._rerender = true this.render.apply(this, this._arguments) } Nanocomponent.prototype._handleRender = function (args) { var createElementTiming = nanotiming(this._name + '.createElement') var el = this.createElement.apply(this, args) createElementTiming() if (!this._rootNodeName) this._rootNodeName = el.nodeName assert(el instanceof window.HTMLElement, 'nanocomponent: createElement should return a DOM node') assert.equal(this._rootNodeName, el.nodeName, 'nanocomponent: root node types cannot differ between re-renders') this._arguments = args return this._brandNode(this._ensureID(el)) } Nanocomponent.prototype._createProxy = function () { var proxy = document.createElement(this._rootNodeName) var self = this this._brandNode(proxy) proxy.id = this._id proxy.setAttribute('data-proxy', '') proxy.isSameNode = function (el) { return (el && el.dataset.nanocomponent === self._ncID) } return proxy } Nanocomponent.prototype._reset = function () { this._ncID = makeID() this._olID = null this._id = null this._proxy = null this._rootNodeName = null } Nanocomponent.prototype._brandNode = function (node) { node.setAttribute('data-nanocomponent', this._ncID) if (this._olID) node.setAttribute(OL_ATTR_ID, this._olID) return node } Nanocomponent.prototype._ensureID = function (node) { if (node.id) this._id = node.id else node.id = this._id = this._ncID // Update proxy node ID if it changed if (this._proxy && this._proxy.id !== this._id) this._proxy.id = this._id return node } Nanocomponent.prototype._handleLoad = function (el) { if (this._loaded) { if (this.afterreorder) this.afterreorder(el) return // Debounce child-reorders } this._loaded = true if (this.load) this.load(el) } Nanocomponent.prototype._handleUnload = function (el) { if (this.element) return // Debounce child-reorders this._loaded = false if (this.unload) this.unload(el) } Nanocomponent.prototype.createElement = function () { throw new Error('nanocomponent: createElement should be implemented!') } Nanocomponent.prototype.update = function () { throw new Error('nanocomponent: update should be implemented!') } },{"assert":123,"global/document":121,"nanomorph":129,"nanotiming":126,"on-load":128}],126:[function(require,module,exports){ var assert = require('assert') var onIdle = require('./lib/on-idle') var perf var disabled = true try { perf = window.performance disabled = window.localStorage.DISABLE_NANOTIMING === 'true' || !perf.mark } catch (e) { } module.exports = nanotiming function nanotiming (name) { assert.equal(typeof name, 'string', 'nanotiming: name should be type string') if (disabled) return noop var uuid = (perf.now() * 10000).toFixed() % Number.MAX_SAFE_INTEGER var startName = 'start-' + uuid + '-' + name perf.mark(startName) function end (cb) { var endName = 'end-' + uuid + '-' + name perf.mark(endName) onIdle(function () { var measureName = name + ' [' + uuid + ']' perf.measure(measureName, startName, endName) perf.clearMarks(startName) perf.clearMarks(endName) if (cb) cb(name) }) } end.uuid = uuid return end } function noop (cb) { if (cb) onIdle(cb) } },{"./lib/on-idle":127,"assert":1}],127:[function(require,module,exports){ var assert = require('assert') var dftOpts = {} var hasWindow = typeof window !== 'undefined' var hasIdle = hasWindow && window.requestIdleCallback module.exports = onIdle function onIdle (cb, opts) { opts = opts || dftOpts var timerId assert.equal(typeof cb, 'function', 'on-idle: cb should be type function') assert.equal(typeof opts, 'object', 'on-idle: opts should be type object') if (hasIdle) { timerId = window.requestIdleCallback(function (idleDeadline) { // reschedule if there's less than 10ms remaining on the tick // and a timer did not expire if (idleDeadline.timeRemaining() <= 10 && !idleDeadline.didTimeout) { return onIdle(cb, opts) } else { cb(idleDeadline) } }, opts) return window.cancelIdleCallback.bind(window, timerId) } else if (hasWindow) { timerId = setTimeout(cb, 0) return clearTimeout.bind(window, timerId) } } },{"assert":1}],128:[function(require,module,exports){ /* global MutationObserver */ var document = require('global/document') var window = require('global/window') var assert = require('assert') var watch = Object.create(null) var KEY_ID = 'onloadid' + (new Date() % 9e6).toString(36) var KEY_ATTR = 'data-' + KEY_ID var INDEX = 0 if (window && window.MutationObserver) { var observer = new MutationObserver(function (mutations) { if (Object.keys(watch).length < 1) return for (var i = 0; i < mutations.length; i++) { if (mutations[i].attributeName === KEY_ATTR) { eachAttr(mutations[i], turnon, turnoff) continue } eachMutation(mutations[i].removedNodes, turnoff) eachMutation(mutations[i].addedNodes, turnon) } }) if (document.body) { beginObserve(observer) } else { document.addEventListener('DOMContentLoaded', function (event) { beginObserve(observer) }) } } function beginObserve (observer) { observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeOldValue: true, attributeFilter: [KEY_ATTR] }) } module.exports = function onload (el, on, off, caller) { assert(document.body, 'on-load: will not work prior to DOMContentLoaded') on = on || function () {} off = off || function () {} el.setAttribute(KEY_ATTR, 'o' + INDEX) watch['o' + INDEX] = [on, off, 0, caller || onload.caller] INDEX += 1 return el } module.exports.KEY_ATTR = KEY_ATTR module.exports.KEY_ID = KEY_ID function turnon (index, el) { if (watch[index][0] && watch[index][2] === 0) { watch[index][0](el) watch[index][2] = 1 } } function turnoff (index, el) { if (watch[index][1] && watch[index][2] === 1) { watch[index][1](el) watch[index][2] = 0 } } function eachAttr (mutation, on, off) { var newValue = mutation.target.getAttribute(KEY_ATTR) if (sameOrigin(mutation.oldValue, newValue)) { watch[newValue] = watch[mutation.oldValue] return } if (watch[mutation.oldValue]) { off(mutation.oldValue, mutation.target) } if (watch[newValue]) { on(newValue, mutation.target) } } function sameOrigin (oldValue, newValue) { if (!oldValue || !newValue) return false return watch[oldValue][3] === watch[newValue][3] } function eachMutation (nodes, fn) { var keys = Object.keys(watch) for (var i = 0; i < nodes.length; i++) { if (nodes[i] && nodes[i].getAttribute && nodes[i].getAttribute(KEY_ATTR)) { var onloadid = nodes[i].getAttribute(KEY_ATTR) keys.forEach(function (k) { if (onloadid === k) { fn(k, nodes[i]) } }) } if (nodes[i].childNodes.length > 0) { eachMutation(nodes[i].childNodes, fn) } } } },{"assert":123,"global/document":121,"global/window":122}],129:[function(require,module,exports){ arguments[4][93][0].apply(exports,arguments) },{"./lib/morph":131,"assert":1,"dup":93}],130:[function(require,module,exports){ module.exports = [ // attribute events (can be set with attributes) 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onmouseenter', 'onmouseleave', 'ondragstart', 'ondrag', 'ondragenter', 'ondragleave', 'ondragover', 'ondrop', 'ondragend', 'onkeydown', 'onkeypress', 'onkeyup', 'onunload', 'onabort', 'onerror', 'onresize', 'onscroll', 'onselect', 'onchange', 'onsubmit', 'onreset', 'onfocus', 'onblur', 'oninput', // other common events 'oncontextmenu', 'onfocusin', 'onfocusout' ] },{}],131:[function(require,module,exports){ var events = require('./events') var eventsLength = events.length var ELEMENT_NODE = 1 var TEXT_NODE = 3 var COMMENT_NODE = 8 module.exports = morph // diff elements and apply the resulting patch to the old node // (obj, obj) -> null function morph (newNode, oldNode) { var nodeType = newNode.nodeType var nodeName = newNode.nodeName if (nodeType === ELEMENT_NODE) { copyAttrs(newNode, oldNode) } if (nodeType === TEXT_NODE || nodeType === COMMENT_NODE) { oldNode.nodeValue = newNode.nodeValue } // Some DOM nodes are weird // https://github.com/patrick-steele-idem/morphdom/blob/master/src/specialElHandlers.js if (nodeName === 'INPUT') updateInput(newNode, oldNode) else if (nodeName === 'OPTION') updateOption(newNode, oldNode) else if (nodeName === 'TEXTAREA') updateTextarea(newNode, oldNode) copyEvents(newNode, oldNode) } function copyAttrs (newNode, oldNode) { var oldAttrs = oldNode.attributes var newAttrs = newNode.attributes var attrNamespaceURI = null var attrValue = null var fromValue = null var attrName = null var attr = null for (var i = newAttrs.length - 1; i >= 0; --i) { attr = newAttrs[i] attrName = attr.name attrNamespaceURI = attr.namespaceURI attrValue = attr.value if (attrNamespaceURI) { attrName = attr.localName || attrName fromValue = oldNode.getAttributeNS(attrNamespaceURI, attrName) if (fromValue !== attrValue) { oldNode.setAttributeNS(attrNamespaceURI, attrName, attrValue) } } else { if (!oldNode.hasAttribute(attrName)) { oldNode.setAttribute(attrName, attrValue) } else { fromValue = oldNode.getAttribute(attrName) if (fromValue !== attrValue) { // apparently values are always cast to strings, ah well if (attrValue === 'null' || attrValue === 'undefined') { oldNode.removeAttribute(attrName) } else { oldNode.setAttribute(attrName, attrValue) } } } } } // Remove any extra attributes found on the original DOM element that // weren't found on the target element. for (var j = oldAttrs.length - 1; j >= 0; --j) { attr = oldAttrs[j] if (attr.specified !== false) { attrName = attr.name attrNamespaceURI = attr.namespaceURI if (attrNamespaceURI) { attrName = attr.localName || attrName if (!newNode.hasAttributeNS(attrNamespaceURI, attrName)) { oldNode.removeAttributeNS(attrNamespaceURI, attrName) } } else { if (!newNode.hasAttributeNS(null, attrName)) { oldNode.removeAttribute(attrName) } } } } } function copyEvents (newNode, oldNode) { for (var i = 0; i < eventsLength; i++) { var ev = events[i] if (newNode[ev]) { // if new element has a whitelisted attribute oldNode[ev] = newNode[ev] // update existing element } else if (oldNode[ev]) { // if existing element has it and new one doesnt oldNode[ev] = undefined // remove it from existing element } } } function updateOption (newNode, oldNode) { updateAttribute(newNode, oldNode, 'selected') } // The "value" attribute is special for the element since it sets the // initial value. Changing the "value" attribute without changing the "value" // property will have no effect since it is only used to the set the initial // value. Similar for the "checked" attribute, and "disabled". function updateInput (newNode, oldNode) { var newValue = newNode.value var oldValue = oldNode.value updateAttribute(newNode, oldNode, 'checked') updateAttribute(newNode, oldNode, 'disabled') if (newValue !== oldValue) { oldNode.setAttribute('value', newValue) oldNode.value = newValue } if (newValue === 'null') { oldNode.value = '' oldNode.removeAttribute('value') } if (!newNode.hasAttributeNS(null, 'value')) { oldNode.removeAttribute('value') } else if (oldNode.type === 'range') { // this is so elements like slider move their UI thingy oldNode.value = newValue } } function updateTextarea (newNode, oldNode) { var newValue = newNode.value if (newValue !== oldNode.value) { oldNode.value = newValue } if (oldNode.firstChild && oldNode.firstChild.nodeValue !== newValue) { // Needed for IE. Apparently IE sets the placeholder as the // node value and vise versa. This ignores an empty update. if (newValue === '' && oldNode.firstChild.nodeValue === oldNode.placeholder) { return } oldNode.firstChild.nodeValue = newValue } } function updateAttribute (newNode, oldNode, name) { if (newNode[name] !== oldNode[name]) { oldNode[name] = newNode[name] if (newNode[name]) { oldNode.setAttribute(name, '') } else { oldNode.removeAttribute(name) } } } },{"./events":130}],132:[function(require,module,exports){ arguments[4][99][0].apply(exports,arguments) },{"assert":123,"dup":99}],133:[function(require,module,exports){ arguments[4][100][0].apply(exports,arguments) },{"assert":1,"dup":100,"nanoscheduler":132}],134:[function(require,module,exports){ arguments[4][105][0].apply(exports,arguments) },{"dup":105}]},{},[7]);