---
`
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]);