From 4af42625a02fe9f3f9917b713e1cad862301de2c Mon Sep 17 00:00:00 2001 From: RHY3756547 Date: Sat, 24 Mar 2018 23:50:10 +0000 Subject: [PATCH 1/4] Initial implementation of Nitro Particles - Drifting particles and mini turbo (sans extra spark particles) - Slowdown particles (grass/sand/water) - Itembox collect particle - Wall collide particle (this is really extreme and there should probably be others) - Shader improvements, such as dithered shadows for alpha and reduction of artifacts. The best way to remove all artifacts would be generating normals for courses and using the diffuse direction as a more reliable indication of shadowed/not. - Fixed checkpoints not resetting on new laps. - Fixed me not being able to count to 3. (now 3 laps instead of 4) - Fixed battle mode courses crashing on load and during due to AI being funny (above 31, eg 36 for block fort) --- code/engine/cameras/cameraIngame.js | 2 +- code/engine/cameras/cameraIntro.js | 2 +- code/engine/cameras/cameraSpectator.js | 1 + code/engine/collisionTypes.js | 30 +- code/engine/controls/controlRaceCPU.js | 10 +- code/engine/ingameRes.js | 2 +- code/entities/decorations.js | 2 +- code/entities/itembox.js | 1 + code/entities/kart.js | 121 +- code/formats/spa.js | 107 +- code/glmatrix/gl-matrix-min.js | 40 +- code/glmatrix/gl-matrix.js | 8592 +++++++++++++++--------- code/particles/itemboxShard.js | 50 +- code/particles/nitroEmitter.js | 173 + code/particles/nitroParticle.js | 251 + code/render/nitroRender.js | 13 +- code/render/nitroShaders.js | 58 +- index.html | 2 +- 18 files changed, 6338 insertions(+), 3119 deletions(-) create mode 100644 code/particles/nitroEmitter.js create mode 100644 code/particles/nitroParticle.js diff --git a/code/engine/cameras/cameraIngame.js b/code/engine/cameras/cameraIngame.js index 1592ace..eaaf0ab 100644 --- a/code/engine/cameras/cameraIngame.js +++ b/code/engine/cameras/cameraIngame.js @@ -52,7 +52,7 @@ window.cameraIngame = function(kart) { var dist = 192; this.targetShadowPos = vec3.add([], kart.pos, [Math.sin(kart.angle)*dist, 0, -Math.cos(kart.angle)*dist]) - thisObj.view = {p:p, mv:mat}; + thisObj.view = {p:p, mv:mat, pos: vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], mat)), 1024)}; return thisObj.view; } diff --git a/code/engine/cameras/cameraIntro.js b/code/engine/cameras/cameraIntro.js index 7081423..0f1d8ee 100644 --- a/code/engine/cameras/cameraIntro.js +++ b/code/engine/cameras/cameraIntro.js @@ -102,7 +102,7 @@ window.cameraIntro = function() { thisObj.targetShadowPos = lookAtPos; - return {p:p, mv:mat} + return {p:p, mv:mat, pos: vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], mat)), 1024)} } var initCam = function(scene, came) { diff --git a/code/engine/cameras/cameraSpectator.js b/code/engine/cameras/cameraSpectator.js index a89cf49..3808a4a 100644 --- a/code/engine/cameras/cameraSpectator.js +++ b/code/engine/cameras/cameraSpectator.js @@ -55,6 +55,7 @@ window.cameraSpectator = function(kart) { if (zoomLevel > curCam.zoomEnd) zoomLevel = curCam.zoomEnd; thisObj.view = camFunc[curCam.camType](scene, curCam); + thisObj.view.pos = vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], thisObj.view.mv)), 1024) return thisObj.view; } diff --git a/code/engine/collisionTypes.js b/code/engine/collisionTypes.js index be9cd5e..e09a485 100644 --- a/code/engine/collisionTypes.js +++ b/code/engine/collisionTypes.js @@ -141,8 +141,10 @@ window.MKDS_COLTYPE = new (function(){ this.PHYS_MAP[this.LOOP] = 11; //collision sound handlers + //26 is blue water, 30 is white + //28 and 15 might be sand/dirt - var waterRoad = {drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATER, drive: MKDS_COLSOUNDS.DRIVE_WATER}; + var waterRoad = {drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATER, drive: MKDS_COLSOUNDS.DRIVE_WATER, particle: 30}; this.SOUNDMAP = { 0x00: //road @@ -164,7 +166,7 @@ window.MKDS_COLTYPE = new (function(){ {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT}, {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT}, {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT}, - {drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATERDEEP, drive: MKDS_COLSOUNDS.DRIVE_WATER}, + {drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATERDEEP, drive: MKDS_COLSOUNDS.DRIVE_WATER, particle: 30}, {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT}, {}, {}, @@ -187,27 +189,27 @@ window.MKDS_COLTYPE = new (function(){ 0x03: //road 4 [ - {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND}, - {drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT}, + {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28}, + {drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT, particle: 15}, - {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS}, + {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32}, - {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND}, - {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND}, - {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_SNOW}, //snow + {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28}, + {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28}, + {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_SNOW, particle:112}, //snow {}, {} ], 0x05: //road 5 [ - {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND}, - {drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT}, + {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28}, + {drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT, particle: 15}, - {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS}, + {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32}, - {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND}, - {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS}, + {drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28}, + {drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32}, {}, {}, {} @@ -216,7 +218,7 @@ window.MKDS_COLTYPE = new (function(){ 0x06: //slippery [ {drift: MKDS_COLSOUNDS.DRIFT_ICE, brake: MKDS_COLSOUNDS.BRAKE_ICE, land:MKDS_COLSOUNDS.LAND_ICE}, - {drift: MKDS_COLSOUNDS.DRIFT_MARSH, brake: MKDS_COLSOUNDS.BRAKE_MARSH, land:MKDS_COLSOUNDS.LAND_MARSH, drive: MKDS_COLSOUNDS.DRIVE_MARSH}, + {drift: MKDS_COLSOUNDS.DRIFT_MARSH, brake: MKDS_COLSOUNDS.BRAKE_MARSH, land:MKDS_COLSOUNDS.LAND_MARSH, drive: MKDS_COLSOUNDS.DRIVE_MARSH, particle: 24}, {}, {}, {}, diff --git a/code/engine/controls/controlRaceCPU.js b/code/engine/controls/controlRaceCPU.js index e43741b..4747122 100644 --- a/code/engine/controls/controlRaceCPU.js +++ b/code/engine/controls/controlRaceCPU.js @@ -102,10 +102,14 @@ window.controlRaceCPU = function(nkm) { //advance to one of next possible paths if (battleMode) { - var pathInd = ((Math.random()>0.5 && ePath.source.length>0)?ePath.source:ePath.dest)[Math.floor(Math.random()*ePath.dest.length)]; + var loc = (Math.random()>0.5 && ePath.source.length>0)?ePath.source:ePath.dest; + var pathInd = loc[Math.floor(Math.random()*loc.length)]; ePoiInd = pathInd; - ePoi = points[ePoiInd]; - recomputePath(); + var pt = points[ePoiInd]; + if (pt != null) { + ePoi = pt; + recomputePath(); + } } else { var pathInd = ePath.dest[Math.floor(Math.random()*ePath.dest.length)]; ePath = paths[pathInd]; diff --git a/code/engine/ingameRes.js b/code/engine/ingameRes.js index d5edb0a..0a103e7 100644 --- a/code/engine/ingameRes.js +++ b/code/engine/ingameRes.js @@ -18,6 +18,7 @@ window.IngameRes = function(rom) { this.Race = new narc(lz77.decompress(rom.getFile("/data/Scene/Race.carc"))); //contains lakitu, count, various graphics this.RaceLoc = new narc(lz77.decompress(rom.getFile("/data/Scene/Race_us.carc"))); //contains lakitu lap signs, START, YOU WIN etc. some of these will be replaced by hi res graphics by default. + this.RaceEffect = new spa(r.MainEffect.getFile("RaceEffect.spa")); this.MainFont = new nftr(r.Main2D.getFile("marioFont.NFTR")); //debugger; @@ -43,7 +44,6 @@ window.IngameRes = function(rom) { var characters = []; var karts = []; - var test = new spa(r.MainEffect.getFile("RaceEffect.spa")); loadItems(); loadTires(); diff --git a/code/entities/decorations.js b/code/entities/decorations.js index d4706f8..7de250a 100644 --- a/code/entities/decorations.js +++ b/code/entities/decorations.js @@ -179,7 +179,7 @@ window.ObjDecor = function(obji, scene) { forceBill = false; return {mdl:[{nsbmd:"choropu.nsbmd"}], other:[null, null, "choropu.nsbtp"]}; //has nsbtp case 0x019B: //cheep cheep (bouncing) - return {mdl:[{nsbmd:"pukupuku.nsbmd"}], other:[null, null, "pukupuku.nsbtp"]}; //has nsbtp + return {mdl:[{nsbmd:"pukupuku.nsbmd"}]}; //has nsbtp //, other:[null, null, "pukupuku.nsbtp"] case 0x019D: //snowman return {mdl:[{nsbmd:"sman_top.nsbmd"}, {nsbmd:"sman_bottom.nsbmd"}]}; case 0x019E: //trunk with bats diff --git a/code/entities/itembox.js b/code/entities/itembox.js index fc64640..a85c5bd 100644 --- a/code/entities/itembox.js +++ b/code/entities/itembox.js @@ -45,6 +45,7 @@ window.ItemBox = function(obji, scene) { for (var j=0; j<10; j++) { scene.particles.push(new ItemShard(scene, ok, res.mdl[2])); } + scene.particles.push(new NitroEmitter(scene, ok, 47)); t.mode = 1; t.time = 0; break; diff --git a/code/entities/kart.js b/code/entities/kart.js index 495d853..3583165 100644 --- a/code/entities/kart.js +++ b/code/entities/kart.js @@ -95,9 +95,18 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { this.lastInput = null; //race statistics - this.lapNumber = 0; + this.lapNumber = 1; this.passedKTP2 = false; this.checkPointNumber = 0; + + this.wheelParticles = [ + new NitroEmitter(scene, k, -1, [1, 1.5, -1]), + new NitroEmitter(scene, k, -1, [-1, 1.5, -1]) + ]; + + scene.particles.push(this.wheelParticles[0]); + scene.particles.push(this.wheelParticles[1]); + var nkm = scene.nkm; var startLine = nkm.sections["KTPS"].entries[0]; var passLine = nkm.sections["KTP2"].entries[0]; @@ -193,6 +202,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { mat4.scale(wmat, wmat, [scale, scale, scale]); if (i<2) mat4.rotateY(wmat, wmat, ((k.driveAnimF-14)/14)*Math.PI/6); mat4.rotateX(wmat, wmat, wheelTurn); + + if (i>1) { + k.wheelParticles[i-2].offset = vec3.scale(k.wheelParticles[i-2].offset, vec3.add(k.wheelParticles[i-2].offset, offsets.wheels[i], [0, -params.colRadius, 0]), 1/16); + } } var scale = 16; @@ -262,7 +275,11 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { drawChar(view, pMatrix); } + + k.lWheelParticle = null; + function update(scene) { + var lastPos = vec3.clone(k.pos); updateMat = true; @@ -314,7 +331,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { sounds.boost = null; } - if (onGround && k.speed > 0.5) { + var isMoving = onGround && k.speed > 0.5; + if (isMoving) { if (lastCollided != sounds.lastTerrain || lastBE != sounds.lastBE || sounds.drive == null) { if (sounds.drive != null) nitroAudio.kill(sounds.drive); if (lastColSounds.drive != null) { @@ -337,7 +355,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { } else { if (sounds.drift != null) { nitroAudio.kill(sounds.drift); sounds.drift = null; } if (sounds.drive != null) { nitroAudio.kill(sounds.drive); sounds.drive = null; } + } + k.wheelParticles[0].pause = !isMoving; + k.wheelParticles[1].pause = !isMoving; //end sound update @@ -346,23 +367,40 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { } else if (k.cannon != null) { //when cannon is active, we fly forward at max move speed until we get to the cannon point. var c = scene.nkm.sections["KTPC"].entries[k.cannon]; - var mat = mat4.create(); - mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180)); - mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180)); + if (c.id2 != 0) { + var c2 = scene.nkm.sections["KTPC"].entries[c.id2]; + c = c2; - var forward = [0, 0, 1]; - var up = [0, 1, 0]; + var mat = mat4.create(); + mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180)); + mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180)); - k.vel = vec3.scale([], vec3.transformMat4(forward, forward, mat), MAXSPEED); - k.speed = MAXSPEED; - vec3.add(k.pos, k.pos, k.vel); - k.physicalDir = (180-c.angle[1])*(Math.PI/180); - k.angle = k.physicalDir; - k.kartTargetNormal = vec3.transformMat4(up, up, mat); + k.pos = vec3.clone(c2.pos); + vec3.add(k.pos, k.pos, vec3.transformMat4([], [0,16,16], mat)); - var planeConst = -vec3.dot(c.pos, forward); - var cannonDist = vec3.dot(k.pos, forward) + planeConst; - if (cannonDist > 0) k.cannon = null; + k.physicalDir = (180-c2.angle[1])*(Math.PI/180); + k.angle = k.physicalDir; + k.cannon = null; + } else { + + var mat = mat4.create(); + mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180)); + mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180)); + + var forward = [0, 0, 1]; + var up = [0, 1, 0]; + + k.vel = vec3.scale([], vec3.transformMat4(forward, forward, mat), MAXSPEED); + k.speed = Math.min(k.speed+1, MAXSPEED); + vec3.add(k.pos, k.pos, k.vel); + k.physicalDir = (180-c.angle[1])*(Math.PI/180); + k.angle = k.physicalDir; + k.kartTargetNormal = vec3.transformMat4(up, up, mat); + + var planeConst = -vec3.dot(c.pos, forward); + var cannonDist = vec3.dot(k.pos, forward) + planeConst; + if (cannonDist > 0) k.cannon = null; + } } else { //default kart mode var groundEffect = 0; @@ -402,6 +440,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { if ((onGround) && !(input.accel && input.drift && (k.speed > 2 || !k.driftLanded))) { //end drift, execute miniturbo k.drifting = false; + clearWheelParticles(); if (sounds.powerslide != null) { nitroAudio.instaKill(sounds.powerslide); sounds.powerslide = null; @@ -434,11 +473,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { if (onGround) { if (!k.driftLanded) { - if (k.driftMode == 0) k.drifting = false; + if (k.driftMode == 0) { + k.drifting = false; + clearWheelParticles(); + } else { k.driftPSMode = 0; k.driftPSTick = 0; k.driftLanded = true; + if (k.drifting) setWheelParticles(20, 1); //20 = smoke, 1 = drift priority } } if (k.drifting) { @@ -467,7 +510,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { k.driftPSMode++; k.driftPSTick = 1; - //play blue spark sound + //play blue spark sound, flare + setWheelParticles(126, 2); //126 = blue flare, 2 = flare priority var blue = nitroAudio.playSound(210, {}, 0, k); blue.gainN.gain.value = 2; @@ -487,6 +531,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { k.driftPSMode++; k.driftPSTick = 1; //play red sparks sound, full MT! + setWheelParticles(22, 2); //22 = red flare, 2 = flare priority + setWheelParticles(17, 1); //17 = red mt, 1 = drift priority sounds.powerslide = nitroAudio.playSound(209, {}, 0, k); sounds.powerslide.gainN.gain.value = 2; } else k.driftPSTick = 0; @@ -642,6 +688,24 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { positionChanged(lastPos, k.pos); } + function clearWheelParticles(prio) { + for (let i=0; i<2; i++) { + if (prio == null) { + //clear all specials + k.wheelParticles[i].clearEmitter(1); //drift mode + //k.wheelParticles[i].clearEmitter(2); //drift flare (blue mt, red big flash) + } else { + k.wheelParticles[i].clearEmitter(0); + } + } + } + + function setWheelParticles(id, prio) { + for (let i=0; i<2; i++) { + k.wheelParticles[i].setEmitter(id, prio); + } + } + function genFutureChecks() { //all future points that var chosen = {} @@ -661,6 +725,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { function positionChanged(oldPos, pos) { //crossed into new checkpoint? + if (checkpoints.length == 0) return; for (var i=0; i>8)&31; var colBE = (plane.CollisionType>>5)&7; + var change = (colType != lastCollided); lastCollided = colType; lastBE = colBE; lastColSounds = colSound(lastCollided, colBE); @@ -832,9 +904,14 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { if (proj < -1) { if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k) + var colObj = {pos:pos, vel:[0,0,0], mat: mat4.fromTranslation([], pos)}; + scene.particles.push(new NitroEmitter(scene, colObj, 13)); + scene.particles.push(new NitroEmitter(scene, colObj, 14)); } vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), adjN, proj)); + + //convert back to angle + speed to keep change to kart vel var v = k.vel; @@ -851,6 +928,14 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) { if (proj < -4 && k.vel[1] < -2) { proj -= 1.5; } vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), n, proj)); k.kartTargetNormal = dat.pNormal; + + if (change) { + var particle = colParticle(lastCollided, colBE); + if (particle == null) + clearWheelParticles(0); + else + setWheelParticles(particle, 0); + } if (!onGround) { console.log("ground: "+colType+", "+colBE); groundAnim = 0; diff --git a/code/formats/spa.js b/code/formats/spa.js index d091d31..2b9abc5 100644 --- a/code/formats/spa.js +++ b/code/formats/spa.js @@ -9,6 +9,7 @@ window.spa = function(input) { var t = this; this.load = load; + this.getTexture = getTexture; var colourBuffer; @@ -36,42 +37,108 @@ window.spa = function(input) { offset += 24; if (version == "12_1") { - this.particles = []; + t.particles = []; for (let i=0; i>3)&1, //weirdly different format + pal0trans: true,//z(flags>>3)&1, //weirdly different format format: ((flags)&7), height: 8 << ((flags>>8)&0xF), width: 8 << ((flags>>4)&0xF), diff --git a/code/glmatrix/gl-matrix-min.js b/code/glmatrix/gl-matrix-min.js index 973d11c..1c56d6c 100644 --- a/code/glmatrix/gl-matrix-min.js +++ b/code/glmatrix/gl-matrix-min.js @@ -2,27 +2,27 @@ * @fileoverview gl-matrix - High performance matrix and vector operations * @author Brandon Jones * @author Colin MacKenzie IV - * @version 2.2.1 + * @version 2.4.0 */ -/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -(function(e){"use strict";var t={};typeof exports=="undefined"?typeof define=="function"&&typeof define.amd=="object"&&define.amd?(t.exports={},define(function(){return t.exports})):t.exports=typeof window!="undefined"?window:e:t.exports=exports,function(e){if(!t)var t=1e-6;if(!n)var n=typeof Float32Array!="undefined"?Float32Array:Array;if(!r)var r=Math.random;var i={};i.setMatrixArrayType=function(e){n=e},typeof e!="undefined"&&(e.glMatrix=i);var s=Math.PI/180;i.toRadian=function(e){return e*s};var o={};o.create=function(){var e=new n(2);return e[0]=0,e[1]=0,e},o.clone=function(e){var t=new n(2);return t[0]=e[0],t[1]=e[1],t},o.fromValues=function(e,t){var r=new n(2);return r[0]=e,r[1]=t,r},o.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e},o.set=function(e,t,n){return e[0]=t,e[1]=n,e},o.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e},o.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e},o.sub=o.subtract,o.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e},o.mul=o.multiply,o.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e},o.div=o.divide,o.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e},o.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e},o.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e},o.scaleAndAdd=function(e,t,n,r){return e[0]=t[0]+n[0]*r,e[1]=t[1]+n[1]*r,e},o.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)},o.dist=o.distance,o.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return n*n+r*r},o.sqrDist=o.squaredDistance,o.length=function(e){var t=e[0],n=e[1];return Math.sqrt(t*t+n*n)},o.len=o.length,o.squaredLength=function(e){var t=e[0],n=e[1];return t*t+n*n},o.sqrLen=o.squaredLength,o.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e},o.normalize=function(e,t){var n=t[0],r=t[1],i=n*n+r*r;return i>0&&(i=1/Math.sqrt(i),e[0]=t[0]*i,e[1]=t[1]*i),e},o.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]},o.cross=function(e,t,n){var r=t[0]*n[1]-t[1]*n[0];return e[0]=e[1]=0,e[2]=r,e},o.lerp=function(e,t,n,r){var i=t[0],s=t[1];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e},o.random=function(e,t){t=t||1;var n=r()*2*Math.PI;return e[0]=Math.cos(n)*t,e[1]=Math.sin(n)*t,e},o.transformMat2=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i,e[1]=n[1]*r+n[3]*i,e},o.transformMat2d=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i+n[4],e[1]=n[1]*r+n[3]*i+n[5],e},o.transformMat3=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[3]*i+n[6],e[1]=n[1]*r+n[4]*i+n[7],e},o.transformMat4=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[4]*i+n[12],e[1]=n[1]*r+n[5]*i+n[13],e},o.forEach=function(){var e=o.create();return function(t,n,r,i,s,o){var u,a;n||(n=2),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u0&&(s=1/Math.sqrt(s),e[0]=t[0]*s,e[1]=t[1]*s,e[2]=t[2]*s),e},u.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]},u.cross=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2];return e[0]=i*a-s*u,e[1]=s*o-r*a,e[2]=r*u-i*o,e},u.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e},u.random=function(e,t){t=t||1;var n=r()*2*Math.PI,i=r()*2-1,s=Math.sqrt(1-i*i)*t;return e[0]=Math.cos(n)*s,e[1]=Math.sin(n)*s,e[2]=i*t,e},u.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12],e[1]=n[1]*r+n[5]*i+n[9]*s+n[13],e[2]=n[2]*r+n[6]*i+n[10]*s+n[14],e},u.transformMat3=function(e,t,n){var r=t[0],i=t[1],s=t[2];return e[0]=r*n[0]+i*n[3]+s*n[6],e[1]=r*n[1]+i*n[4]+s*n[7],e[2]=r*n[2]+i*n[5]+s*n[8],e},u.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},u.rotateX=function(e,t,n,r){var i=[],s=[];return i[0]=t[0]-n[0],i[1]=t[1]-n[1],i[2]=t[2]-n[2],s[0]=i[0],s[1]=i[1]*Math.cos(r)-i[2]*Math.sin(r),s[2]=i[1]*Math.sin(r)+i[2]*Math.cos(r),e[0]=s[0]+n[0],e[1]=s[1]+n[1],e[2]=s[2]+n[2],e},u.rotateY=function(e,t,n,r){var i=[],s=[];return i[0]=t[0]-n[0],i[1]=t[1]-n[1],i[2]=t[2]-n[2],s[0]=i[2]*Math.sin(r)+i[0]*Math.cos(r),s[1]=i[1],s[2]=i[2]*Math.cos(r)-i[0]*Math.sin(r),e[0]=s[0]+n[0],e[1]=s[1]+n[1],e[2]=s[2]+n[2],e},u.rotateZ=function(e,t,n,r){var i=[],s=[];return i[0]=t[0]-n[0],i[1]=t[1]-n[1],i[2]=t[2]-n[2],s[0]=i[0]*Math.cos(r)-i[1]*Math.sin(r),s[1]=i[0]*Math.sin(r)+i[1]*Math.cos(r),s[2]=i[2],e[0]=s[0]+n[0],e[1]=s[1]+n[1],e[2]=s[2]+n[2],e},u.forEach=function(){var e=u.create();return function(t,n,r,i,s,o){var u,a;n||(n=3),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u0&&(o=1/Math.sqrt(o),e[0]=t[0]*o,e[1]=t[1]*o,e[2]=t[2]*o,e[3]=t[3]*o),e},a.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]},a.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e[3]=u+r*(n[3]-u),e},a.random=function(e,t){return t=t||1,e[0]=r(),e[1]=r(),e[2]=r(),e[3]=r(),a.normalize(e,e),a.scale(e,e,t),e},a.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12]*o,e[1]=n[1]*r+n[5]*i+n[9]*s+n[13]*o,e[2]=n[2]*r+n[6]*i+n[10]*s+n[14]*o,e[3]=n[3]*r+n[7]*i+n[11]*s+n[15]*o,e},a.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},a.forEach=function(){var e=a.create();return function(t,n,r,i,s,o){var u,a;n||(n=4),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u.999999?(r[0]=0,r[1]=0,r[2]=0,r[3]=1,r):(u.cross(e,i,s),r[0]=e[0],r[1]=e[1],r[2]=e[2],r[3]=1+o,p.normalize(r,r))}}(),p.setAxes=function(){var e=c.create();return function(t,n,r,i){return e[0]=r[0],e[3]=r[1],e[6]=r[2],e[1]=i[0],e[4]=i[1],e[7]=i[2],e[2]=-n[0],e[5]=-n[1],e[8]=-n[2],p.normalize(t,p.fromMat3(t,e))}}(),p.clone=a.clone,p.fromValues=a.fromValues,p.copy=a.copy,p.set=a.set,p.identity=function(e){return e[0]=0,e[1]=0,e[2]=0,e[3]=1,e},p.setAxisAngle=function(e,t,n){n*=.5;var r=Math.sin(n);return e[0]=r*t[0],e[1]=r*t[1],e[2]=r*t[2],e[3]=Math.cos(n),e},p.add=a.add,p.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1],f=n[2],l=n[3];return e[0]=r*l+o*u+i*f-s*a,e[1]=i*l+o*a+s*u-r*f,e[2]=s*l+o*f+r*a-i*u,e[3]=o*l-r*u-i*a-s*f,e},p.mul=p.multiply,p.scale=a.scale,p.rotateX=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+o*u,e[1]=i*a+s*u,e[2]=s*a-i*u,e[3]=o*a-r*u,e},p.rotateY=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a-s*u,e[1]=i*a+o*u,e[2]=s*a+r*u,e[3]=o*a-i*u,e},p.rotateZ=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+i*u,e[1]=i*a-r*u,e[2]=s*a+o*u,e[3]=o*a-s*u,e},p.calculateW=function(e,t){var n=t[0],r=t[1],i=t[2];return e[0]=n,e[1]=r,e[2]=i,e[3]=-Math.sqrt(Math.abs(1-n*n-r*r-i*i)),e},p.dot=a.dot,p.lerp=a.lerp,p.slerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3],a=n[0],f=n[1],l=n[2],c=n[3],h,p,d,v,m;return p=i*a+s*f+o*l+u*c,p<0&&(p=-p,a=-a,f=-f,l=-l,c=-c),1-p>1e-6?(h=Math.acos(p),d=Math.sin(h),v=Math.sin((1-r)*h)/d,m=Math.sin(r*h)/d):(v=1-r,m=r),e[0]=v*i+m*a,e[1]=v*s+m*f,e[2]=v*o+m*l,e[3]=v*u+m*c,e},p.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*n+r*r+i*i+s*s,u=o?1/o:0;return e[0]=-n*u,e[1]=-r*u,e[2]=-i*u,e[3]=s*u,e},p.conjugate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e[3]=t[3],e},p.length=a.length,p.len=p.length,p.squaredLength=a.squaredLength,p.sqrLen=p.squaredLength,p.normalize=a.normalize,p.fromMat3=function(e,t){var n=t[0]+t[4]+t[8],r;if(n>0)r=Math.sqrt(n+1),e[3]=.5*r,r=.5/r,e[0]=(t[7]-t[5])*r,e[1]=(t[2]-t[6])*r,e[2]=(t[3]-t[1])*r;else{var i=0;t[4]>t[0]&&(i=1),t[8]>t[i*3+i]&&(i=2);var s=(i+1)%3,o=(i+2)%3;r=Math.sqrt(t[i*3+i]-t[s*3+s]-t[o*3+o]+1),e[i]=.5*r,r=.5/r,e[3]=(t[o*3+s]-t[s*3+o])*r,e[s]=(t[s*3+i]+t[i*3+s])*r,e[o]=(t[o*3+i]+t[i*3+o])*r}return e},p.str=function(e){return"quat("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.quat=p)}(t.exports)})(this); +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ + +!function(t,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var r=n();for(var a in r)("object"==typeof exports?exports:t)[a]=r[a]}}(this,function(){return function(t){function n(a){if(r[a])return r[a].exports;var e=r[a]={i:a,l:!1,exports:{}};return t[a].call(e.exports,e,e.exports,n),e.l=!0,e.exports}var r={};return n.m=t,n.c=r,n.d=function(t,r,a){n.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:a})},n.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(r,"a",r),r},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=4)}([function(t,n,r){"use strict";function a(t){n.ARRAY_TYPE=i=t}function e(t){return t*s}function u(t,n){return Math.abs(t-n)<=o*Math.max(1,Math.abs(t),Math.abs(n))}Object.defineProperty(n,"__esModule",{value:!0}),n.setMatrixArrayType=a,n.toRadian=e,n.equals=u;var o=n.EPSILON=1e-6,i=n.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,s=(n.RANDOM=Math.random,Math.PI/180)},function(t,n,r){"use strict";function a(){var t=new g.ARRAY_TYPE(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function e(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t}function u(t){var n=new g.ARRAY_TYPE(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n}function o(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t}function i(t,n,r,a,e,u,o,i,s){var c=new g.ARRAY_TYPE(9);return c[0]=t,c[1]=n,c[2]=r,c[3]=a,c[4]=e,c[5]=u,c[6]=o,c[7]=i,c[8]=s,c}function s(t,n,r,a,e,u,o,i,s,c){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t[4]=u,t[5]=o,t[6]=i,t[7]=s,t[8]=c,t}function c(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function f(t,n){if(t===n){var r=n[1],a=n[2],e=n[5];t[1]=n[3],t[2]=n[6],t[3]=r,t[5]=n[7],t[6]=a,t[7]=e}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t}function M(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=f*o-i*c,h=-f*u+i*s,l=c*u-o*s,v=r*M+a*h+e*l;return v?(v=1/v,t[0]=M*v,t[1]=(-f*a+e*c)*v,t[2]=(i*a-e*o)*v,t[3]=h*v,t[4]=(f*r-e*s)*v,t[5]=(-i*r+e*u)*v,t[6]=l*v,t[7]=(-c*r+a*s)*v,t[8]=(o*r-a*u)*v,t):null}function h(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8];return t[0]=o*f-i*c,t[1]=e*c-a*f,t[2]=a*i-e*o,t[3]=i*s-u*f,t[4]=r*f-e*s,t[5]=e*u-r*i,t[6]=u*c-o*s,t[7]=a*s-r*c,t[8]=r*o-a*u,t}function l(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],s=t[7],c=t[8];return n*(c*u-o*s)+r*(-c*e+o*i)+a*(s*e-u*i)}function v(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=r[0],l=r[1],v=r[2],d=r[3],b=r[4],m=r[5],p=r[6],P=r[7],E=r[8];return t[0]=h*a+l*o+v*c,t[1]=h*e+l*i+v*f,t[2]=h*u+l*s+v*M,t[3]=d*a+b*o+m*c,t[4]=d*e+b*i+m*f,t[5]=d*u+b*s+m*M,t[6]=p*a+P*o+E*c,t[7]=p*e+P*i+E*f,t[8]=p*u+P*s+E*M,t}function d(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=r[0],l=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=i,t[5]=s,t[6]=h*a+l*o+c,t[7]=h*e+l*i+f,t[8]=h*u+l*s+M,t}function b(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=Math.sin(r),l=Math.cos(r);return t[0]=l*a+h*o,t[1]=l*e+h*i,t[2]=l*u+h*s,t[3]=l*o-h*a,t[4]=l*i-h*e,t[5]=l*s-h*u,t[6]=c,t[7]=f,t[8]=M,t}function m(t,n,r){var a=r[0],e=r[1];return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=e*n[3],t[4]=e*n[4],t[5]=e*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t}function p(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t}function P(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=0,t[3]=-r,t[4]=a,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function E(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function O(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t}function x(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,s=e+e,c=r*o,f=a*o,M=a*i,h=e*o,l=e*i,v=e*s,d=u*o,b=u*i,m=u*s;return t[0]=1-M-v,t[3]=f-m,t[6]=h+b,t[1]=f+m,t[4]=1-c-v,t[7]=l-d,t[2]=h-b,t[5]=l+d,t[8]=1-c-M,t}function A(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=n[9],h=n[10],l=n[11],v=n[12],d=n[13],b=n[14],m=n[15],p=r*i-a*o,P=r*s-e*o,E=r*c-u*o,O=a*s-e*i,x=a*c-u*i,A=e*c-u*s,q=f*d-M*v,y=f*b-h*v,w=f*m-l*v,R=M*b-h*d,L=M*m-l*d,S=h*m-l*b,_=p*S-P*L+E*R+O*w-x*y+A*q;return _?(_=1/_,t[0]=(i*S-s*L+c*R)*_,t[1]=(s*w-o*S-c*y)*_,t[2]=(o*L-i*w+c*q)*_,t[3]=(e*L-a*S-u*R)*_,t[4]=(r*S-e*w+u*y)*_,t[5]=(a*w-r*L-u*q)*_,t[6]=(d*A-b*x+m*O)*_,t[7]=(b*E-v*A-m*P)*_,t[8]=(v*x-d*E+m*p)*_,t):null}function q(t,n,r){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/r,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t}function y(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"}function w(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2))}function R(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t[4]=n[4]+r[4],t[5]=n[5]+r[5],t[6]=n[6]+r[6],t[7]=n[7]+r[7],t[8]=n[8]+r[8],t}function L(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t[4]=n[4]-r[4],t[5]=n[5]-r[5],t[6]=n[6]-r[6],t[7]=n[7]-r[7],t[8]=n[8]-r[8],t}function S(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=n[7]*r,t[8]=n[8]*r,t}function _(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t[4]=n[4]+r[4]*a,t[5]=n[5]+r[5]*a,t[6]=n[6]+r[6]*a,t[7]=n[7]+r[7]*a,t[8]=n[8]+r[8]*a,t}function I(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]}function N(t,n){var r=t[0],a=t[1],e=t[2],u=t[3],o=t[4],i=t[5],s=t[6],c=t[7],f=t[8],M=n[0],h=n[1],l=n[2],v=n[3],d=n[4],b=n[5],m=n[6],p=n[7],P=n[8];return Math.abs(r-M)<=g.EPSILON*Math.max(1,Math.abs(r),Math.abs(M))&&Math.abs(a-h)<=g.EPSILON*Math.max(1,Math.abs(a),Math.abs(h))&&Math.abs(e-l)<=g.EPSILON*Math.max(1,Math.abs(e),Math.abs(l))&&Math.abs(u-v)<=g.EPSILON*Math.max(1,Math.abs(u),Math.abs(v))&&Math.abs(o-d)<=g.EPSILON*Math.max(1,Math.abs(o),Math.abs(d))&&Math.abs(i-b)<=g.EPSILON*Math.max(1,Math.abs(i),Math.abs(b))&&Math.abs(s-m)<=g.EPSILON*Math.max(1,Math.abs(s),Math.abs(m))&&Math.abs(c-p)<=g.EPSILON*Math.max(1,Math.abs(c),Math.abs(p))&&Math.abs(f-P)<=g.EPSILON*Math.max(1,Math.abs(f),Math.abs(P))}Object.defineProperty(n,"__esModule",{value:!0}),n.sub=n.mul=void 0,n.create=a,n.fromMat4=e,n.clone=u,n.copy=o,n.fromValues=i,n.set=s,n.identity=c,n.transpose=f,n.invert=M,n.adjoint=h,n.determinant=l,n.multiply=v,n.translate=d,n.rotate=b,n.scale=m,n.fromTranslation=p,n.fromRotation=P,n.fromScaling=E,n.fromMat2d=O,n.fromQuat=x,n.normalFromMat4=A,n.projection=q,n.str=y,n.frob=w,n.add=R,n.subtract=L,n.multiplyScalar=S,n.multiplyScalarAndAdd=_,n.exactEquals=I,n.equals=N;var Y=r(0),g=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(Y);n.mul=v,n.sub=L},function(t,n,r){"use strict";function a(){var t=new Z.ARRAY_TYPE(3);return t[0]=0,t[1]=0,t[2]=0,t}function e(t){var n=new Z.ARRAY_TYPE(3);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n}function u(t){var n=t[0],r=t[1],a=t[2];return Math.sqrt(n*n+r*r+a*a)}function o(t,n,r){var a=new Z.ARRAY_TYPE(3);return a[0]=t,a[1]=n,a[2]=r,a}function i(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t}function s(t,n,r,a){return t[0]=n,t[1]=r,t[2]=a,t}function c(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t}function f(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t}function M(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t[2]=n[2]*r[2],t}function h(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t[2]=n[2]/r[2],t}function l(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t[2]=Math.ceil(n[2]),t}function v(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t[2]=Math.floor(n[2]),t}function d(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t[2]=Math.min(n[2],r[2]),t}function b(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t[2]=Math.max(n[2],r[2]),t}function m(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t[2]=Math.round(n[2]),t}function p(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t}function P(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t}function E(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return Math.sqrt(r*r+a*a+e*e)}function O(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return r*r+a*a+e*e}function x(t){var n=t[0],r=t[1],a=t[2];return n*n+r*r+a*a}function A(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t}function q(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t}function y(t,n){var r=n[0],a=n[1],e=n[2],u=r*r+a*a+e*e;return u>0&&(u=1/Math.sqrt(u),t[0]=n[0]*u,t[1]=n[1]*u,t[2]=n[2]*u),t}function w(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function R(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],s=r[2];return t[0]=e*s-u*i,t[1]=u*o-a*s,t[2]=a*i-e*o,t}function L(t,n,r,a){var e=n[0],u=n[1],o=n[2];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t}function S(t,n,r,a,e,u){var o=u*u,i=o*(2*u-3)+1,s=o*(u-2)+u,c=o*(u-1),f=o*(3-2*u);return t[0]=n[0]*i+r[0]*s+a[0]*c+e[0]*f,t[1]=n[1]*i+r[1]*s+a[1]*c+e[1]*f,t[2]=n[2]*i+r[2]*s+a[2]*c+e[2]*f,t}function _(t,n,r,a,e,u){var o=1-u,i=o*o,s=u*u,c=i*o,f=3*u*i,M=3*s*o,h=s*u;return t[0]=n[0]*c+r[0]*f+a[0]*M+e[0]*h,t[1]=n[1]*c+r[1]*f+a[1]*M+e[1]*h,t[2]=n[2]*c+r[2]*f+a[2]*M+e[2]*h,t}function I(t,n){n=n||1;var r=2*Z.RANDOM()*Math.PI,a=2*Z.RANDOM()-1,e=Math.sqrt(1-a*a)*n;return t[0]=Math.cos(r)*e,t[1]=Math.sin(r)*e,t[2]=a*n,t}function N(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[3]*a+r[7]*e+r[11]*u+r[15];return o=o||1,t[0]=(r[0]*a+r[4]*e+r[8]*u+r[12])/o,t[1]=(r[1]*a+r[5]*e+r[9]*u+r[13])/o,t[2]=(r[2]*a+r[6]*e+r[10]*u+r[14])/o,t}function Y(t,n,r){var a=n[0],e=n[1],u=n[2];return t[0]=a*r[0]+e*r[3]+u*r[6],t[1]=a*r[1]+e*r[4]+u*r[7],t[2]=a*r[2]+e*r[5]+u*r[8],t}function g(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],s=r[2],c=r[3],f=c*a+i*u-s*e,M=c*e+s*a-o*u,h=c*u+o*e-i*a,l=-o*a-i*e-s*u;return t[0]=f*c+l*-o+M*-s-h*-i,t[1]=M*c+l*-i+h*-o-f*-s,t[2]=h*c+l*-s+f*-i-M*-o,t}function T(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[0],u[1]=e[1]*Math.cos(a)-e[2]*Math.sin(a),u[2]=e[1]*Math.sin(a)+e[2]*Math.cos(a),t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t}function j(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[2]*Math.sin(a)+e[0]*Math.cos(a),u[1]=e[1],u[2]=e[2]*Math.cos(a)-e[0]*Math.sin(a),t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t}function D(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[0]*Math.cos(a)-e[1]*Math.sin(a),u[1]=e[0]*Math.sin(a)+e[1]*Math.cos(a),u[2]=e[2],t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t}function V(t,n){var r=o(t[0],t[1],t[2]),a=o(n[0],n[1],n[2]);y(r,r),y(a,a);var e=w(r,a);return e>1?0:e<-1?Math.PI:Math.acos(e)}function z(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"}function F(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]}function Q(t,n){var r=t[0],a=t[1],e=t[2],u=n[0],o=n[1],i=n[2];return Math.abs(r-u)<=Z.EPSILON*Math.max(1,Math.abs(r),Math.abs(u))&&Math.abs(a-o)<=Z.EPSILON*Math.max(1,Math.abs(a),Math.abs(o))&&Math.abs(e-i)<=Z.EPSILON*Math.max(1,Math.abs(e),Math.abs(i))}Object.defineProperty(n,"__esModule",{value:!0}),n.forEach=n.sqrLen=n.len=n.sqrDist=n.dist=n.div=n.mul=n.sub=void 0,n.create=a,n.clone=e,n.length=u,n.fromValues=o,n.copy=i,n.set=s,n.add=c,n.subtract=f,n.multiply=M,n.divide=h,n.ceil=l,n.floor=v,n.min=d,n.max=b,n.round=m,n.scale=p,n.scaleAndAdd=P,n.distance=E,n.squaredDistance=O,n.squaredLength=x,n.negate=A,n.inverse=q,n.normalize=y,n.dot=w,n.cross=R,n.lerp=L,n.hermite=S,n.bezier=_,n.random=I,n.transformMat4=N,n.transformMat3=Y,n.transformQuat=g,n.rotateX=T,n.rotateY=j,n.rotateZ=D,n.angle=V,n.str=z,n.exactEquals=F,n.equals=Q;var X=r(0),Z=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(X);n.sub=f,n.mul=M,n.div=h,n.dist=E,n.sqrDist=O,n.len=u,n.sqrLen=x,n.forEach=function(){var t=a();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=3),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;i0&&(o=1/Math.sqrt(o),t[0]=r*o,t[1]=a*o,t[2]=e*o,t[3]=u*o),t}function w(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function R(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t[3]=i+a*(r[3]-i),t}function L(t,n){return n=n||1,t[0]=T.RANDOM(),t[1]=T.RANDOM(),t[2]=T.RANDOM(),t[3]=T.RANDOM(),y(t,t),m(t,t,n),t}function S(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3];return t[0]=r[0]*a+r[4]*e+r[8]*u+r[12]*o,t[1]=r[1]*a+r[5]*e+r[9]*u+r[13]*o,t[2]=r[2]*a+r[6]*e+r[10]*u+r[14]*o,t[3]=r[3]*a+r[7]*e+r[11]*u+r[15]*o,t}function _(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],s=r[2],c=r[3],f=c*a+i*u-s*e,M=c*e+s*a-o*u,h=c*u+o*e-i*a,l=-o*a-i*e-s*u;return t[0]=f*c+l*-o+M*-s-h*-i,t[1]=M*c+l*-i+h*-o-f*-s,t[2]=h*c+l*-s+f*-i-M*-o,t[3]=n[3],t}function I(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"}function N(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]}function Y(t,n){var r=t[0],a=t[1],e=t[2],u=t[3],o=n[0],i=n[1],s=n[2],c=n[3];return Math.abs(r-o)<=T.EPSILON*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(a-i)<=T.EPSILON*Math.max(1,Math.abs(a),Math.abs(i))&&Math.abs(e-s)<=T.EPSILON*Math.max(1,Math.abs(e),Math.abs(s))&&Math.abs(u-c)<=T.EPSILON*Math.max(1,Math.abs(u),Math.abs(c))}Object.defineProperty(n,"__esModule",{value:!0}),n.forEach=n.sqrLen=n.len=n.sqrDist=n.dist=n.div=n.mul=n.sub=void 0,n.create=a,n.clone=e,n.fromValues=u,n.copy=o,n.set=i,n.add=s,n.subtract=c,n.multiply=f,n.divide=M,n.ceil=h,n.floor=l,n.min=v,n.max=d,n.round=b,n.scale=m,n.scaleAndAdd=p,n.distance=P,n.squaredDistance=E,n.length=O,n.squaredLength=x,n.negate=A,n.inverse=q,n.normalize=y,n.dot=w,n.lerp=R,n.random=L,n.transformMat4=S,n.transformQuat=_,n.str=I,n.exactEquals=N,n.equals=Y;var g=r(0),T=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(g);n.sub=c,n.mul=f,n.div=M,n.dist=P,n.sqrDist=E,n.len=O,n.sqrLen=x,n.forEach=function(){var t=a();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=4),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;i0?(a=2*Math.sqrt(r+1),t[3]=.25*a,t[0]=(n[6]-n[9])/a,t[1]=(n[8]-n[2])/a,t[2]=(n[1]-n[4])/a):n[0]>n[5]&n[0]>n[10]?(a=2*Math.sqrt(1+n[0]-n[5]-n[10]),t[3]=(n[6]-n[9])/a,t[0]=.25*a,t[1]=(n[1]+n[4])/a,t[2]=(n[8]+n[2])/a):n[5]>n[10]?(a=2*Math.sqrt(1+n[5]-n[0]-n[10]),t[3]=(n[8]-n[2])/a,t[0]=(n[1]+n[4])/a,t[1]=.25*a,t[2]=(n[6]+n[9])/a):(a=2*Math.sqrt(1+n[10]-n[0]-n[5]),t[3]=(n[1]-n[4])/a,t[0]=(n[8]+n[2])/a,t[1]=(n[6]+n[9])/a,t[2]=.25*a),t}function _(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3],s=e+e,c=u+u,f=o+o,M=e*s,h=e*c,l=e*f,v=u*c,d=u*f,b=o*f,m=i*s,p=i*c,P=i*f,E=a[0],O=a[1],x=a[2];return t[0]=(1-(v+b))*E,t[1]=(h+P)*E,t[2]=(l-p)*E,t[3]=0,t[4]=(h-P)*O,t[5]=(1-(M+b))*O,t[6]=(d+m)*O,t[7]=0,t[8]=(l+p)*x,t[9]=(d-m)*x,t[10]=(1-(M+v))*x,t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t}function I(t,n,r,a,e){var u=n[0],o=n[1],i=n[2],s=n[3],c=u+u,f=o+o,M=i+i,h=u*c,l=u*f,v=u*M,d=o*f,b=o*M,m=i*M,p=s*c,P=s*f,E=s*M,O=a[0],x=a[1],A=a[2],q=e[0],y=e[1],w=e[2];return t[0]=(1-(d+m))*O,t[1]=(l+E)*O,t[2]=(v-P)*O,t[3]=0,t[4]=(l-E)*x,t[5]=(1-(h+m))*x,t[6]=(b+p)*x,t[7]=0,t[8]=(v+P)*A,t[9]=(b-p)*A,t[10]=(1-(h+d))*A,t[11]=0,t[12]=r[0]+q-(t[0]*q+t[4]*y+t[8]*w),t[13]=r[1]+y-(t[1]*q+t[5]*y+t[9]*w),t[14]=r[2]+w-(t[2]*q+t[6]*y+t[10]*w),t[15]=1,t}function N(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,s=e+e,c=r*o,f=a*o,M=a*i,h=e*o,l=e*i,v=e*s,d=u*o,b=u*i,m=u*s;return t[0]=1-M-v,t[1]=f+m,t[2]=h-b,t[3]=0,t[4]=f-m,t[5]=1-c-v,t[6]=l+d,t[7]=0,t[8]=h+b,t[9]=l-d,t[10]=1-c-M,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function Y(t,n,r,a,e,u,o){var i=1/(r-n),s=1/(e-a),c=1/(u-o);return t[0]=2*u*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*u*s,t[6]=0,t[7]=0,t[8]=(r+n)*i,t[9]=(e+a)*s,t[10]=(o+u)*c,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*u*2*c,t[15]=0,t}function g(t,n,r,a,e){var u=1/Math.tan(n/2),o=1/(a-e);return t[0]=u/r,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=u,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=(e+a)*o,t[11]=-1,t[12]=0,t[13]=0,t[14]=2*e*a*o,t[15]=0,t}function T(t,n,r,a){var e=Math.tan(n.upDegrees*Math.PI/180),u=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),s=2/(o+i),c=2/(e+u);return t[0]=s,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=c,t[6]=0,t[7]=0,t[8]=-(o-i)*s*.5,t[9]=(e-u)*c*.5,t[10]=a/(r-a),t[11]=-1,t[12]=0,t[13]=0,t[14]=a*r/(r-a),t[15]=0,t}function j(t,n,r,a,e,u,o){var i=1/(n-r),s=1/(a-e),c=1/(u-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*s,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*c,t[11]=0,t[12]=(n+r)*i,t[13]=(e+a)*s,t[14]=(o+u)*c,t[15]=1,t}function D(t,n,r,a){var e=void 0,u=void 0,o=void 0,i=void 0,s=void 0,c=void 0,f=void 0,M=void 0,h=void 0,l=void 0,v=n[0],d=n[1],b=n[2],m=a[0],p=a[1],P=a[2],E=r[0],O=r[1],x=r[2];return Math.abs(v-E)0&&(l=1/Math.sqrt(l),f*=l,M*=l,h*=l);var v=s*h-c*M,d=c*f-i*h,b=i*M-s*f;return t[0]=v,t[1]=d,t[2]=b,t[3]=0,t[4]=M*b-h*d,t[5]=h*v-f*b,t[6]=f*d-M*v,t[7]=0,t[8]=f,t[9]=M,t[10]=h,t[11]=0,t[12]=e,t[13]=u,t[14]=o,t[15]=1,t}function z(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"}function F(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2)+Math.pow(t[9],2)+Math.pow(t[10],2)+Math.pow(t[11],2)+Math.pow(t[12],2)+Math.pow(t[13],2)+Math.pow(t[14],2)+Math.pow(t[15],2))}function Q(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t[4]=n[4]+r[4],t[5]=n[5]+r[5],t[6]=n[6]+r[6],t[7]=n[7]+r[7],t[8]=n[8]+r[8],t[9]=n[9]+r[9],t[10]=n[10]+r[10],t[11]=n[11]+r[11],t[12]=n[12]+r[12],t[13]=n[13]+r[13],t[14]=n[14]+r[14],t[15]=n[15]+r[15],t}function X(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t[4]=n[4]-r[4],t[5]=n[5]-r[5],t[6]=n[6]-r[6],t[7]=n[7]-r[7],t[8]=n[8]-r[8],t[9]=n[9]-r[9],t[10]=n[10]-r[10],t[11]=n[11]-r[11],t[12]=n[12]-r[12],t[13]=n[13]-r[13],t[14]=n[14]-r[14],t[15]=n[15]-r[15],t}function Z(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=n[7]*r,t[8]=n[8]*r,t[9]=n[9]*r,t[10]=n[10]*r,t[11]=n[11]*r,t[12]=n[12]*r,t[13]=n[13]*r,t[14]=n[14]*r,t[15]=n[15]*r,t}function k(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t[4]=n[4]+r[4]*a,t[5]=n[5]+r[5]*a,t[6]=n[6]+r[6]*a,t[7]=n[7]+r[7]*a,t[8]=n[8]+r[8]*a,t[9]=n[9]+r[9]*a,t[10]=n[10]+r[10]*a,t[11]=n[11]+r[11]*a,t[12]=n[12]+r[12]*a,t[13]=n[13]+r[13]*a,t[14]=n[14]+r[14]*a,t[15]=n[15]+r[15]*a,t}function U(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[10]===n[10]&&t[11]===n[11]&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[15]===n[15]}function W(t,n){var r=t[0],a=t[1],e=t[2],u=t[3],o=t[4],i=t[5],s=t[6],c=t[7],f=t[8],M=t[9],h=t[10],l=t[11],v=t[12],d=t[13],b=t[14],m=t[15],p=n[0],P=n[1],E=n[2],O=n[3],x=n[4],A=n[5],q=n[6],y=n[7],w=n[8],R=n[9],L=n[10],S=n[11],_=n[12],I=n[13],N=n[14],Y=n[15];return Math.abs(r-p)<=C.EPSILON*Math.max(1,Math.abs(r),Math.abs(p))&&Math.abs(a-P)<=C.EPSILON*Math.max(1,Math.abs(a),Math.abs(P))&&Math.abs(e-E)<=C.EPSILON*Math.max(1,Math.abs(e),Math.abs(E))&&Math.abs(u-O)<=C.EPSILON*Math.max(1,Math.abs(u),Math.abs(O))&&Math.abs(o-x)<=C.EPSILON*Math.max(1,Math.abs(o),Math.abs(x))&&Math.abs(i-A)<=C.EPSILON*Math.max(1,Math.abs(i),Math.abs(A))&&Math.abs(s-q)<=C.EPSILON*Math.max(1,Math.abs(s),Math.abs(q))&&Math.abs(c-y)<=C.EPSILON*Math.max(1,Math.abs(c),Math.abs(y))&&Math.abs(f-w)<=C.EPSILON*Math.max(1,Math.abs(f),Math.abs(w))&&Math.abs(M-R)<=C.EPSILON*Math.max(1,Math.abs(M),Math.abs(R))&&Math.abs(h-L)<=C.EPSILON*Math.max(1,Math.abs(h),Math.abs(L))&&Math.abs(l-S)<=C.EPSILON*Math.max(1,Math.abs(l),Math.abs(S))&&Math.abs(v-_)<=C.EPSILON*Math.max(1,Math.abs(v),Math.abs(_))&&Math.abs(d-I)<=C.EPSILON*Math.max(1,Math.abs(d),Math.abs(I))&&Math.abs(b-N)<=C.EPSILON*Math.max(1,Math.abs(b),Math.abs(N))&&Math.abs(m-Y)<=C.EPSILON*Math.max(1,Math.abs(m),Math.abs(Y))}Object.defineProperty(n,"__esModule",{value:!0}),n.sub=n.mul=void 0,n.create=a,n.clone=e,n.copy=u,n.fromValues=o,n.set=i,n.identity=s,n.transpose=c,n.invert=f,n.adjoint=M,n.determinant=h,n.multiply=l,n.translate=v,n.scale=d,n.rotate=b,n.rotateX=m,n.rotateY=p,n.rotateZ=P,n.fromTranslation=E,n.fromScaling=O,n.fromRotation=x,n.fromXRotation=A,n.fromYRotation=q,n.fromZRotation=y,n.fromRotationTranslation=w,n.getTranslation=R,n.getScaling=L,n.getRotation=S,n.fromRotationTranslationScale=_,n.fromRotationTranslationScaleOrigin=I,n.fromQuat=N,n.frustum=Y,n.perspective=g,n.perspectiveFromFieldOfView=T,n.ortho=j,n.lookAt=D,n.targetTo=V,n.str=z,n.frob=F,n.add=Q,n.subtract=X,n.multiplyScalar=Z,n.multiplyScalarAndAdd=k,n.exactEquals=U,n.equals=W;var B=r(0),C=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(B);n.mul=l,n.sub=X},function(t,n,r){"use strict";function a(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}function e(){var t=new E.ARRAY_TYPE(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t}function u(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t}function o(t,n,r){r*=.5;var a=Math.sin(r);return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=Math.cos(r),t}function i(t,n){var r=2*Math.acos(n[3]),a=Math.sin(r/2);return 0!=a?(t[0]=n[0]/a,t[1]=n[1]/a,t[2]=n[2]/a):(t[0]=1,t[1]=0,t[2]=0),r}function s(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],s=r[1],c=r[2],f=r[3];return t[0]=a*f+o*i+e*c-u*s,t[1]=e*f+o*s+u*i-a*c,t[2]=u*f+o*c+a*s-e*i,t[3]=o*f-a*i-e*s-u*c,t}function c(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s+o*i,t[1]=e*s+u*i,t[2]=u*s-e*i,t[3]=o*s-a*i,t}function f(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s-u*i,t[1]=e*s+o*i,t[2]=u*s+a*i,t[3]=o*s-e*i,t}function M(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),s=Math.cos(r);return t[0]=a*s+e*i,t[1]=e*s-a*i,t[2]=u*s+o*i,t[3]=o*s-u*i,t}function h(t,n){var r=n[0],a=n[1],e=n[2];return t[0]=r,t[1]=a,t[2]=e,t[3]=Math.sqrt(Math.abs(1-r*r-a*a-e*e)),t}function l(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3],s=r[0],c=r[1],f=r[2],M=r[3],h=void 0,l=void 0,v=void 0,d=void 0,b=void 0;return l=e*s+u*c+o*f+i*M,l<0&&(l=-l,s=-s,c=-c,f=-f,M=-M),1-l>1e-6?(h=Math.acos(l),v=Math.sin(h),d=Math.sin((1-a)*h)/v,b=Math.sin(a*h)/v):(d=1-a,b=a),t[0]=d*e+b*s,t[1]=d*u+b*c,t[2]=d*o+b*f,t[3]=d*i+b*M,t}function v(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*r+a*a+e*e+u*u,i=o?1/o:0;return t[0]=-r*i,t[1]=-a*i,t[2]=-e*i,t[3]=u*i,t}function d(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t}function b(t,n){var r=n[0]+n[4]+n[8],a=void 0;if(r>0)a=Math.sqrt(r+1),t[3]=.5*a,a=.5/a,t[0]=(n[5]-n[7])*a,t[1]=(n[6]-n[2])*a,t[2]=(n[1]-n[3])*a;else{var e=0;n[4]>n[0]&&(e=1),n[8]>n[3*e+e]&&(e=2);var u=(e+1)%3,o=(e+2)%3;a=Math.sqrt(n[3*e+e]-n[3*u+u]-n[3*o+o]+1),t[e]=.5*a,a=.5/a,t[3]=(n[3*u+o]-n[3*o+u])*a,t[u]=(n[3*u+e]+n[3*e+u])*a,t[o]=(n[3*o+e]+n[3*e+o])*a}return t}function m(t,n,r,a){var e=.5*Math.PI/180;n*=e,r*=e,a*=e;var u=Math.sin(n),o=Math.cos(n),i=Math.sin(r),s=Math.cos(r),c=Math.sin(a),f=Math.cos(a);return t[0]=u*s*f-o*i*c,t[1]=o*i*f+u*s*c,t[2]=o*s*c-u*i*f,t[3]=o*s*f+u*i*c,t}function p(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"}Object.defineProperty(n,"__esModule",{value:!0}),n.setAxes=n.sqlerp=n.rotationTo=n.equals=n.exactEquals=n.normalize=n.sqrLen=n.squaredLength=n.len=n.length=n.lerp=n.dot=n.scale=n.mul=n.add=n.set=n.copy=n.fromValues=n.clone=void 0,n.create=e,n.identity=u,n.setAxisAngle=o,n.getAxisAngle=i,n.multiply=s,n.rotateX=c,n.rotateY=f,n.rotateZ=M,n.calculateW=h,n.slerp=l,n.invert=v,n.conjugate=d,n.fromMat3=b,n.fromEuler=m,n.str=p;var P=r(0),E=a(P),O=r(1),x=a(O),A=r(2),q=a(A),y=r(3),w=a(y),R=(n.clone=w.clone,n.fromValues=w.fromValues,n.copy=w.copy,n.set=w.set,n.add=w.add,n.mul=s,n.scale=w.scale,n.dot=w.dot,n.lerp=w.lerp,n.length=w.length),L=(n.len=R,n.squaredLength=w.squaredLength),S=(n.sqrLen=L,n.normalize=w.normalize);n.exactEquals=w.exactEquals,n.equals=w.equals,n.rotationTo=function(){var t=q.create(),n=q.fromValues(1,0,0),r=q.fromValues(0,1,0);return function(a,e,u){var i=q.dot(e,u);return i<-.999999?(q.cross(t,n,e),q.len(t)<1e-6&&q.cross(t,r,e),q.normalize(t,t),o(a,t,Math.PI),a):i>.999999?(a[0]=0,a[1]=0,a[2]=0,a[3]=1,a):(q.cross(t,e,u),a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=1+i,S(a,a))}}(),n.sqlerp=function(){var t=e(),n=e();return function(r,a,e,u,o,i){return l(t,a,o,i),l(n,e,u,i),l(r,t,n,2*i*(1-i)),r}}(),n.setAxes=function(){var t=x.create();return function(n,r,a,e){return t[0]=a[0],t[3]=a[1],t[6]=a[2],t[1]=e[0],t[4]=e[1],t[7]=e[2],t[2]=-r[0],t[5]=-r[1],t[8]=-r[2],S(n,b(n,t))}}()},function(t,n,r){"use strict";function a(){var t=new V.ARRAY_TYPE(2);return t[0]=0,t[1]=0,t}function e(t){var n=new V.ARRAY_TYPE(2);return n[0]=t[0],n[1]=t[1],n}function u(t,n){var r=new V.ARRAY_TYPE(2);return r[0]=t,r[1]=n,r}function o(t,n){return t[0]=n[0],t[1]=n[1],t}function i(t,n,r){return t[0]=n,t[1]=r,t}function s(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t}function c(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t}function f(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t}function M(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t}function h(t,n){return t[0]=Math.ceil(n[0]),t[1]=Math.ceil(n[1]),t}function l(t,n){return t[0]=Math.floor(n[0]),t[1]=Math.floor(n[1]),t}function v(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t}function d(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t}function b(t,n){return t[0]=Math.round(n[0]),t[1]=Math.round(n[1]),t}function m(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t}function p(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t}function P(t,n){var r=n[0]-t[0],a=n[1]-t[1];return Math.sqrt(r*r+a*a)}function E(t,n){var r=n[0]-t[0],a=n[1]-t[1];return r*r+a*a}function O(t){var n=t[0],r=t[1];return Math.sqrt(n*n+r*r)}function x(t){var n=t[0],r=t[1];return n*n+r*r}function A(t,n){return t[0]=-n[0],t[1]=-n[1],t}function q(t,n){return t[0]=1/n[0],t[1]=1/n[1],t}function y(t,n){var r=n[0],a=n[1],e=r*r+a*a;return e>0&&(e=1/Math.sqrt(e),t[0]=n[0]*e,t[1]=n[1]*e),t}function w(t,n){return t[0]*n[0]+t[1]*n[1]}function R(t,n,r){var a=n[0]*r[1]-n[1]*r[0];return t[0]=t[1]=0,t[2]=a,t}function L(t,n,r,a){var e=n[0],u=n[1];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t}function S(t,n){n=n||1;var r=2*V.RANDOM()*Math.PI;return t[0]=Math.cos(r)*n,t[1]=Math.sin(r)*n,t}function _(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e,t[1]=r[1]*a+r[3]*e,t}function I(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e+r[4],t[1]=r[1]*a+r[3]*e+r[5],t}function N(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[3]*e+r[6],t[1]=r[1]*a+r[4]*e+r[7],t}function Y(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[4]*e+r[12],t[1]=r[1]*a+r[5]*e+r[13],t}function g(t){return"vec2("+t[0]+", "+t[1]+")"}function T(t,n){return t[0]===n[0]&&t[1]===n[1]}function j(t,n){var r=t[0],a=t[1],e=n[0],u=n[1];return Math.abs(r-e)<=V.EPSILON*Math.max(1,Math.abs(r),Math.abs(e))&&Math.abs(a-u)<=V.EPSILON*Math.max(1,Math.abs(a),Math.abs(u))}Object.defineProperty(n,"__esModule",{value:!0}),n.forEach=n.sqrLen=n.sqrDist=n.dist=n.div=n.mul=n.sub=n.len=void 0,n.create=a,n.clone=e,n.fromValues=u,n.copy=o,n.set=i,n.add=s,n.subtract=c,n.multiply=f,n.divide=M,n.ceil=h,n.floor=l,n.min=v,n.max=d,n.round=b,n.scale=m,n.scaleAndAdd=p,n.distance=P,n.squaredDistance=E,n.length=O,n.squaredLength=x,n.negate=A,n.inverse=q,n.normalize=y,n.dot=w,n.cross=R,n.lerp=L,n.random=S,n.transformMat2=_,n.transformMat2d=I,n.transformMat3=N,n.transformMat4=Y,n.str=g,n.exactEquals=T,n.equals=j;var D=r(0),V=function(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n.default=t,n}(D);n.len=O,n.sub=c,n.mul=f,n.div=M,n.dist=P,n.sqrDist=E,n.sqrLen=x,n.forEach=function(){var t=a();return function(n,r,a,e,u,o){var i=void 0,s=void 0;for(r||(r=2),a||(a=0),s=e?Math.min(e*r+a,n.length):n.length,i=a;i 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; -}; + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to rotate + * @param {vec2} v the vec2 to scale the matrix by + * @returns {mat3} out + **/ +function scale(out, a, v) { + var x = v[0], + y = v[1]; + + out[0] = x * a[0]; + out[1] = x * a[1]; + out[2] = x * a[2]; + + out[3] = y * a[3]; + out[4] = y * a[4]; + out[5] = y * a[5]; + + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + return out; +} /** - * Calculates the dot product of two vec2's + * Creates a matrix from a vector translation + * This is equivalent to (but much faster than): * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} dot product of a and b + * mat3.identity(dest); + * mat3.translate(dest, dest, vec); + * + * @param {mat3} out mat3 receiving operation result + * @param {vec2} v Translation vector + * @returns {mat3} out */ -vec2.dot = function (a, b) { - return a[0] * b[0] + a[1] * b[1]; -}; +function fromTranslation(out, v) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 1; + out[5] = 0; + out[6] = v[0]; + out[7] = v[1]; + out[8] = 1; + return out; +} /** - * Computes the cross product of two vec2's - * Note that the cross product must by definition produce a 3D vector + * Creates a matrix from a given angle + * This is equivalent to (but much faster than): * - * @param {vec3} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec3} out + * mat3.identity(dest); + * mat3.rotate(dest, dest, rad); + * + * @param {mat3} out mat3 receiving operation result + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat3} out */ -vec2.cross = function(out, a, b) { - var z = a[0] * b[1] - a[1] * b[0]; - out[0] = out[1] = 0; - out[2] = z; - return out; -}; +function fromRotation(out, rad) { + var s = Math.sin(rad), + c = Math.cos(rad); + + out[0] = c; + out[1] = s; + out[2] = 0; + + out[3] = -s; + out[4] = c; + out[5] = 0; + + out[6] = 0; + out[7] = 0; + out[8] = 1; + return out; +} /** - * Performs a linear interpolation between two vec2's + * Creates a matrix from a vector scaling + * This is equivalent to (but much faster than): * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec2} out + * mat3.identity(dest); + * mat3.scale(dest, dest, vec); + * + * @param {mat3} out mat3 receiving operation result + * @param {vec2} v Scaling vector + * @returns {mat3} out */ -vec2.lerp = function (out, a, b, t) { - var ax = a[0], - ay = a[1]; - out[0] = ax + t * (b[0] - ax); - out[1] = ay + t * (b[1] - ay); - return out; -}; +function fromScaling(out, v) { + out[0] = v[0]; + out[1] = 0; + out[2] = 0; + + out[3] = 0; + out[4] = v[1]; + out[5] = 0; + + out[6] = 0; + out[7] = 0; + out[8] = 1; + return out; +} /** - * Generates a random vector with the given scale + * Copies the values from a mat2d into a mat3 * - * @param {vec2} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec2} out - */ -vec2.random = function (out, scale) { - scale = scale || 1.0; - var r = GLMAT_RANDOM() * 2.0 * Math.PI; - out[0] = Math.cos(r) * scale; - out[1] = Math.sin(r) * scale; - return out; -}; + * @param {mat3} out the receiving matrix + * @param {mat2d} a the matrix to copy + * @returns {mat3} out + **/ +function fromMat2d(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = 0; + + out[3] = a[2]; + out[4] = a[3]; + out[5] = 0; + + out[6] = a[4]; + out[7] = a[5]; + out[8] = 1; + return out; +} /** - * Transforms the vec2 with a mat2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat2} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat2 = function(out, a, m) { - var x = a[0], - y = a[1]; - out[0] = m[0] * x + m[2] * y; - out[1] = m[1] * x + m[3] * y; - return out; -}; +* Calculates a 3x3 matrix from the given quaternion +* +* @param {mat3} out mat3 receiving operation result +* @param {quat} q Quaternion to create matrix from +* +* @returns {mat3} out +*/ +function fromQuat(out, q) { + var x = q[0], + y = q[1], + z = q[2], + w = q[3]; + var x2 = x + x; + var y2 = y + y; + var z2 = z + z; + + var xx = x * x2; + var yx = y * x2; + var yy = y * y2; + var zx = z * x2; + var zy = z * y2; + var zz = z * z2; + var wx = w * x2; + var wy = w * y2; + var wz = w * z2; + + out[0] = 1 - yy - zz; + out[3] = yx - wz; + out[6] = zx + wy; + + out[1] = yx + wz; + out[4] = 1 - xx - zz; + out[7] = zy - wx; + + out[2] = zx - wy; + out[5] = zy + wx; + out[8] = 1 - xx - yy; + + return out; +} /** - * Transforms the vec2 with a mat2d - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat2d} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat2d = function(out, a, m) { - var x = a[0], - y = a[1]; - out[0] = m[0] * x + m[2] * y + m[4]; - out[1] = m[1] * x + m[3] * y + m[5]; - return out; -}; +* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix +* +* @param {mat3} out mat3 receiving operation result +* @param {mat4} a Mat4 to derive the normal matrix from +* +* @returns {mat3} out +*/ +function normalFromMat4(out, a) { + var a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3]; + var a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7]; + var a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; + var a30 = a[12], + a31 = a[13], + a32 = a[14], + a33 = a[15]; + + var b00 = a00 * a11 - a01 * a10; + var b01 = a00 * a12 - a02 * a10; + var b02 = a00 * a13 - a03 * a10; + var b03 = a01 * a12 - a02 * a11; + var b04 = a01 * a13 - a03 * a11; + var b05 = a02 * a13 - a03 * a12; + var b06 = a20 * a31 - a21 * a30; + var b07 = a20 * a32 - a22 * a30; + var b08 = a20 * a33 - a23 * a30; + var b09 = a21 * a32 - a22 * a31; + var b10 = a21 * a33 - a23 * a31; + var b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + var 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] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + + out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + + out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + + return out; +} /** - * Transforms the vec2 with a mat3 - * 3rd vector component is implicitly '1' + * Generates a 2D projection matrix with the given bounds * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat3} m matrix to transform with - * @returns {vec2} out + * @param {mat3} out mat3 frustum matrix will be written into + * @param {number} width Width of your gl context + * @param {number} height Height of gl context + * @returns {mat3} out */ -vec2.transformMat3 = function(out, a, m) { - var x = a[0], - y = a[1]; - out[0] = m[0] * x + m[3] * y + m[6]; - out[1] = m[1] * x + m[4] * y + m[7]; - return out; -}; +function projection(out, width, height) { + out[0] = 2 / width; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = -2 / height; + out[5] = 0; + out[6] = -1; + out[7] = 1; + out[8] = 1; + return out; +} /** - * Transforms the vec2 with a mat4 - * 3rd vector component is implicitly '0' - * 4th vector component is implicitly '1' + * Returns a string representation of a mat3 * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec2} out + * @param {mat3} a matrix to represent as a string + * @returns {String} string representation of the matrix */ -vec2.transformMat4 = function(out, a, m) { - var x = a[0], - y = a[1]; - out[0] = m[0] * x + m[4] * y + m[12]; - out[1] = m[1] * x + m[5] * y + m[13]; - return out; -}; +function str(a) { + return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ')'; +} /** - * Perform some operation over an array of vec2s. + * Returns Frobenius norm of a mat3 * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec2s 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 + * @param {mat3} a the matrix to calculate Frobenius norm of + * @returns {Number} Frobenius norm + */ +function frob(a) { + return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)); +} + +/** + * Adds two mat3's + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the first operand + * @param {mat3} b the second operand + * @returns {mat3} out + */ +function add(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; + out[4] = a[4] + b[4]; + out[5] = a[5] + b[5]; + out[6] = a[6] + b[6]; + out[7] = a[7] + b[7]; + out[8] = a[8] + b[8]; + return out; +} + +/** + * Subtracts matrix b from matrix a + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the first operand + * @param {mat3} b the second operand + * @returns {mat3} out + */ +function subtract(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + out[3] = a[3] - b[3]; + out[4] = a[4] - b[4]; + out[5] = a[5] - b[5]; + out[6] = a[6] - b[6]; + out[7] = a[7] - b[7]; + out[8] = a[8] - b[8]; + return out; +} + +/** + * Multiply each element of the matrix by a scalar. + * + * @param {mat3} out the receiving matrix + * @param {mat3} a the matrix to scale + * @param {Number} b amount to scale the matrix's elements by + * @returns {mat3} out + */ +function multiplyScalar(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + out[3] = a[3] * b; + out[4] = a[4] * b; + out[5] = a[5] * b; + out[6] = a[6] * b; + out[7] = a[7] * b; + out[8] = a[8] * b; + return out; +} + +/** + * Adds two mat3's after multiplying each element of the second operand by a scalar value. + * + * @param {mat3} out the receiving vector + * @param {mat3} a the first operand + * @param {mat3} b the second operand + * @param {Number} scale the amount to scale b's elements by before adding + * @returns {mat3} out + */ +function multiplyScalarAndAdd(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; + out[3] = a[3] + b[3] * scale; + out[4] = a[4] + b[4] * scale; + out[5] = a[5] + b[5] * scale; + out[6] = a[6] + b[6] * scale; + out[7] = a[7] + b[7] * scale; + out[8] = a[8] + b[8] * scale; + return out; +} + +/** + * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) + * + * @param {mat3} a The first matrix. + * @param {mat3} b The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ +function exactEquals(a, b) { + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8]; +} + +/** + * Returns whether or not the matrices have approximately the same elements in the same position. + * + * @param {mat3} a The first matrix. + * @param {mat3} b The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ +function equals(a, b) { + var a0 = a[0], + a1 = a[1], + a2 = a[2], + a3 = a[3], + a4 = a[4], + a5 = a[5], + a6 = a[6], + a7 = a[7], + a8 = a[8]; + var b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3], + b4 = b[4], + b5 = b[5], + b6 = b[6], + b7 = b[7], + b8 = b[8]; + return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)); +} + +/** + * Alias for {@link mat3.multiply} * @function */ -vec2.forEach = (function() { - var vec = vec2.create(); - - return function(a, stride, offset, count, fn, arg) { - var i, l; - if(!stride) { - stride = 2; - } - - 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]; - fn(vec, vec, arg); - a[i] = vec[0]; a[i+1] = vec[1]; - } - - return a; - }; -})(); +var mul = exports.mul = multiply; /** - * Returns a string representation of a vector - * - * @param {vec2} vec vector to represent as a string - * @returns {String} string representation of the vector + * Alias for {@link mat3.subtract} + * @function */ -vec2.str = function (a) { - return 'vec2(' + a[0] + ', ' + a[1] + ')'; -}; +var sub = exports.sub = subtract; -if(typeof(exports) !== 'undefined') { - exports.vec2 = vec2; -} -; -/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +"use strict"; - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.forEach = exports.sqrLen = exports.len = exports.sqrDist = exports.dist = exports.div = exports.mul = exports.sub = undefined; +exports.create = create; +exports.clone = clone; +exports.length = length; +exports.fromValues = fromValues; +exports.copy = copy; +exports.set = set; +exports.add = add; +exports.subtract = subtract; +exports.multiply = multiply; +exports.divide = divide; +exports.ceil = ceil; +exports.floor = floor; +exports.min = min; +exports.max = max; +exports.round = round; +exports.scale = scale; +exports.scaleAndAdd = scaleAndAdd; +exports.distance = distance; +exports.squaredDistance = squaredDistance; +exports.squaredLength = squaredLength; +exports.negate = negate; +exports.inverse = inverse; +exports.normalize = normalize; +exports.dot = dot; +exports.cross = cross; +exports.lerp = lerp; +exports.hermite = hermite; +exports.bezier = bezier; +exports.random = random; +exports.transformMat4 = transformMat4; +exports.transformMat3 = transformMat3; +exports.transformQuat = transformQuat; +exports.rotateX = rotateX; +exports.rotateY = rotateY; +exports.rotateZ = rotateZ; +exports.angle = angle; +exports.str = str; +exports.exactEquals = exactEquals; +exports.equals = equals; + +var _common = __webpack_require__(0); + +var glMatrix = _interopRequireWildcard(_common); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } /** - * @class 3 Dimensional Vector - * @name vec3 + * 3 Dimensional Vector + * @module vec3 */ -var vec3 = {}; - /** * Creates a new, empty vec3 * * @returns {vec3} a new 3D vector */ -vec3.create = function() { - var out = new GLMAT_ARRAY_TYPE(3); - out[0] = 0; - out[1] = 0; - out[2] = 0; - return out; -}; +function create() { + var out = new glMatrix.ARRAY_TYPE(3); + out[0] = 0; + out[1] = 0; + out[2] = 0; + return out; +} /** * Creates a new vec3 initialized with values from an existing vector @@ -689,13 +1132,46 @@ vec3.create = function() { * @param {vec3} a vector to clone * @returns {vec3} a new 3D vector */ -vec3.clone = function(a) { - var out = new GLMAT_ARRAY_TYPE(3); - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - return out; -}; +/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ + +function clone(a) { + var out = new glMatrix.ARRAY_TYPE(3); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + return out; +} + +/** + * 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]; + var y = a[1]; + var z = a[2]; + return Math.sqrt(x * x + y * y + z * z); +} /** * Creates a new vec3 initialized with the given values @@ -705,13 +1181,13 @@ vec3.clone = function(a) { * @param {Number} z Z component * @returns {vec3} a new 3D vector */ -vec3.fromValues = function(x, y, z) { - var out = new GLMAT_ARRAY_TYPE(3); - out[0] = x; - out[1] = y; - out[2] = z; - return out; -}; +function fromValues(x, y, z) { + var out = new glMatrix.ARRAY_TYPE(3); + out[0] = x; + out[1] = y; + out[2] = z; + return out; +} /** * Copy the values from one vec3 to another @@ -720,12 +1196,12 @@ vec3.fromValues = function(x, y, z) { * @param {vec3} a the source vector * @returns {vec3} out */ -vec3.copy = function(out, a) { - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - return out; -}; +function copy(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + return out; +} /** * Set the components of a vec3 to the given values @@ -736,12 +1212,12 @@ vec3.copy = function(out, a) { * @param {Number} z Z component * @returns {vec3} out */ -vec3.set = function(out, x, y, z) { - out[0] = x; - out[1] = y; - out[2] = z; - return out; -}; +function set(out, x, y, z) { + out[0] = x; + out[1] = y; + out[2] = z; + return out; +} /** * Adds two vec3's @@ -751,12 +1227,12 @@ vec3.set = function(out, x, y, z) { * @param {vec3} b the second operand * @returns {vec3} out */ -vec3.add = function(out, a, b) { - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; - return 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; +} /** * Subtracts vector b from vector a @@ -766,18 +1242,12 @@ vec3.add = function(out, a, b) { * @param {vec3} b the second operand * @returns {vec3} out */ -vec3.subtract = function(out, a, b) { - out[0] = a[0] - b[0]; - out[1] = a[1] - b[1]; - out[2] = a[2] - b[2]; - return out; -}; - -/** - * Alias for {@link vec3.subtract} - * @function - */ -vec3.sub = vec3.subtract; +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; +} /** * Multiplies two vec3's @@ -787,18 +1257,12 @@ vec3.sub = vec3.subtract; * @param {vec3} b the second operand * @returns {vec3} out */ -vec3.multiply = function(out, a, b) { - out[0] = a[0] * b[0]; - out[1] = a[1] * b[1]; - out[2] = a[2] * b[2]; - return out; -}; - -/** - * Alias for {@link vec3.multiply} - * @function - */ -vec3.mul = vec3.multiply; +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; +} /** * Divides two vec3's @@ -808,18 +1272,40 @@ vec3.mul = vec3.multiply; * @param {vec3} b the second operand * @returns {vec3} out */ -vec3.divide = function(out, a, b) { - out[0] = a[0] / b[0]; - out[1] = a[1] / b[1]; - out[2] = a[2] / b[2]; - return 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; +} /** - * Alias for {@link vec3.divide} - * @function + * Math.ceil the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to ceil + * @returns {vec3} out */ -vec3.div = vec3.divide; +function ceil(out, a) { + out[0] = Math.ceil(a[0]); + out[1] = Math.ceil(a[1]); + out[2] = Math.ceil(a[2]); + return out; +} + +/** + * Math.floor the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to floor + * @returns {vec3} out + */ +function floor(out, a) { + out[0] = Math.floor(a[0]); + out[1] = Math.floor(a[1]); + out[2] = Math.floor(a[2]); + return out; +} /** * Returns the minimum of two vec3's @@ -829,12 +1315,12 @@ vec3.div = vec3.divide; * @param {vec3} b the second operand * @returns {vec3} out */ -vec3.min = function(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; -}; +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; +} /** * Returns the maximum of two vec3's @@ -844,12 +1330,26 @@ vec3.min = function(out, a, b) { * @param {vec3} b the second operand * @returns {vec3} out */ -vec3.max = function(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; -}; +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; +} + +/** + * Math.round the components of a vec3 + * + * @param {vec3} out the receiving vector + * @param {vec3} a vector to round + * @returns {vec3} out + */ +function round(out, a) { + out[0] = Math.round(a[0]); + out[1] = Math.round(a[1]); + out[2] = Math.round(a[2]); + return out; +} /** * Scales a vec3 by a scalar number @@ -859,12 +1359,12 @@ vec3.max = function(out, a, b) { * @param {Number} b amount to scale the vector by * @returns {vec3} out */ -vec3.scale = function(out, a, b) { - out[0] = a[0] * b; - out[1] = a[1] * b; - out[2] = a[2] * b; - return out; -}; +function scale(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + return out; +} /** * Adds two vec3's after scaling the second operand by a scalar value @@ -875,12 +1375,12 @@ vec3.scale = function(out, a, b) { * @param {Number} scale the amount to scale b by before adding * @returns {vec3} out */ -vec3.scaleAndAdd = function(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; -}; +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; +} /** * Calculates the euclidian distance between two vec3's @@ -889,18 +1389,12 @@ vec3.scaleAndAdd = function(out, a, b, scale) { * @param {vec3} b the second operand * @returns {Number} distance between a and b */ -vec3.distance = function(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); -}; - -/** - * Alias for {@link vec3.distance} - * @function - */ -vec3.dist = vec3.distance; +function distance(a, b) { + var x = b[0] - a[0]; + var y = b[1] - a[1]; + var z = b[2] - a[2]; + return Math.sqrt(x * x + y * y + z * z); +} /** * Calculates the squared euclidian distance between two vec3's @@ -909,37 +1403,12 @@ vec3.dist = vec3.distance; * @param {vec3} b the second operand * @returns {Number} squared distance between a and b */ -vec3.squaredDistance = function(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; -}; - -/** - * Alias for {@link vec3.squaredDistance} - * @function - */ -vec3.sqrDist = vec3.squaredDistance; - -/** - * Calculates the length of a vec3 - * - * @param {vec3} a vector to calculate length of - * @returns {Number} length of a - */ -vec3.length = function (a) { - var x = a[0], - y = a[1], - z = a[2]; - return Math.sqrt(x*x + y*y + z*z); -}; - -/** - * Alias for {@link vec3.length} - * @function - */ -vec3.len = vec3.length; +function squaredDistance(a, b) { + var x = b[0] - a[0]; + var y = b[1] - a[1]; + var z = b[2] - a[2]; + return x * x + y * y + z * z; +} /** * Calculates the squared length of a vec3 @@ -947,18 +1416,12 @@ vec3.len = vec3.length; * @param {vec3} a vector to calculate squared length of * @returns {Number} squared length of a */ -vec3.squaredLength = function (a) { - var x = a[0], - y = a[1], - z = a[2]; - return x*x + y*y + z*z; -}; - -/** - * Alias for {@link vec3.squaredLength} - * @function - */ -vec3.sqrLen = vec3.squaredLength; +function squaredLength(a) { + var x = a[0]; + var y = a[1]; + var z = a[2]; + return x * x + y * y + z * z; +} /** * Negates the components of a vec3 @@ -967,12 +1430,12 @@ vec3.sqrLen = vec3.squaredLength; * @param {vec3} a vector to negate * @returns {vec3} out */ -vec3.negate = function(out, a) { - out[0] = -a[0]; - out[1] = -a[1]; - out[2] = -a[2]; - return out; -}; +function negate(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + return out; +} /** * Returns the inverse of the components of a vec3 @@ -981,12 +1444,12 @@ vec3.negate = function(out, a) { * @param {vec3} a vector to invert * @returns {vec3} out */ -vec3.inverse = function(out, a) { +function inverse(out, a) { out[0] = 1.0 / a[0]; out[1] = 1.0 / a[1]; out[2] = 1.0 / a[2]; return out; -}; +} /** * Normalize a vec3 @@ -995,20 +1458,20 @@ vec3.inverse = function(out, a) { * @param {vec3} a vector to normalize * @returns {vec3} out */ -vec3.normalize = function(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; -}; +function normalize(out, a) { + var x = a[0]; + var y = a[1]; + var 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; +} /** * Calculates the dot product of two vec3's @@ -1017,9 +1480,9 @@ vec3.normalize = function(out, a) { * @param {vec3} b the second operand * @returns {Number} dot product of a and b */ -vec3.dot = function (a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; -}; +function dot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} /** * Computes the cross product of two vec3's @@ -1029,15 +1492,19 @@ vec3.dot = function (a, b) { * @param {vec3} b the second operand * @returns {vec3} out */ -vec3.cross = function(out, a, b) { - var ax = a[0], ay = a[1], az = a[2], - bx = b[0], by = b[1], bz = b[2]; +function cross(out, a, b) { + var ax = a[0], + ay = a[1], + az = a[2]; + var 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; -}; + out[0] = ay * bz - az * by; + out[1] = az * bx - ax * bz; + out[2] = ax * by - ay * bx; + return out; +} /** * Performs a linear interpolation between two vec3's @@ -1048,15 +1515,67 @@ vec3.cross = function(out, a, b) { * @param {Number} t interpolation amount between the two inputs * @returns {vec3} out */ -vec3.lerp = function (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; -}; +function lerp(out, a, b, t) { + var ax = a[0]; + var ay = a[1]; + var 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; +} + +/** + * Performs a hermite interpolation with two control points + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {vec3} c the third operand + * @param {vec3} d the fourth operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec3} out + */ +function hermite(out, a, b, c, d, t) { + var factorTimes2 = t * t; + var factor1 = factorTimes2 * (2 * t - 3) + 1; + var factor2 = factorTimes2 * (t - 2) + t; + var factor3 = factorTimes2 * (t - 1); + var factor4 = factorTimes2 * (3 - 2 * t); + + out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4; + out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4; + out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4; + + return out; +} + +/** + * Performs a bezier interpolation with two control points + * + * @param {vec3} out the receiving vector + * @param {vec3} a the first operand + * @param {vec3} b the second operand + * @param {vec3} c the third operand + * @param {vec3} d the fourth operand + * @param {Number} t interpolation amount between the two inputs + * @returns {vec3} out + */ +function bezier(out, a, b, c, d, t) { + var inverseFactor = 1 - t; + var inverseFactorTimesTwo = inverseFactor * inverseFactor; + var factorTimes2 = t * t; + var factor1 = inverseFactorTimesTwo * inverseFactor; + var factor2 = 3 * t * inverseFactorTimesTwo; + var factor3 = 3 * factorTimes2 * inverseFactor; + var factor4 = factorTimes2 * t; + + out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4; + out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4; + out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4; + + return out; +} /** * Generates a random vector with the given scale @@ -1065,18 +1584,18 @@ vec3.lerp = function (out, a, b, t) { * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec3} out */ -vec3.random = function (out, scale) { - scale = scale || 1.0; +function random(out, scale) { + scale = scale || 1.0; - var r = GLMAT_RANDOM() * 2.0 * Math.PI; - var z = (GLMAT_RANDOM() * 2.0) - 1.0; - var zScale = Math.sqrt(1.0-z*z) * scale; + var r = glMatrix.RANDOM() * 2.0 * Math.PI; + var z = glMatrix.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; -}; + out[0] = Math.cos(r) * zScale; + out[1] = Math.sin(r) * zScale; + out[2] = z * scale; + return out; +} /** * Transforms the vec3 with a mat4. @@ -1087,31 +1606,35 @@ vec3.random = function (out, scale) { * @param {mat4} m matrix to transform with * @returns {vec3} out */ -vec3.transformMat4 = function(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; -}; +function transformMat4(out, a, m) { + var x = a[0], + y = a[1], + z = a[2]; + var 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; +} /** * 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 + * @param {mat3} m the 3x3 matrix to transform with * @returns {vec3} out */ -vec3.transformMat3 = function(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; -}; +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; +} /** * Transforms the vec3 with a quat @@ -1121,24 +1644,29 @@ vec3.transformMat3 = function(out, a, m) { * @param {quat} q quaternion to transform with * @returns {vec3} out */ -vec3.transformQuat = function(out, a, q) { - // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations +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], + var x = a[0], + y = a[1], + z = a[2]; + var 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 quat * vec + var ix = qw * x + qy * z - qz * y; + var iy = qw * y + qz * x - qx * z; + var iz = qw * z + qx * y - qy * x; + var 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; -}; + // 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; +} /** * Rotate a 3D vector around the x-axis @@ -1148,25 +1676,26 @@ vec3.transformQuat = function(out, a, q) { * @param {Number} c The angle of rotation * @returns {vec3} out */ -vec3.rotateX = function(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]; +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); + //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]; + //translate to correct position + out[0] = r[0] + b[0]; + out[1] = r[1] + b[1]; + out[2] = r[2] + b[2]; - return out; -}; + return out; +} /** * Rotate a 3D vector around the y-axis @@ -1176,25 +1705,26 @@ vec3.rotateX = function(out, a, b, c){ * @param {Number} c The angle of rotation * @returns {vec3} out */ -vec3.rotateY = function(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; -}; +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; +} /** * Rotate a 3D vector around the z-axis @@ -1204,25 +1734,130 @@ vec3.rotateY = function(out, a, b, c){ * @param {Number} c The angle of rotation * @returns {vec3} out */ -vec3.rotateZ = function(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; -}; +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; +} + +/** + * 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 if (cosine < -1.0) { + return Math.PI; + } else { + return Math.acos(cosine); + } +} + +/** + * Returns a string representation of a vector + * + * @param {vec3} a vector to represent as a string + * @returns {String} string representation of the vector + */ +function str(a) { + return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; +} + +/** + * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) + * + * @param {vec3} a The first vector. + * @param {vec3} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ +function exactEquals(a, b) { + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2]; +} + +/** + * Returns whether or not the vectors have approximately the same elements in the same position. + * + * @param {vec3} a The first vector. + * @param {vec3} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ +function equals(a, b) { + var a0 = a[0], + a1 = a[1], + a2 = a[2]; + var b0 = b[0], + b1 = b[1], + b2 = b[2]; + return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)); +} + +/** + * Alias for {@link vec3.subtract} + * @function + */ +var sub = exports.sub = subtract; + +/** + * Alias for {@link vec3.multiply} + * @function + */ +var mul = exports.mul = multiply; + +/** + * Alias for {@link vec3.divide} + * @function + */ +var div = exports.div = divide; + +/** + * Alias for {@link vec3.distance} + * @function + */ +var dist = exports.dist = distance; + +/** + * Alias for {@link vec3.squaredDistance} + * @function + */ +var sqrDist = exports.sqrDist = squaredDistance; + +/** + * Alias for {@link vec3.length} + * @function + */ +var len = exports.len = length; + +/** + * Alias for {@link vec3.squaredLength} + * @function + */ +var sqrLen = exports.sqrLen = squaredLength; /** * Perform some operation over an array of vec3s. @@ -1236,91 +1871,103 @@ vec3.rotateZ = function(out, a, b, c){ * @returns {Array} a * @function */ -vec3.forEach = (function() { - var vec = vec3.create(); +var forEach = exports.forEach = function () { + var vec = create(); - return function(a, stride, offset, count, fn, arg) { - var i, l; - if(!stride) { - stride = 3; - } + return function (a, stride, offset, count, fn, arg) { + var i = void 0, + l = void 0; + if (!stride) { + stride = 3; + } - if(!offset) { - offset = 0; - } - - if(count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } + if (!offset) { + offset = 0; + } - 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; - }; -})(); + 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; + }; +}(); + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.forEach = exports.sqrLen = exports.len = exports.sqrDist = exports.dist = exports.div = exports.mul = exports.sub = undefined; +exports.create = create; +exports.clone = clone; +exports.fromValues = fromValues; +exports.copy = copy; +exports.set = set; +exports.add = add; +exports.subtract = subtract; +exports.multiply = multiply; +exports.divide = divide; +exports.ceil = ceil; +exports.floor = floor; +exports.min = min; +exports.max = max; +exports.round = round; +exports.scale = scale; +exports.scaleAndAdd = scaleAndAdd; +exports.distance = distance; +exports.squaredDistance = squaredDistance; +exports.length = length; +exports.squaredLength = squaredLength; +exports.negate = negate; +exports.inverse = inverse; +exports.normalize = normalize; +exports.dot = dot; +exports.lerp = lerp; +exports.random = random; +exports.transformMat4 = transformMat4; +exports.transformQuat = transformQuat; +exports.str = str; +exports.exactEquals = exactEquals; +exports.equals = equals; + +var _common = __webpack_require__(0); + +var glMatrix = _interopRequireWildcard(_common); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } /** - * Returns a string representation of a vector - * - * @param {vec3} vec vector to represent as a string - * @returns {String} string representation of the vector + * 4 Dimensional Vector + * @module vec4 */ -vec3.str = function (a) { - return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; -}; - -if(typeof(exports) !== 'undefined') { - exports.vec3 = vec3; -} -; -/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/** - * @class 4 Dimensional Vector - * @name vec4 - */ - -var vec4 = {}; /** * Creates a new, empty vec4 * * @returns {vec4} a new 4D vector */ -vec4.create = function() { - var out = new GLMAT_ARRAY_TYPE(4); - out[0] = 0; - out[1] = 0; - out[2] = 0; - out[3] = 0; - return out; -}; +function create() { + var out = new glMatrix.ARRAY_TYPE(4); + out[0] = 0; + out[1] = 0; + out[2] = 0; + out[3] = 0; + return out; +} /** * Creates a new vec4 initialized with values from an existing vector @@ -1328,14 +1975,34 @@ vec4.create = function() { * @param {vec4} a vector to clone * @returns {vec4} a new 4D vector */ -vec4.clone = function(a) { - var out = new GLMAT_ARRAY_TYPE(4); - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - return out; -}; +/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ + +function clone(a) { + var out = new glMatrix.ARRAY_TYPE(4); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +} /** * Creates a new vec4 initialized with the given values @@ -1346,14 +2013,14 @@ vec4.clone = function(a) { * @param {Number} w W component * @returns {vec4} a new 4D vector */ -vec4.fromValues = function(x, y, z, w) { - var out = new GLMAT_ARRAY_TYPE(4); - out[0] = x; - out[1] = y; - out[2] = z; - out[3] = w; - return out; -}; +function fromValues(x, y, z, w) { + var out = new glMatrix.ARRAY_TYPE(4); + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = w; + return out; +} /** * Copy the values from one vec4 to another @@ -1362,13 +2029,13 @@ vec4.fromValues = function(x, y, z, w) { * @param {vec4} a the source vector * @returns {vec4} out */ -vec4.copy = function(out, a) { - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - return out; -}; +function copy(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +} /** * Set the components of a vec4 to the given values @@ -1380,13 +2047,13 @@ vec4.copy = function(out, a) { * @param {Number} w W component * @returns {vec4} out */ -vec4.set = function(out, x, y, z, w) { - out[0] = x; - out[1] = y; - out[2] = z; - out[3] = w; - return out; -}; +function set(out, x, y, z, w) { + out[0] = x; + out[1] = y; + out[2] = z; + out[3] = w; + return out; +} /** * Adds two vec4's @@ -1396,13 +2063,13 @@ vec4.set = function(out, x, y, z, w) { * @param {vec4} b the second operand * @returns {vec4} out */ -vec4.add = function(out, a, b) { - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; - out[3] = a[3] + b[3]; - return out; -}; +function add(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; + return out; +} /** * Subtracts vector b from vector a @@ -1412,19 +2079,13 @@ vec4.add = function(out, a, b) { * @param {vec4} b the second operand * @returns {vec4} out */ -vec4.subtract = function(out, a, b) { - out[0] = a[0] - b[0]; - out[1] = a[1] - b[1]; - out[2] = a[2] - b[2]; - out[3] = a[3] - b[3]; - return out; -}; - -/** - * Alias for {@link vec4.subtract} - * @function - */ -vec4.sub = vec4.subtract; +function subtract(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + out[3] = a[3] - b[3]; + return out; +} /** * Multiplies two vec4's @@ -1434,19 +2095,13 @@ vec4.sub = vec4.subtract; * @param {vec4} b the second operand * @returns {vec4} out */ -vec4.multiply = function(out, a, b) { - out[0] = a[0] * b[0]; - out[1] = a[1] * b[1]; - out[2] = a[2] * b[2]; - out[3] = a[3] * b[3]; - return out; -}; - -/** - * Alias for {@link vec4.multiply} - * @function - */ -vec4.mul = vec4.multiply; +function multiply(out, a, b) { + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; + out[3] = a[3] * b[3]; + return out; +} /** * Divides two vec4's @@ -1456,19 +2111,43 @@ vec4.mul = vec4.multiply; * @param {vec4} b the second operand * @returns {vec4} out */ -vec4.divide = function(out, a, b) { - out[0] = a[0] / b[0]; - out[1] = a[1] / b[1]; - out[2] = a[2] / b[2]; - out[3] = a[3] / b[3]; - return out; -}; +function divide(out, a, b) { + out[0] = a[0] / b[0]; + out[1] = a[1] / b[1]; + out[2] = a[2] / b[2]; + out[3] = a[3] / b[3]; + return out; +} /** - * Alias for {@link vec4.divide} - * @function + * Math.ceil the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to ceil + * @returns {vec4} out */ -vec4.div = vec4.divide; +function ceil(out, a) { + out[0] = Math.ceil(a[0]); + out[1] = Math.ceil(a[1]); + out[2] = Math.ceil(a[2]); + out[3] = Math.ceil(a[3]); + return out; +} + +/** + * Math.floor the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to floor + * @returns {vec4} out + */ +function floor(out, a) { + out[0] = Math.floor(a[0]); + out[1] = Math.floor(a[1]); + out[2] = Math.floor(a[2]); + out[3] = Math.floor(a[3]); + return out; +} /** * Returns the minimum of two vec4's @@ -1478,13 +2157,13 @@ vec4.div = vec4.divide; * @param {vec4} b the second operand * @returns {vec4} out */ -vec4.min = function(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]); - out[3] = Math.min(a[3], b[3]); - return 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]); + out[3] = Math.min(a[3], b[3]); + return out; +} /** * Returns the maximum of two vec4's @@ -1494,13 +2173,28 @@ vec4.min = function(out, a, b) { * @param {vec4} b the second operand * @returns {vec4} out */ -vec4.max = function(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]); - out[3] = Math.max(a[3], b[3]); - return 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]); + out[3] = Math.max(a[3], b[3]); + return out; +} + +/** + * Math.round the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to round + * @returns {vec4} out + */ +function round(out, a) { + out[0] = Math.round(a[0]); + out[1] = Math.round(a[1]); + out[2] = Math.round(a[2]); + out[3] = Math.round(a[3]); + return out; +} /** * Scales a vec4 by a scalar number @@ -1510,13 +2204,13 @@ vec4.max = function(out, a, b) { * @param {Number} b amount to scale the vector by * @returns {vec4} out */ -vec4.scale = function(out, a, b) { - out[0] = a[0] * b; - out[1] = a[1] * b; - out[2] = a[2] * b; - out[3] = a[3] * b; - return out; -}; +function scale(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + out[3] = a[3] * b; + return out; +} /** * Adds two vec4's after scaling the second operand by a scalar value @@ -1527,13 +2221,13 @@ vec4.scale = function(out, a, b) { * @param {Number} scale the amount to scale b by before adding * @returns {vec4} out */ -vec4.scaleAndAdd = function(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); - out[3] = a[3] + (b[3] * scale); - return 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; + out[3] = a[3] + b[3] * scale; + return out; +} /** * Calculates the euclidian distance between two vec4's @@ -1542,19 +2236,13 @@ vec4.scaleAndAdd = function(out, a, b, scale) { * @param {vec4} b the second operand * @returns {Number} distance between a and b */ -vec4.distance = function(a, b) { - var x = b[0] - a[0], - y = b[1] - a[1], - z = b[2] - a[2], - w = b[3] - a[3]; - return Math.sqrt(x*x + y*y + z*z + w*w); -}; - -/** - * Alias for {@link vec4.distance} - * @function - */ -vec4.dist = vec4.distance; +function distance(a, b) { + var x = b[0] - a[0]; + var y = b[1] - a[1]; + var z = b[2] - a[2]; + var w = b[3] - a[3]; + return Math.sqrt(x * x + y * y + z * z + w * w); +} /** * Calculates the squared euclidian distance between two vec4's @@ -1563,19 +2251,13 @@ vec4.dist = vec4.distance; * @param {vec4} b the second operand * @returns {Number} squared distance between a and b */ -vec4.squaredDistance = function(a, b) { - var x = b[0] - a[0], - y = b[1] - a[1], - z = b[2] - a[2], - w = b[3] - a[3]; - return x*x + y*y + z*z + w*w; -}; - -/** - * Alias for {@link vec4.squaredDistance} - * @function - */ -vec4.sqrDist = vec4.squaredDistance; +function squaredDistance(a, b) { + var x = b[0] - a[0]; + var y = b[1] - a[1]; + var z = b[2] - a[2]; + var w = b[3] - a[3]; + return x * x + y * y + z * z + w * w; +} /** * Calculates the length of a vec4 @@ -1583,19 +2265,13 @@ vec4.sqrDist = vec4.squaredDistance; * @param {vec4} a vector to calculate length of * @returns {Number} length of a */ -vec4.length = function (a) { - var x = a[0], - y = a[1], - z = a[2], - w = a[3]; - return Math.sqrt(x*x + y*y + z*z + w*w); -}; - -/** - * Alias for {@link vec4.length} - * @function - */ -vec4.len = vec4.length; +function length(a) { + var x = a[0]; + var y = a[1]; + var z = a[2]; + var w = a[3]; + return Math.sqrt(x * x + y * y + z * z + w * w); +} /** * Calculates the squared length of a vec4 @@ -1603,19 +2279,13 @@ vec4.len = vec4.length; * @param {vec4} a vector to calculate squared length of * @returns {Number} squared length of a */ -vec4.squaredLength = function (a) { - var x = a[0], - y = a[1], - z = a[2], - w = a[3]; - return x*x + y*y + z*z + w*w; -}; - -/** - * Alias for {@link vec4.squaredLength} - * @function - */ -vec4.sqrLen = vec4.squaredLength; +function squaredLength(a) { + var x = a[0]; + var y = a[1]; + var z = a[2]; + var w = a[3]; + return x * x + y * y + z * z + w * w; +} /** * Negates the components of a vec4 @@ -1624,13 +2294,13 @@ vec4.sqrLen = vec4.squaredLength; * @param {vec4} a vector to negate * @returns {vec4} out */ -vec4.negate = function(out, a) { - out[0] = -a[0]; - out[1] = -a[1]; - out[2] = -a[2]; - out[3] = -a[3]; - return out; -}; +function negate(out, a) { + out[0] = -a[0]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = -a[3]; + return out; +} /** * Returns the inverse of the components of a vec4 @@ -1639,13 +2309,13 @@ vec4.negate = function(out, a) { * @param {vec4} a vector to invert * @returns {vec4} out */ -vec4.inverse = function(out, a) { +function inverse(out, a) { out[0] = 1.0 / a[0]; out[1] = 1.0 / a[1]; out[2] = 1.0 / a[2]; out[3] = 1.0 / a[3]; return out; -}; +} /** * Normalize a vec4 @@ -1654,21 +2324,21 @@ vec4.inverse = function(out, a) { * @param {vec4} a vector to normalize * @returns {vec4} out */ -vec4.normalize = function(out, a) { - var x = a[0], - y = a[1], - z = a[2], - w = a[3]; - var len = x*x + y*y + z*z + w*w; - if (len > 0) { - len = 1 / Math.sqrt(len); - out[0] = a[0] * len; - out[1] = a[1] * len; - out[2] = a[2] * len; - out[3] = a[3] * len; - } - return out; -}; +function normalize(out, a) { + var x = a[0]; + var y = a[1]; + var z = a[2]; + var w = a[3]; + var len = x * x + y * y + z * z + w * w; + if (len > 0) { + len = 1 / Math.sqrt(len); + out[0] = x * len; + out[1] = y * len; + out[2] = z * len; + out[3] = w * len; + } + return out; +} /** * Calculates the dot product of two vec4's @@ -1677,9 +2347,9 @@ vec4.normalize = function(out, a) { * @param {vec4} b the second operand * @returns {Number} dot product of a and b */ -vec4.dot = function (a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; -}; +function dot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +} /** * Performs a linear interpolation between two vec4's @@ -1690,17 +2360,17 @@ vec4.dot = function (a, b) { * @param {Number} t interpolation amount between the two inputs * @returns {vec4} out */ -vec4.lerp = function (out, a, b, t) { - var ax = a[0], - ay = a[1], - az = a[2], - aw = a[3]; - out[0] = ax + t * (b[0] - ax); - out[1] = ay + t * (b[1] - ay); - out[2] = az + t * (b[2] - az); - out[3] = aw + t * (b[3] - aw); - return out; -}; +function lerp(out, a, b, t) { + var ax = a[0]; + var ay = a[1]; + var az = a[2]; + var aw = a[3]; + out[0] = ax + t * (b[0] - ax); + out[1] = ay + t * (b[1] - ay); + out[2] = az + t * (b[2] - az); + out[3] = aw + t * (b[3] - aw); + return out; +} /** * Generates a random vector with the given scale @@ -1709,18 +2379,18 @@ vec4.lerp = function (out, a, b, t) { * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned * @returns {vec4} out */ -vec4.random = function (out, scale) { - scale = scale || 1.0; +function random(out, vectorScale) { + vectorScale = vectorScale || 1.0; - //TODO: This is a pretty awful way of doing this. Find something better. - out[0] = GLMAT_RANDOM(); - out[1] = GLMAT_RANDOM(); - out[2] = GLMAT_RANDOM(); - out[3] = GLMAT_RANDOM(); - vec4.normalize(out, out); - vec4.scale(out, out, scale); - return out; -}; + //TODO: This is a pretty awful way of doing this. Find something better. + out[0] = glMatrix.RANDOM(); + out[1] = glMatrix.RANDOM(); + out[2] = glMatrix.RANDOM(); + out[3] = glMatrix.RANDOM(); + normalize(out, out); + scale(out, out, vectorScale); + return out; +} /** * Transforms the vec4 with a mat4. @@ -1730,14 +2400,17 @@ vec4.random = function (out, scale) { * @param {mat4} m matrix to transform with * @returns {vec4} out */ -vec4.transformMat4 = function(out, a, m) { - var x = a[0], y = a[1], z = a[2], w = a[3]; - 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; - out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; - return out; -}; +function transformMat4(out, a, m) { + var x = a[0], + y = a[1], + z = a[2], + w = a[3]; + 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; + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; + return out; +} /** * Transforms the vec4 with a quat @@ -1747,22 +2420,110 @@ vec4.transformMat4 = function(out, a, m) { * @param {quat} q quaternion to transform with * @returns {vec4} out */ -vec4.transformQuat = function(out, a, q) { - var x = a[0], y = a[1], z = a[2], - qx = q[0], qy = q[1], qz = q[2], qw = q[3], +function transformQuat(out, a, q) { + var x = a[0], + y = a[1], + z = a[2]; + var 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 quat * vec + var ix = qw * x + qy * z - qz * y; + var iy = qw * y + qz * x - qx * z; + var iz = qw * z + qx * y - qy * x; + var 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; -}; + // 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; + out[3] = a[3]; + return out; +} + +/** + * Returns a string representation of a vector + * + * @param {vec4} a vector to represent as a string + * @returns {String} string representation of the vector + */ +function str(a) { + return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; +} + +/** + * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) + * + * @param {vec4} a The first vector. + * @param {vec4} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ +function exactEquals(a, b) { + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]; +} + +/** + * Returns whether or not the vectors have approximately the same elements in the same position. + * + * @param {vec4} a The first vector. + * @param {vec4} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ +function equals(a, b) { + var a0 = a[0], + a1 = a[1], + a2 = a[2], + a3 = a[3]; + var b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3]; + return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)); +} + +/** + * Alias for {@link vec4.subtract} + * @function + */ +var sub = exports.sub = subtract; + +/** + * Alias for {@link vec4.multiply} + * @function + */ +var mul = exports.mul = multiply; + +/** + * Alias for {@link vec4.divide} + * @function + */ +var div = exports.div = divide; + +/** + * Alias for {@link vec4.distance} + * @function + */ +var dist = exports.dist = distance; + +/** + * Alias for {@link vec4.squaredDistance} + * @function + */ +var sqrDist = exports.sqrDist = squaredDistance; + +/** + * Alias for {@link vec4.length} + * @function + */ +var len = exports.len = length; + +/** + * Alias for {@link vec4.squaredLength} + * @function + */ +var sqrLen = exports.sqrLen = squaredLength; /** * Perform some operation over an array of vec4s. @@ -1776,91 +2537,182 @@ vec4.transformQuat = function(out, a, q) { * @returns {Array} a * @function */ -vec4.forEach = (function() { - var vec = vec4.create(); +var forEach = exports.forEach = function () { + var vec = create(); - return function(a, stride, offset, count, fn, arg) { - var i, l; - if(!stride) { - stride = 4; - } + return function (a, stride, offset, count, fn, arg) { + var i = void 0, + l = void 0; + if (!stride) { + stride = 4; + } - if(!offset) { - offset = 0; - } - - if(count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } + if (!offset) { + offset = 0; + } - for(i = offset; i < l; i += stride) { - vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; - fn(vec, vec, arg); - a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; - } - - return a; - }; -})(); + 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];vec[3] = a[i + 3]; + fn(vec, vec, arg); + a[i] = vec[0];a[i + 1] = vec[1];a[i + 2] = vec[2];a[i + 3] = vec[3]; + } + + return a; + }; +}(); + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.vec4 = exports.vec3 = exports.vec2 = exports.quat = exports.mat4 = exports.mat3 = exports.mat2d = exports.mat2 = exports.glMatrix = undefined; + +var _common = __webpack_require__(0); + +var glMatrix = _interopRequireWildcard(_common); + +var _mat = __webpack_require__(5); + +var mat2 = _interopRequireWildcard(_mat); + +var _mat2d = __webpack_require__(6); + +var mat2d = _interopRequireWildcard(_mat2d); + +var _mat2 = __webpack_require__(1); + +var mat3 = _interopRequireWildcard(_mat2); + +var _mat3 = __webpack_require__(7); + +var mat4 = _interopRequireWildcard(_mat3); + +var _quat = __webpack_require__(8); + +var quat = _interopRequireWildcard(_quat); + +var _vec = __webpack_require__(9); + +var vec2 = _interopRequireWildcard(_vec); + +var _vec2 = __webpack_require__(2); + +var vec3 = _interopRequireWildcard(_vec2); + +var _vec3 = __webpack_require__(3); + +var vec4 = _interopRequireWildcard(_vec3); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +exports.glMatrix = glMatrix; +exports.mat2 = mat2; +exports.mat2d = mat2d; +exports.mat3 = mat3; +exports.mat4 = mat4; +exports.quat = quat; +exports.vec2 = vec2; +exports.vec3 = vec3; +exports.vec4 = vec4; /** + * @fileoverview gl-matrix - High performance matrix and vector operations + * @author Brandon Jones + * @author Colin MacKenzie IV + * @version 2.4.0 + */ + +/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +// END HEADER + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sub = exports.mul = undefined; +exports.create = create; +exports.clone = clone; +exports.copy = copy; +exports.identity = identity; +exports.fromValues = fromValues; +exports.set = set; +exports.transpose = transpose; +exports.invert = invert; +exports.adjoint = adjoint; +exports.determinant = determinant; +exports.multiply = multiply; +exports.rotate = rotate; +exports.scale = scale; +exports.fromRotation = fromRotation; +exports.fromScaling = fromScaling; +exports.str = str; +exports.frob = frob; +exports.LDU = LDU; +exports.add = add; +exports.subtract = subtract; +exports.exactEquals = exactEquals; +exports.equals = equals; +exports.multiplyScalar = multiplyScalar; +exports.multiplyScalarAndAdd = multiplyScalarAndAdd; + +var _common = __webpack_require__(0); + +var glMatrix = _interopRequireWildcard(_common); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } /** - * Returns a string representation of a vector - * - * @param {vec4} vec vector to represent as a string - * @returns {String} string representation of the vector + * 2x2 Matrix + * @module mat2 */ -vec4.str = function (a) { - return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; -}; - -if(typeof(exports) !== 'undefined') { - exports.vec4 = vec4; -} -; -/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/** - * @class 2x2 Matrix - * @name mat2 - */ - -var mat2 = {}; /** * Creates a new identity mat2 * * @returns {mat2} a new 2x2 matrix */ -mat2.create = function() { - var out = new GLMAT_ARRAY_TYPE(4); - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 1; - return out; -}; +function create() { + var out = new glMatrix.ARRAY_TYPE(4); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; +} /** * Creates a new mat2 initialized with values from an existing matrix @@ -1868,14 +2720,34 @@ mat2.create = function() { * @param {mat2} a matrix to clone * @returns {mat2} a new 2x2 matrix */ -mat2.clone = function(a) { - var out = new GLMAT_ARRAY_TYPE(4); - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - return out; -}; +/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ + +function clone(a) { + var out = new glMatrix.ARRAY_TYPE(4); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +} /** * Copy the values from one mat2 to another @@ -1884,13 +2756,13 @@ mat2.clone = function(a) { * @param {mat2} a the source matrix * @returns {mat2} out */ -mat2.copy = function(out, a) { - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - return out; -}; +function copy(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; +} /** * Set a mat2 to the identity matrix @@ -1898,13 +2770,49 @@ mat2.copy = function(out, a) { * @param {mat2} out the receiving matrix * @returns {mat2} out */ -mat2.identity = function(out) { - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 1; - return out; -}; +function identity(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + return out; +} + +/** + * Create a new mat2 with the given values + * + * @param {Number} m00 Component in column 0, row 0 position (index 0) + * @param {Number} m01 Component in column 0, row 1 position (index 1) + * @param {Number} m10 Component in column 1, row 0 position (index 2) + * @param {Number} m11 Component in column 1, row 1 position (index 3) + * @returns {mat2} out A new 2x2 matrix + */ +function fromValues(m00, m01, m10, m11) { + var out = new glMatrix.ARRAY_TYPE(4); + out[0] = m00; + out[1] = m01; + out[2] = m10; + out[3] = m11; + return out; +} + +/** + * Set the components of a mat2 to the given values + * + * @param {mat2} out the receiving matrix + * @param {Number} m00 Component in column 0, row 0 position (index 0) + * @param {Number} m01 Component in column 0, row 1 position (index 1) + * @param {Number} m10 Component in column 1, row 0 position (index 2) + * @param {Number} m11 Component in column 1, row 1 position (index 3) + * @returns {mat2} out + */ +function set(out, m00, m01, m10, m11) { + out[0] = m00; + out[1] = m01; + out[2] = m10; + out[3] = m11; + return out; +} /** * Transpose the values of a mat2 @@ -1913,21 +2821,22 @@ mat2.identity = function(out) { * @param {mat2} a the source matrix * @returns {mat2} out */ -mat2.transpose = function(out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a1 = a[1]; - out[1] = a[2]; - out[2] = a1; - } else { - out[0] = a[0]; - out[1] = a[2]; - out[2] = a[1]; - out[3] = a[3]; - } - - return 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 a1 = a[1]; + out[1] = a[2]; + out[2] = a1; + } else { + out[0] = a[0]; + out[1] = a[2]; + out[2] = a[1]; + out[3] = a[3]; + } + + return out; +} /** * Inverts a mat2 @@ -1936,24 +2845,27 @@ mat2.transpose = function(out, a) { * @param {mat2} a the source matrix * @returns {mat2} out */ -mat2.invert = function(out, a) { - var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], +function invert(out, a) { + var a0 = a[0], + a1 = a[1], + a2 = a[2], + a3 = a[3]; - // Calculate the determinant - det = a0 * a3 - a2 * a1; + // Calculate the determinant + var det = a0 * a3 - a2 * a1; - if (!det) { - return null; - } - det = 1.0 / det; - - out[0] = a3 * det; - out[1] = -a1 * det; - out[2] = -a2 * det; - out[3] = a0 * det; + if (!det) { + return null; + } + det = 1.0 / det; - return out; -}; + out[0] = a3 * det; + out[1] = -a1 * det; + out[2] = -a2 * det; + out[3] = a0 * det; + + return out; +} /** * Calculates the adjugate of a mat2 @@ -1962,16 +2874,16 @@ mat2.invert = function(out, a) { * @param {mat2} a the source matrix * @returns {mat2} out */ -mat2.adjoint = function(out, a) { - // Caching this value is nessecary if out == a - var a0 = a[0]; - out[0] = a[3]; - out[1] = -a[1]; - out[2] = -a[2]; - out[3] = a0; +function adjoint(out, a) { + // Caching this value is nessecary if out == a + var a0 = a[0]; + out[0] = a[3]; + out[1] = -a[1]; + out[2] = -a[2]; + out[3] = a0; - return out; -}; + return out; +} /** * Calculates the determinant of a mat2 @@ -1979,9 +2891,9 @@ mat2.adjoint = function(out, a) { * @param {mat2} a the source matrix * @returns {Number} determinant of a */ -mat2.determinant = function (a) { - return a[0] * a[3] - a[2] * a[1]; -}; +function determinant(a) { + return a[0] * a[3] - a[2] * a[1]; +} /** * Multiplies two mat2's @@ -1991,21 +2903,21 @@ mat2.determinant = function (a) { * @param {mat2} b the second operand * @returns {mat2} out */ -mat2.multiply = function (out, a, b) { - var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; - var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; - out[0] = a0 * b0 + a2 * b1; - out[1] = a1 * b0 + a3 * b1; - out[2] = a0 * b2 + a2 * b3; - out[3] = a1 * b2 + a3 * b3; - return out; -}; - -/** - * Alias for {@link mat2.multiply} - * @function - */ -mat2.mul = mat2.multiply; +function multiply(out, a, b) { + var a0 = a[0], + a1 = a[1], + a2 = a[2], + a3 = a[3]; + var b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3]; + out[0] = a0 * b0 + a2 * b1; + out[1] = a1 * b0 + a3 * b1; + out[2] = a0 * b2 + a2 * b3; + out[3] = a1 * b2 + a3 * b3; + return out; +} /** * Rotates a mat2 by the given angle @@ -2015,16 +2927,19 @@ mat2.mul = mat2.multiply; * @param {Number} rad the angle to rotate the matrix by * @returns {mat2} out */ -mat2.rotate = function (out, a, rad) { - var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], - s = Math.sin(rad), - c = Math.cos(rad); - out[0] = a0 * c + a2 * s; - out[1] = a1 * c + a3 * s; - out[2] = a0 * -s + a2 * c; - out[3] = a1 * -s + a3 * c; - return out; -}; +function rotate(out, a, rad) { + var a0 = a[0], + a1 = a[1], + a2 = a[2], + a3 = a[3]; + var s = Math.sin(rad); + var c = Math.cos(rad); + out[0] = a0 * c + a2 * s; + out[1] = a1 * c + a3 * s; + out[2] = a0 * -s + a2 * c; + out[3] = a1 * -s + a3 * c; + return out; +} /** * Scales the mat2 by the dimensions in the given vec2 @@ -2034,25 +2949,69 @@ mat2.rotate = function (out, a, rad) { * @param {vec2} v the vec2 to scale the matrix by * @returns {mat2} out **/ -mat2.scale = function(out, a, v) { - var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], - v0 = v[0], v1 = v[1]; - out[0] = a0 * v0; - out[1] = a1 * v0; - out[2] = a2 * v1; - out[3] = a3 * v1; - return out; -}; +function scale(out, a, v) { + var a0 = a[0], + a1 = a[1], + a2 = a[2], + a3 = a[3]; + var v0 = v[0], + v1 = v[1]; + out[0] = a0 * v0; + out[1] = a1 * v0; + out[2] = a2 * v1; + out[3] = a3 * v1; + return out; +} + +/** + * Creates a matrix from a given angle + * This is equivalent to (but much faster than): + * + * mat2.identity(dest); + * mat2.rotate(dest, dest, rad); + * + * @param {mat2} out mat2 receiving operation result + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat2} out + */ +function fromRotation(out, rad) { + var s = Math.sin(rad); + var c = Math.cos(rad); + out[0] = c; + out[1] = s; + out[2] = -s; + out[3] = c; + return out; +} + +/** + * Creates a matrix from a vector scaling + * This is equivalent to (but much faster than): + * + * mat2.identity(dest); + * mat2.scale(dest, dest, vec); + * + * @param {mat2} out mat2 receiving operation result + * @param {vec2} v Scaling vector + * @returns {mat2} out + */ +function fromScaling(out, v) { + out[0] = v[0]; + out[1] = 0; + out[2] = 0; + out[3] = v[1]; + return out; +} /** * Returns a string representation of a mat2 * - * @param {mat2} mat matrix to represent as a string + * @param {mat2} a matrix to represent as a string * @returns {String} string representation of the matrix */ -mat2.str = function (a) { - return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; -}; +function str(a) { + return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; +} /** * Returns Frobenius norm of a mat2 @@ -2060,57 +3019,179 @@ mat2.str = function (a) { * @param {mat2} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ -mat2.frob = function (a) { - return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2))) -}; +function frob(a) { + return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)); +} /** * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix - * @param {mat2} L the lower triangular matrix - * @param {mat2} D the diagonal matrix - * @param {mat2} U the upper triangular matrix + * @param {mat2} L the lower triangular matrix + * @param {mat2} D the diagonal matrix + * @param {mat2} U the upper triangular matrix * @param {mat2} a the input matrix to factorize */ -mat2.LDU = function (L, D, U, a) { - L[2] = a[2]/a[0]; - U[0] = a[0]; - U[1] = a[1]; - U[3] = a[3] - L[2] * U[1]; - return [L, D, U]; -}; - -if(typeof(exports) !== 'undefined') { - exports.mat2 = mat2; +function LDU(L, D, U, a) { + L[2] = a[2] / a[0]; + U[0] = a[0]; + U[1] = a[1]; + U[3] = a[3] - L[2] * U[1]; + return [L, D, U]; } -; -/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * @class 2x3 Matrix - * @name mat2d - * - * @description + * Adds two mat2's + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the first operand + * @param {mat2} b the second operand + * @returns {mat2} out + */ +function add(out, a, b) { + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; + return out; +} + +/** + * Subtracts matrix b from matrix a + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the first operand + * @param {mat2} b the second operand + * @returns {mat2} out + */ +function subtract(out, a, b) { + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + out[3] = a[3] - b[3]; + return out; +} + +/** + * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) + * + * @param {mat2} a The first matrix. + * @param {mat2} b The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ +function exactEquals(a, b) { + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]; +} + +/** + * Returns whether or not the matrices have approximately the same elements in the same position. + * + * @param {mat2} a The first matrix. + * @param {mat2} b The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ +function equals(a, b) { + var a0 = a[0], + a1 = a[1], + a2 = a[2], + a3 = a[3]; + var b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3]; + return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)); +} + +/** + * Multiply each element of the matrix by a scalar. + * + * @param {mat2} out the receiving matrix + * @param {mat2} a the matrix to scale + * @param {Number} b amount to scale the matrix's elements by + * @returns {mat2} out + */ +function multiplyScalar(out, a, b) { + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + out[3] = a[3] * b; + return out; +} + +/** + * Adds two mat2's after multiplying each element of the second operand by a scalar value. + * + * @param {mat2} out the receiving vector + * @param {mat2} a the first operand + * @param {mat2} b the second operand + * @param {Number} scale the amount to scale b's elements by before adding + * @returns {mat2} out + */ +function multiplyScalarAndAdd(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; + out[3] = a[3] + b[3] * scale; + return out; +} + +/** + * Alias for {@link mat2.multiply} + * @function + */ +var mul = exports.mul = multiply; + +/** + * Alias for {@link mat2.subtract} + * @function + */ +var sub = exports.sub = subtract; + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sub = exports.mul = undefined; +exports.create = create; +exports.clone = clone; +exports.copy = copy; +exports.identity = identity; +exports.fromValues = fromValues; +exports.set = set; +exports.invert = invert; +exports.determinant = determinant; +exports.multiply = multiply; +exports.rotate = rotate; +exports.scale = scale; +exports.translate = translate; +exports.fromRotation = fromRotation; +exports.fromScaling = fromScaling; +exports.fromTranslation = fromTranslation; +exports.str = str; +exports.frob = frob; +exports.add = add; +exports.subtract = subtract; +exports.multiplyScalar = multiplyScalar; +exports.multiplyScalarAndAdd = multiplyScalarAndAdd; +exports.exactEquals = exactEquals; +exports.equals = equals; + +var _common = __webpack_require__(0); + +var glMatrix = _interopRequireWildcard(_common); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +/** + * 2x3 Matrix + * @module mat2d + * + * @description * A mat2d contains six elements defined as: *
  * [a, c, tx,
@@ -2125,23 +3206,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
  * The last row is ignored so the array is shorter and operations are faster.
  */
 
-var mat2d = {};
-
 /**
  * Creates a new identity mat2d
  *
  * @returns {mat2d} a new 2x3 matrix
  */
-mat2d.create = function() {
-    var out = new GLMAT_ARRAY_TYPE(6);
-    out[0] = 1;
-    out[1] = 0;
-    out[2] = 0;
-    out[3] = 1;
-    out[4] = 0;
-    out[5] = 0;
-    return out;
-};
+function create() {
+  var out = new glMatrix.ARRAY_TYPE(6);
+  out[0] = 1;
+  out[1] = 0;
+  out[2] = 0;
+  out[3] = 1;
+  out[4] = 0;
+  out[5] = 0;
+  return out;
+}
 
 /**
  * Creates a new mat2d initialized with values from an existing matrix
@@ -2149,16 +3228,36 @@ mat2d.create = function() {
  * @param {mat2d} a matrix to clone
  * @returns {mat2d} a new 2x3 matrix
  */
-mat2d.clone = function(a) {
-    var out = new GLMAT_ARRAY_TYPE(6);
-    out[0] = a[0];
-    out[1] = a[1];
-    out[2] = a[2];
-    out[3] = a[3];
-    out[4] = a[4];
-    out[5] = a[5];
-    return out;
-};
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+function clone(a) {
+  var out = new glMatrix.ARRAY_TYPE(6);
+  out[0] = a[0];
+  out[1] = a[1];
+  out[2] = a[2];
+  out[3] = a[3];
+  out[4] = a[4];
+  out[5] = a[5];
+  return out;
+}
 
 /**
  * Copy the values from one mat2d to another
@@ -2167,15 +3266,15 @@ mat2d.clone = function(a) {
  * @param {mat2d} a the source matrix
  * @returns {mat2d} out
  */
-mat2d.copy = function(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];
-    return 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];
+  return out;
+}
 
 /**
  * Set a mat2d to the identity matrix
@@ -2183,15 +3282,59 @@ mat2d.copy = function(out, a) {
  * @param {mat2d} out the receiving matrix
  * @returns {mat2d} out
  */
-mat2d.identity = function(out) {
-    out[0] = 1;
-    out[1] = 0;
-    out[2] = 0;
-    out[3] = 1;
-    out[4] = 0;
-    out[5] = 0;
-    return out;
-};
+function identity(out) {
+  out[0] = 1;
+  out[1] = 0;
+  out[2] = 0;
+  out[3] = 1;
+  out[4] = 0;
+  out[5] = 0;
+  return out;
+}
+
+/**
+ * Create a new mat2d with the given values
+ *
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} A new mat2d
+ */
+function fromValues(a, b, c, d, tx, ty) {
+  var out = new glMatrix.ARRAY_TYPE(6);
+  out[0] = a;
+  out[1] = b;
+  out[2] = c;
+  out[3] = d;
+  out[4] = tx;
+  out[5] = ty;
+  return out;
+}
+
+/**
+ * Set the components of a mat2d to the given values
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} out
+ */
+function set(out, a, b, c, d, tx, ty) {
+  out[0] = a;
+  out[1] = b;
+  out[2] = c;
+  out[3] = d;
+  out[4] = tx;
+  out[5] = ty;
+  return out;
+}
 
 /**
  * Inverts a mat2d
@@ -2200,24 +3343,28 @@ mat2d.identity = function(out) {
  * @param {mat2d} a the source matrix
  * @returns {mat2d} out
  */
-mat2d.invert = function(out, a) {
-    var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
-        atx = a[4], aty = a[5];
+function invert(out, a) {
+  var aa = a[0],
+      ab = a[1],
+      ac = a[2],
+      ad = a[3];
+  var atx = a[4],
+      aty = a[5];
 
-    var det = aa * ad - ab * ac;
-    if(!det){
-        return null;
-    }
-    det = 1.0 / det;
+  var det = aa * ad - ab * ac;
+  if (!det) {
+    return null;
+  }
+  det = 1.0 / det;
 
-    out[0] = ad * det;
-    out[1] = -ab * det;
-    out[2] = -ac * det;
-    out[3] = aa * det;
-    out[4] = (ac * aty - ad * atx) * det;
-    out[5] = (ab * atx - aa * aty) * det;
-    return out;
-};
+  out[0] = ad * det;
+  out[1] = -ab * det;
+  out[2] = -ac * det;
+  out[3] = aa * det;
+  out[4] = (ac * aty - ad * atx) * det;
+  out[5] = (ab * atx - aa * aty) * det;
+  return out;
+}
 
 /**
  * Calculates the determinant of a mat2d
@@ -2225,9 +3372,9 @@ mat2d.invert = function(out, a) {
  * @param {mat2d} a the source matrix
  * @returns {Number} determinant of a
  */
-mat2d.determinant = function (a) {
-    return a[0] * a[3] - a[1] * a[2];
-};
+function determinant(a) {
+  return a[0] * a[3] - a[1] * a[2];
+}
 
 /**
  * Multiplies two mat2d's
@@ -2237,24 +3384,27 @@ mat2d.determinant = function (a) {
  * @param {mat2d} b the second operand
  * @returns {mat2d} out
  */
-mat2d.multiply = function (out, a, b) {
-    var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
-        b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
-    out[0] = a0 * b0 + a2 * b1;
-    out[1] = a1 * b0 + a3 * b1;
-    out[2] = a0 * b2 + a2 * b3;
-    out[3] = a1 * b2 + a3 * b3;
-    out[4] = a0 * b4 + a2 * b5 + a4;
-    out[5] = a1 * b4 + a3 * b5 + a5;
-    return out;
-};
-
-/**
- * Alias for {@link mat2d.multiply}
- * @function
- */
-mat2d.mul = mat2d.multiply;
-
+function multiply(out, a, b) {
+  var a0 = a[0],
+      a1 = a[1],
+      a2 = a[2],
+      a3 = a[3],
+      a4 = a[4],
+      a5 = a[5];
+  var b0 = b[0],
+      b1 = b[1],
+      b2 = b[2],
+      b3 = b[3],
+      b4 = b[4],
+      b5 = b[5];
+  out[0] = a0 * b0 + a2 * b1;
+  out[1] = a1 * b0 + a3 * b1;
+  out[2] = a0 * b2 + a2 * b3;
+  out[3] = a1 * b2 + a3 * b3;
+  out[4] = a0 * b4 + a2 * b5 + a4;
+  out[5] = a1 * b4 + a3 * b5 + a5;
+  return out;
+}
 
 /**
  * Rotates a mat2d by the given angle
@@ -2264,18 +3414,23 @@ mat2d.mul = mat2d.multiply;
  * @param {Number} rad the angle to rotate the matrix by
  * @returns {mat2d} out
  */
-mat2d.rotate = function (out, a, rad) {
-    var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
-        s = Math.sin(rad),
-        c = Math.cos(rad);
-    out[0] = a0 *  c + a2 * s;
-    out[1] = a1 *  c + a3 * s;
-    out[2] = a0 * -s + a2 * c;
-    out[3] = a1 * -s + a3 * c;
-    out[4] = a4;
-    out[5] = a5;
-    return out;
-};
+function rotate(out, a, rad) {
+  var a0 = a[0],
+      a1 = a[1],
+      a2 = a[2],
+      a3 = a[3],
+      a4 = a[4],
+      a5 = a[5];
+  var s = Math.sin(rad);
+  var c = Math.cos(rad);
+  out[0] = a0 * c + a2 * s;
+  out[1] = a1 * c + a3 * s;
+  out[2] = a0 * -s + a2 * c;
+  out[3] = a1 * -s + a3 * c;
+  out[4] = a4;
+  out[5] = a5;
+  return out;
+}
 
 /**
  * Scales the mat2d by the dimensions in the given vec2
@@ -2285,17 +3440,23 @@ mat2d.rotate = function (out, a, rad) {
  * @param {vec2} v the vec2 to scale the matrix by
  * @returns {mat2d} out
  **/
-mat2d.scale = function(out, a, v) {
-    var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
-        v0 = v[0], v1 = v[1];
-    out[0] = a0 * v0;
-    out[1] = a1 * v0;
-    out[2] = a2 * v1;
-    out[3] = a3 * v1;
-    out[4] = a4;
-    out[5] = a5;
-    return out;
-};
+function scale(out, a, v) {
+  var a0 = a[0],
+      a1 = a[1],
+      a2 = a[2],
+      a3 = a[3],
+      a4 = a[4],
+      a5 = a[5];
+  var v0 = v[0],
+      v1 = v[1];
+  out[0] = a0 * v0;
+  out[1] = a1 * v0;
+  out[2] = a2 * v1;
+  out[3] = a3 * v1;
+  out[4] = a4;
+  out[5] = a5;
+  return out;
+}
 
 /**
  * Translates the mat2d by the dimensions in the given vec2
@@ -2305,17 +3466,88 @@ mat2d.scale = function(out, a, v) {
  * @param {vec2} v the vec2 to translate the matrix by
  * @returns {mat2d} out
  **/
-mat2d.translate = function(out, a, v) {
-    var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
-        v0 = v[0], v1 = v[1];
-    out[0] = a0;
-    out[1] = a1;
-    out[2] = a2;
-    out[3] = a3;
-    out[4] = a0 * v0 + a2 * v1 + a4;
-    out[5] = a1 * v0 + a3 * v1 + a5;
-    return out;
-};
+function translate(out, a, v) {
+  var a0 = a[0],
+      a1 = a[1],
+      a2 = a[2],
+      a3 = a[3],
+      a4 = a[4],
+      a5 = a[5];
+  var v0 = v[0],
+      v1 = v[1];
+  out[0] = a0;
+  out[1] = a1;
+  out[2] = a2;
+  out[3] = a3;
+  out[4] = a0 * v0 + a2 * v1 + a4;
+  out[5] = a1 * v0 + a3 * v1 + a5;
+  return out;
+}
+
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ *     mat2d.identity(dest);
+ *     mat2d.rotate(dest, dest, rad);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+function fromRotation(out, rad) {
+  var s = Math.sin(rad),
+      c = Math.cos(rad);
+  out[0] = c;
+  out[1] = s;
+  out[2] = -s;
+  out[3] = c;
+  out[4] = 0;
+  out[5] = 0;
+  return out;
+}
+
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ *     mat2d.identity(dest);
+ *     mat2d.scale(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {vec2} v Scaling vector
+ * @returns {mat2d} out
+ */
+function fromScaling(out, v) {
+  out[0] = v[0];
+  out[1] = 0;
+  out[2] = 0;
+  out[3] = v[1];
+  out[4] = 0;
+  out[5] = 0;
+  return out;
+}
+
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ *     mat2d.identity(dest);
+ *     mat2d.translate(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {vec2} v Translation vector
+ * @returns {mat2d} out
+ */
+function fromTranslation(out, v) {
+  out[0] = 1;
+  out[1] = 0;
+  out[2] = 0;
+  out[3] = 1;
+  out[4] = v[0];
+  out[5] = v[1];
+  return out;
+}
 
 /**
  * Returns a string representation of a mat2d
@@ -2323,10 +3555,9 @@ mat2d.translate = function(out, a, v) {
  * @param {mat2d} a matrix to represent as a string
  * @returns {String} string representation of the matrix
  */
-mat2d.str = function (a) {
-    return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + 
-                    a[3] + ', ' + a[4] + ', ' + a[5] + ')';
-};
+function str(a) {
+  return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ')';
+}
 
 /**
  * Returns Frobenius norm of a mat2d
@@ -2334,559 +3565,221 @@ mat2d.str = function (a) {
  * @param {mat2d} a the matrix to calculate Frobenius norm of
  * @returns {Number} Frobenius norm
  */
-mat2d.frob = function (a) { 
-    return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1))
-}; 
-
-if(typeof(exports) !== 'undefined') {
-    exports.mat2d = mat2d;
+function frob(a) {
+  return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1);
 }
-;
-/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-  * Redistributions of source code must retain the above copyright notice, this
-    list of conditions and the following disclaimer.
-  * Redistributions in binary form must reproduce the above copyright notice,
-    this list of conditions and the following disclaimer in the documentation 
-    and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 
 /**
- * @class 3x3 Matrix
- * @name mat3
- */
-
-var mat3 = {};
-
-/**
- * Creates a new identity mat3
+ * Adds two mat2d's
  *
- * @returns {mat3} a new 3x3 matrix
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the first operand
+ * @param {mat2d} b the second operand
+ * @returns {mat2d} out
  */
-mat3.create = function() {
-    var out = new GLMAT_ARRAY_TYPE(9);
-    out[0] = 1;
-    out[1] = 0;
-    out[2] = 0;
-    out[3] = 0;
-    out[4] = 1;
-    out[5] = 0;
-    out[6] = 0;
-    out[7] = 0;
-    out[8] = 1;
-    return out;
-};
+function add(out, a, b) {
+  out[0] = a[0] + b[0];
+  out[1] = a[1] + b[1];
+  out[2] = a[2] + b[2];
+  out[3] = a[3] + b[3];
+  out[4] = a[4] + b[4];
+  out[5] = a[5] + b[5];
+  return out;
+}
 
 /**
- * Copies the upper-left 3x3 values into the given mat3.
+ * Subtracts matrix b from matrix a
  *
- * @param {mat3} out the receiving 3x3 matrix
- * @param {mat4} a   the source 4x4 matrix
- * @returns {mat3} out
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the first operand
+ * @param {mat2d} b the second operand
+ * @returns {mat2d} out
  */
-mat3.fromMat4 = function(out, a) {
-    out[0] = a[0];
-    out[1] = a[1];
-    out[2] = a[2];
-    out[3] = a[4];
-    out[4] = a[5];
-    out[5] = a[6];
-    out[6] = a[8];
-    out[7] = a[9];
-    out[8] = a[10];
-    return out;
-};
+function subtract(out, a, b) {
+  out[0] = a[0] - b[0];
+  out[1] = a[1] - b[1];
+  out[2] = a[2] - b[2];
+  out[3] = a[3] - b[3];
+  out[4] = a[4] - b[4];
+  out[5] = a[5] - b[5];
+  return out;
+}
 
 /**
- * Creates a new mat3 initialized with values from an existing matrix
+ * Multiply each element of the matrix by a scalar.
  *
- * @param {mat3} a matrix to clone
- * @returns {mat3} a new 3x3 matrix
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2d} out
  */
-mat3.clone = function(a) {
-    var out = new GLMAT_ARRAY_TYPE(9);
-    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];
-    return out;
-};
+function multiplyScalar(out, a, b) {
+  out[0] = a[0] * b;
+  out[1] = a[1] * b;
+  out[2] = a[2] * b;
+  out[3] = a[3] * b;
+  out[4] = a[4] * b;
+  out[5] = a[5] * b;
+  return out;
+}
 
 /**
- * Copy the values from one mat3 to another
+ * Adds two mat2d's after multiplying each element of the second operand by a scalar value.
  *
- * @param {mat3} out the receiving matrix
- * @param {mat3} a the source matrix
- * @returns {mat3} out
+ * @param {mat2d} out the receiving vector
+ * @param {mat2d} a the first operand
+ * @param {mat2d} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2d} out
  */
-mat3.copy = function(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];
-    return out;
-};
+function multiplyScalarAndAdd(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;
+  out[3] = a[3] + b[3] * scale;
+  out[4] = a[4] + b[4] * scale;
+  out[5] = a[5] + b[5] * scale;
+  return out;
+}
 
 /**
- * Set a mat3 to the identity matrix
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
  *
- * @param {mat3} out the receiving matrix
- * @returns {mat3} out
+ * @param {mat2d} a The first matrix.
+ * @param {mat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
  */
-mat3.identity = function(out) {
-    out[0] = 1;
-    out[1] = 0;
-    out[2] = 0;
-    out[3] = 0;
-    out[4] = 1;
-    out[5] = 0;
-    out[6] = 0;
-    out[7] = 0;
-    out[8] = 1;
-    return out;
-};
+function exactEquals(a, b) {
+  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5];
+}
 
 /**
- * Transpose the values of a mat3
+ * Returns whether or not the matrices have approximately the same elements in the same position.
  *
- * @param {mat3} out the receiving matrix
- * @param {mat3} a the source matrix
- * @returns {mat3} out
+ * @param {mat2d} a The first matrix.
+ * @param {mat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
  */
-mat3.transpose = function(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], a12 = a[5];
-        out[1] = a[3];
-        out[2] = a[6];
-        out[3] = a01;
-        out[5] = a[7];
-        out[6] = a02;
-        out[7] = a12;
-    } else {
-        out[0] = a[0];
-        out[1] = a[3];
-        out[2] = a[6];
-        out[3] = a[1];
-        out[4] = a[4];
-        out[5] = a[7];
-        out[6] = a[2];
-        out[7] = a[5];
-        out[8] = a[8];
-    }
-    
-    return out;
-};
+function equals(a, b) {
+  var a0 = a[0],
+      a1 = a[1],
+      a2 = a[2],
+      a3 = a[3],
+      a4 = a[4],
+      a5 = a[5];
+  var b0 = b[0],
+      b1 = b[1],
+      b2 = b[2],
+      b3 = b[3],
+      b4 = b[4],
+      b5 = b[5];
+  return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5));
+}
 
 /**
- * Inverts a mat3
- *
- * @param {mat3} out the receiving matrix
- * @param {mat3} a the source matrix
- * @returns {mat3} out
- */
-mat3.invert = function(out, a) {
-    var a00 = a[0], a01 = a[1], a02 = a[2],
-        a10 = a[3], a11 = a[4], a12 = a[5],
-        a20 = a[6], a21 = a[7], a22 = a[8],
-
-        b01 = a22 * a11 - a12 * a21,
-        b11 = -a22 * a10 + a12 * a20,
-        b21 = a21 * a10 - a11 * a20,
-
-        // Calculate the determinant
-        det = a00 * b01 + a01 * b11 + a02 * b21;
-
-    if (!det) { 
-        return null; 
-    }
-    det = 1.0 / det;
-
-    out[0] = b01 * det;
-    out[1] = (-a22 * a01 + a02 * a21) * det;
-    out[2] = (a12 * a01 - a02 * a11) * det;
-    out[3] = b11 * det;
-    out[4] = (a22 * a00 - a02 * a20) * det;
-    out[5] = (-a12 * a00 + a02 * a10) * det;
-    out[6] = b21 * det;
-    out[7] = (-a21 * a00 + a01 * a20) * det;
-    out[8] = (a11 * a00 - a01 * a10) * det;
-    return out;
-};
-
-/**
- * Calculates the adjugate of a mat3
- *
- * @param {mat3} out the receiving matrix
- * @param {mat3} a the source matrix
- * @returns {mat3} out
- */
-mat3.adjoint = function(out, a) {
-    var a00 = a[0], a01 = a[1], a02 = a[2],
-        a10 = a[3], a11 = a[4], a12 = a[5],
-        a20 = a[6], a21 = a[7], a22 = a[8];
-
-    out[0] = (a11 * a22 - a12 * a21);
-    out[1] = (a02 * a21 - a01 * a22);
-    out[2] = (a01 * a12 - a02 * a11);
-    out[3] = (a12 * a20 - a10 * a22);
-    out[4] = (a00 * a22 - a02 * a20);
-    out[5] = (a02 * a10 - a00 * a12);
-    out[6] = (a10 * a21 - a11 * a20);
-    out[7] = (a01 * a20 - a00 * a21);
-    out[8] = (a00 * a11 - a01 * a10);
-    return out;
-};
-
-/**
- * Calculates the determinant of a mat3
- *
- * @param {mat3} a the source matrix
- * @returns {Number} determinant of a
- */
-mat3.determinant = function (a) {
-    var a00 = a[0], a01 = a[1], a02 = a[2],
-        a10 = a[3], a11 = a[4], a12 = a[5],
-        a20 = a[6], a21 = a[7], a22 = a[8];
-
-    return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
-};
-
-/**
- * Multiplies two mat3's
- *
- * @param {mat3} out the receiving matrix
- * @param {mat3} a the first operand
- * @param {mat3} b the second operand
- * @returns {mat3} out
- */
-mat3.multiply = function (out, a, b) {
-    var a00 = a[0], a01 = a[1], a02 = a[2],
-        a10 = a[3], a11 = a[4], a12 = a[5],
-        a20 = a[6], a21 = a[7], a22 = a[8],
-
-        b00 = b[0], b01 = b[1], b02 = b[2],
-        b10 = b[3], b11 = b[4], b12 = b[5],
-        b20 = b[6], b21 = b[7], b22 = b[8];
-
-    out[0] = b00 * a00 + b01 * a10 + b02 * a20;
-    out[1] = b00 * a01 + b01 * a11 + b02 * a21;
-    out[2] = b00 * a02 + b01 * a12 + b02 * a22;
-
-    out[3] = b10 * a00 + b11 * a10 + b12 * a20;
-    out[4] = b10 * a01 + b11 * a11 + b12 * a21;
-    out[5] = b10 * a02 + b11 * a12 + b12 * a22;
-
-    out[6] = b20 * a00 + b21 * a10 + b22 * a20;
-    out[7] = b20 * a01 + b21 * a11 + b22 * a21;
-    out[8] = b20 * a02 + b21 * a12 + b22 * a22;
-    return out;
-};
-
-/**
- * Alias for {@link mat3.multiply}
+ * Alias for {@link mat2d.multiply}
  * @function
  */
-mat3.mul = mat3.multiply;
+var mul = exports.mul = multiply;
 
 /**
- * Translate a mat3 by the given vector
- *
- * @param {mat3} out the receiving matrix
- * @param {mat3} a the matrix to translate
- * @param {vec2} v vector to translate by
- * @returns {mat3} out
+ * Alias for {@link mat2d.subtract}
+ * @function
  */
-mat3.translate = function(out, a, v) {
-    var a00 = a[0], a01 = a[1], a02 = a[2],
-        a10 = a[3], a11 = a[4], a12 = a[5],
-        a20 = a[6], a21 = a[7], a22 = a[8],
-        x = v[0], y = v[1];
+var sub = exports.sub = subtract;
 
-    out[0] = a00;
-    out[1] = a01;
-    out[2] = a02;
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
 
-    out[3] = a10;
-    out[4] = a11;
-    out[5] = a12;
+"use strict";
 
-    out[6] = x * a00 + y * a10 + a20;
-    out[7] = x * a01 + y * a11 + a21;
-    out[8] = x * a02 + y * a12 + a22;
-    return out;
-};
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.sub = exports.mul = undefined;
+exports.create = create;
+exports.clone = clone;
+exports.copy = copy;
+exports.fromValues = fromValues;
+exports.set = set;
+exports.identity = identity;
+exports.transpose = transpose;
+exports.invert = invert;
+exports.adjoint = adjoint;
+exports.determinant = determinant;
+exports.multiply = multiply;
+exports.translate = translate;
+exports.scale = scale;
+exports.rotate = rotate;
+exports.rotateX = rotateX;
+exports.rotateY = rotateY;
+exports.rotateZ = rotateZ;
+exports.fromTranslation = fromTranslation;
+exports.fromScaling = fromScaling;
+exports.fromRotation = fromRotation;
+exports.fromXRotation = fromXRotation;
+exports.fromYRotation = fromYRotation;
+exports.fromZRotation = fromZRotation;
+exports.fromRotationTranslation = fromRotationTranslation;
+exports.getTranslation = getTranslation;
+exports.getScaling = getScaling;
+exports.getRotation = getRotation;
+exports.fromRotationTranslationScale = fromRotationTranslationScale;
+exports.fromRotationTranslationScaleOrigin = fromRotationTranslationScaleOrigin;
+exports.fromQuat = fromQuat;
+exports.frustum = frustum;
+exports.perspective = perspective;
+exports.perspectiveFromFieldOfView = perspectiveFromFieldOfView;
+exports.ortho = ortho;
+exports.lookAt = lookAt;
+exports.targetTo = targetTo;
+exports.str = str;
+exports.frob = frob;
+exports.add = add;
+exports.subtract = subtract;
+exports.multiplyScalar = multiplyScalar;
+exports.multiplyScalarAndAdd = multiplyScalarAndAdd;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+
+var _common = __webpack_require__(0);
+
+var glMatrix = _interopRequireWildcard(_common);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
 
 /**
- * Rotates a mat3 by the given angle
- *
- * @param {mat3} out the receiving matrix
- * @param {mat3} a the matrix to rotate
- * @param {Number} rad the angle to rotate the matrix by
- * @returns {mat3} out
+ * 4x4 Matrix
+ * @module mat4
  */
-mat3.rotate = function (out, a, rad) {
-    var a00 = a[0], a01 = a[1], a02 = a[2],
-        a10 = a[3], a11 = a[4], a12 = a[5],
-        a20 = a[6], a21 = a[7], a22 = a[8],
-
-        s = Math.sin(rad),
-        c = Math.cos(rad);
-
-    out[0] = c * a00 + s * a10;
-    out[1] = c * a01 + s * a11;
-    out[2] = c * a02 + s * a12;
-
-    out[3] = c * a10 - s * a00;
-    out[4] = c * a11 - s * a01;
-    out[5] = c * a12 - s * a02;
-
-    out[6] = a20;
-    out[7] = a21;
-    out[8] = a22;
-    return out;
-};
-
-/**
- * Scales the mat3 by the dimensions in the given vec2
- *
- * @param {mat3} out the receiving matrix
- * @param {mat3} a the matrix to rotate
- * @param {vec2} v the vec2 to scale the matrix by
- * @returns {mat3} out
- **/
-mat3.scale = function(out, a, v) {
-    var x = v[0], y = v[1];
-
-    out[0] = x * a[0];
-    out[1] = x * a[1];
-    out[2] = x * a[2];
-
-    out[3] = y * a[3];
-    out[4] = y * a[4];
-    out[5] = y * a[5];
-
-    out[6] = a[6];
-    out[7] = a[7];
-    out[8] = a[8];
-    return out;
-};
-
-/**
- * Copies the values from a mat2d into a mat3
- *
- * @param {mat3} out the receiving matrix
- * @param {mat2d} a the matrix to copy
- * @returns {mat3} out
- **/
-mat3.fromMat2d = function(out, a) {
-    out[0] = a[0];
-    out[1] = a[1];
-    out[2] = 0;
-
-    out[3] = a[2];
-    out[4] = a[3];
-    out[5] = 0;
-
-    out[6] = a[4];
-    out[7] = a[5];
-    out[8] = 1;
-    return out;
-};
-
-/**
-* Calculates a 3x3 matrix from the given quaternion
-*
-* @param {mat3} out mat3 receiving operation result
-* @param {quat} q Quaternion to create matrix from
-*
-* @returns {mat3} out
-*/
-mat3.fromQuat = function (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[3] = yx - wz;
-    out[6] = zx + wy;
-
-    out[1] = yx + wz;
-    out[4] = 1 - xx - zz;
-    out[7] = zy - wx;
-
-    out[2] = zx - wy;
-    out[5] = zy + wx;
-    out[8] = 1 - xx - yy;
-
-    return out;
-};
-
-/**
-* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
-*
-* @param {mat3} out mat3 receiving operation result
-* @param {mat4} a Mat4 to derive the normal matrix from
-*
-* @returns {mat3} out
-*/
-mat3.normalFromMat4 = function (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] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
-    out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
-
-    out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
-    out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
-    out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
-
-    out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
-    out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
-    out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
-
-    return out;
-};
-
-/**
- * Returns a string representation of a mat3
- *
- * @param {mat3} mat matrix to represent as a string
- * @returns {String} string representation of the matrix
- */
-mat3.str = function (a) {
-    return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + 
-                    a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + 
-                    a[6] + ', ' + a[7] + ', ' + a[8] + ')';
-};
-
-/**
- * Returns Frobenius norm of a mat3
- *
- * @param {mat3} a the matrix to calculate Frobenius norm of
- * @returns {Number} Frobenius norm
- */
-mat3.frob = function (a) {
-    return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)))
-};
-
-
-if(typeof(exports) !== 'undefined') {
-    exports.mat3 = mat3;
-}
-;
-/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-  * Redistributions of source code must retain the above copyright notice, this
-    list of conditions and the following disclaimer.
-  * Redistributions in binary form must reproduce the above copyright notice,
-    this list of conditions and the following disclaimer in the documentation 
-    and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-/**
- * @class 4x4 Matrix
- * @name mat4
- */
-
-var mat4 = {};
 
 /**
  * Creates a new identity mat4
  *
  * @returns {mat4} a new 4x4 matrix
  */
-mat4.create = function() {
-    var out = new GLMAT_ARRAY_TYPE(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;
-};
+function create() {
+  var out = new glMatrix.ARRAY_TYPE(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;
+}
 
 /**
  * Creates a new mat4 initialized with values from an existing matrix
@@ -2894,26 +3787,46 @@ mat4.create = function() {
  * @param {mat4} a matrix to clone
  * @returns {mat4} a new 4x4 matrix
  */
-mat4.clone = function(a) {
-    var out = new GLMAT_ARRAY_TYPE(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;
-};
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+function clone(a) {
+  var out = new glMatrix.ARRAY_TYPE(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;
+}
 
 /**
  * Copy the values from one mat4 to another
@@ -2922,25 +3835,109 @@ mat4.clone = function(a) {
  * @param {mat4} a the source matrix
  * @returns {mat4} out
  */
-mat4.copy = function(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;
-};
+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;
+}
+
+/**
+ * Create a new mat4 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} A new mat4
+ */
+function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
+  var out = new glMatrix.ARRAY_TYPE(16);
+  out[0] = m00;
+  out[1] = m01;
+  out[2] = m02;
+  out[3] = m03;
+  out[4] = m10;
+  out[5] = m11;
+  out[6] = m12;
+  out[7] = m13;
+  out[8] = m20;
+  out[9] = m21;
+  out[10] = m22;
+  out[11] = m23;
+  out[12] = m30;
+  out[13] = m31;
+  out[14] = m32;
+  out[15] = m33;
+  return out;
+}
+
+/**
+ * Set the components of a mat4 to the given values
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} out
+ */
+function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
+  out[0] = m00;
+  out[1] = m01;
+  out[2] = m02;
+  out[3] = m03;
+  out[4] = m10;
+  out[5] = m11;
+  out[6] = m12;
+  out[7] = m13;
+  out[8] = m20;
+  out[9] = m21;
+  out[10] = m22;
+  out[11] = m23;
+  out[12] = m30;
+  out[13] = m31;
+  out[14] = m32;
+  out[15] = m33;
+  return out;
+}
 
 /**
  * Set a mat4 to the identity matrix
@@ -2948,25 +3945,25 @@ mat4.copy = function(out, a) {
  * @param {mat4} out the receiving matrix
  * @returns {mat4} out
  */
-mat4.identity = function(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;
-};
+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;
+}
 
 /**
  * Transpose the values of a mat4
@@ -2975,46 +3972,49 @@ mat4.identity = function(out) {
  * @param {mat4} a the source matrix
  * @returns {mat4} out
  */
-mat4.transpose = function(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];
+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];
+    var a12 = a[6],
+        a13 = a[7];
+    var 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;
-};
+    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;
+}
 
 /**
  * Inverts a mat4
@@ -3023,52 +4023,64 @@ mat4.transpose = function(out, a) {
  * @param {mat4} a the source matrix
  * @returns {mat4} out
  */
-mat4.invert = function(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],
+function invert(out, a) {
+  var a00 = a[0],
+      a01 = a[1],
+      a02 = a[2],
+      a03 = a[3];
+  var a10 = a[4],
+      a11 = a[5],
+      a12 = a[6],
+      a13 = a[7];
+  var a20 = a[8],
+      a21 = a[9],
+      a22 = a[10],
+      a23 = a[11];
+  var 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,
+  var b00 = a00 * a11 - a01 * a10;
+  var b01 = a00 * a12 - a02 * a10;
+  var b02 = a00 * a13 - a03 * a10;
+  var b03 = a01 * a12 - a02 * a11;
+  var b04 = a01 * a13 - a03 * a11;
+  var b05 = a02 * a13 - a03 * a12;
+  var b06 = a20 * a31 - a21 * a30;
+  var b07 = a20 * a32 - a22 * a30;
+  var b08 = a20 * a33 - a23 * a30;
+  var b09 = a21 * a32 - a22 * a31;
+  var b10 = a21 * a33 - a23 * a31;
+  var b11 = a22 * a33 - a23 * a32;
 
-        // Calculate the determinant
-        det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+  // Calculate the determinant
+  var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
 
-    if (!det) { 
-        return null; 
-    }
-    det = 1.0 / det;
+  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;
+  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;
-};
+  return out;
+}
 
 /**
  * Calculates the adjugate of a mat4
@@ -3077,30 +4089,42 @@ mat4.invert = function(out, a) {
  * @param {mat4} a the source matrix
  * @returns {mat4} out
  */
-mat4.adjoint = function(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];
+function adjoint(out, a) {
+  var a00 = a[0],
+      a01 = a[1],
+      a02 = a[2],
+      a03 = a[3];
+  var a10 = a[4],
+      a11 = a[5],
+      a12 = a[6],
+      a13 = a[7];
+  var a20 = a[8],
+      a21 = a[9],
+      a22 = a[10],
+      a23 = a[11];
+  var 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;
-};
+  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;
+}
 
 /**
  * Calculates the determinant of a mat4
@@ -3108,75 +4132,96 @@ mat4.adjoint = function(out, a) {
  * @param {mat4} a the source matrix
  * @returns {Number} determinant of a
  */
-mat4.determinant = function (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],
+function determinant(a) {
+  var a00 = a[0],
+      a01 = a[1],
+      a02 = a[2],
+      a03 = a[3];
+  var a10 = a[4],
+      a11 = a[5],
+      a12 = a[6],
+      a13 = a[7];
+  var a20 = a[8],
+      a21 = a[9],
+      a22 = a[10],
+      a23 = a[11];
+  var 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;
+  var b00 = a00 * a11 - a01 * a10;
+  var b01 = a00 * a12 - a02 * a10;
+  var b02 = a00 * a13 - a03 * a10;
+  var b03 = a01 * a12 - a02 * a11;
+  var b04 = a01 * a13 - a03 * a11;
+  var b05 = a02 * a13 - a03 * a12;
+  var b06 = a20 * a31 - a21 * a30;
+  var b07 = a20 * a32 - a22 * a30;
+  var b08 = a20 * a33 - a23 * a30;
+  var b09 = a21 * a32 - a22 * a31;
+  var b10 = a21 * a33 - a23 * a31;
+  var b11 = a22 * a33 - a23 * a32;
 
-    // Calculate the determinant
-    return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
-};
+  // Calculate the determinant
+  return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+}
 
 /**
- * Multiplies two mat4's
+ * Multiplies two mat4s
  *
  * @param {mat4} out the receiving matrix
  * @param {mat4} a the first operand
  * @param {mat4} b the second operand
  * @returns {mat4} out
  */
-mat4.multiply = function (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];
+function multiply(out, a, b) {
+  var a00 = a[0],
+      a01 = a[1],
+      a02 = a[2],
+      a03 = a[3];
+  var a10 = a[4],
+      a11 = a[5],
+      a12 = a[6],
+      a13 = a[7];
+  var a20 = a[8],
+      a21 = a[9],
+      a22 = a[10],
+      a23 = a[11];
+  var 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;
+  // 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[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[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;
-};
-
-/**
- * Alias for {@link mat4.multiply}
- * @function
- */
-mat4.mul = mat4.multiply;
+  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;
+}
 
 /**
  * Translate a mat4 by the given vector
@@ -3186,67 +4231,80 @@ mat4.mul = mat4.multiply;
  * @param {vec3} v vector to translate by
  * @returns {mat4} out
  */
-mat4.translate = function (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;
+function translate(out, a, v) {
+  var x = v[0],
+      y = v[1],
+      z = v[2];
+  var a00 = void 0,
+      a01 = void 0,
+      a02 = void 0,
+      a03 = void 0;
+  var a10 = void 0,
+      a11 = void 0,
+      a12 = void 0,
+      a13 = void 0;
+  var a20 = void 0,
+      a21 = void 0,
+      a22 = void 0,
+      a23 = void 0;
 
-    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];
+  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[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];
-    }
+    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;
-};
+  return out;
+}
 
 /**
- * Scales the mat4 by the dimensions in the given vec3
+ * Scales the mat4 by the dimensions in the given vec3 not using vectorization
  *
  * @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
  **/
-mat4.scale = function(out, a, v) {
-    var x = v[0], y = v[1], z = v[2];
+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;
-};
+  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;
+}
 
 /**
- * Rotates a mat4 by the given angle
+ * Rotates a mat4 by the given angle around the given axis
  *
  * @param {mat4} out the receiving matrix
  * @param {mat4} a the matrix to rotate
@@ -3254,59 +4312,81 @@ mat4.scale = function(out, a, v) {
  * @param {vec3} axis the axis to rotate around
  * @returns {mat4} out
  */
-mat4.rotate = function (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;
+function rotate(out, a, rad, axis) {
+  var x = axis[0],
+      y = axis[1],
+      z = axis[2];
+  var len = Math.sqrt(x * x + y * y + z * z);
+  var s = void 0,
+      c = void 0,
+      t = void 0;
+  var a00 = void 0,
+      a01 = void 0,
+      a02 = void 0,
+      a03 = void 0;
+  var a10 = void 0,
+      a11 = void 0,
+      a12 = void 0,
+      a13 = void 0;
+  var a20 = void 0,
+      a21 = void 0,
+      a22 = void 0,
+      a23 = void 0;
+  var b00 = void 0,
+      b01 = void 0,
+      b02 = void 0;
+  var b10 = void 0,
+      b11 = void 0,
+      b12 = void 0;
+  var b20 = void 0,
+      b21 = void 0,
+      b22 = void 0;
 
-    if (Math.abs(len) < GLMAT_EPSILON) { return null; }
-    
-    len = 1 / len;
-    x *= len;
-    y *= len;
-    z *= len;
+  if (Math.abs(len) < glMatrix.EPSILON) {
+    return null;
+  }
 
-    s = Math.sin(rad);
-    c = Math.cos(rad);
-    t = 1 - c;
+  len = 1 / len;
+  x *= len;
+  y *= len;
+  z *= len;
 
-    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];
+  s = Math.sin(rad);
+  c = Math.cos(rad);
+  t = 1 - c;
 
-    // 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;
+  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];
 
-    // 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;
+  // 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;
 
-    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;
-};
+  // 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;
+}
 
 /**
  * Rotates a matrix by the given angle around the X axis
@@ -3316,40 +4396,41 @@ mat4.rotate = function (out, a, rad, axis) {
  * @param {Number} rad the angle to rotate the matrix by
  * @returns {mat4} out
  */
-mat4.rotateX = function (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];
+function rotateX(out, a, rad) {
+  var s = Math.sin(rad);
+  var c = Math.cos(rad);
+  var a10 = a[4];
+  var a11 = a[5];
+  var a12 = a[6];
+  var a13 = a[7];
+  var a20 = a[8];
+  var a21 = a[9];
+  var a22 = a[10];
+  var 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];
-    }
+  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;
-};
+  // 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;
+}
 
 /**
  * Rotates a matrix by the given angle around the Y axis
@@ -3359,40 +4440,41 @@ mat4.rotateX = function (out, a, rad) {
  * @param {Number} rad the angle to rotate the matrix by
  * @returns {mat4} out
  */
-mat4.rotateY = function (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];
+function rotateY(out, a, rad) {
+  var s = Math.sin(rad);
+  var c = Math.cos(rad);
+  var a00 = a[0];
+  var a01 = a[1];
+  var a02 = a[2];
+  var a03 = a[3];
+  var a20 = a[8];
+  var a21 = a[9];
+  var a22 = a[10];
+  var 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];
-    }
+  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;
-};
+  // 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;
+}
 
 /**
  * Rotates a matrix by the given angle around the Z axis
@@ -3402,40 +4484,262 @@ mat4.rotateY = function (out, a, rad) {
  * @param {Number} rad the angle to rotate the matrix by
  * @returns {mat4} out
  */
-mat4.rotateZ = function (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];
+function rotateZ(out, a, rad) {
+  var s = Math.sin(rad);
+  var c = Math.cos(rad);
+  var a00 = a[0];
+  var a01 = a[1];
+  var a02 = a[2];
+  var a03 = a[3];
+  var a10 = a[4];
+  var a11 = a[5];
+  var a12 = a[6];
+  var 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];
-    }
+  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;
-};
+  // 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;
+}
+
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ *     mat4.identity(dest);
+ *     mat4.translate(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {vec3} v Translation vector
+ * @returns {mat4} out
+ */
+function fromTranslation(out, v) {
+  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] = v[0];
+  out[13] = v[1];
+  out[14] = v[2];
+  out[15] = 1;
+  return out;
+}
+
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ *     mat4.identity(dest);
+ *     mat4.scale(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {vec3} v Scaling vector
+ * @returns {mat4} out
+ */
+function fromScaling(out, v) {
+  out[0] = v[0];
+  out[1] = 0;
+  out[2] = 0;
+  out[3] = 0;
+  out[4] = 0;
+  out[5] = v[1];
+  out[6] = 0;
+  out[7] = 0;
+  out[8] = 0;
+  out[9] = 0;
+  out[10] = v[2];
+  out[11] = 0;
+  out[12] = 0;
+  out[13] = 0;
+  out[14] = 0;
+  out[15] = 1;
+  return out;
+}
+
+/**
+ * Creates a matrix from a given angle around a given axis
+ * This is equivalent to (but much faster than):
+ *
+ *     mat4.identity(dest);
+ *     mat4.rotate(dest, dest, rad, axis);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {vec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+function fromRotation(out, rad, axis) {
+  var x = axis[0],
+      y = axis[1],
+      z = axis[2];
+  var len = Math.sqrt(x * x + y * y + z * z);
+  var s = void 0,
+      c = void 0,
+      t = void 0;
+
+  if (Math.abs(len) < glMatrix.EPSILON) {
+    return null;
+  }
+
+  len = 1 / len;
+  x *= len;
+  y *= len;
+  z *= len;
+
+  s = Math.sin(rad);
+  c = Math.cos(rad);
+  t = 1 - c;
+
+  // Perform rotation-specific matrix multiplication
+  out[0] = x * x * t + c;
+  out[1] = y * x * t + z * s;
+  out[2] = z * x * t - y * s;
+  out[3] = 0;
+  out[4] = x * y * t - z * s;
+  out[5] = y * y * t + c;
+  out[6] = z * y * t + x * s;
+  out[7] = 0;
+  out[8] = x * z * t + y * s;
+  out[9] = y * z * t - x * s;
+  out[10] = z * z * t + c;
+  out[11] = 0;
+  out[12] = 0;
+  out[13] = 0;
+  out[14] = 0;
+  out[15] = 1;
+  return out;
+}
+
+/**
+ * Creates a matrix from the given angle around the X axis
+ * This is equivalent to (but much faster than):
+ *
+ *     mat4.identity(dest);
+ *     mat4.rotateX(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+function fromXRotation(out, rad) {
+  var s = Math.sin(rad);
+  var c = Math.cos(rad);
+
+  // Perform axis-specific matrix multiplication
+  out[0] = 1;
+  out[1] = 0;
+  out[2] = 0;
+  out[3] = 0;
+  out[4] = 0;
+  out[5] = c;
+  out[6] = s;
+  out[7] = 0;
+  out[8] = 0;
+  out[9] = -s;
+  out[10] = c;
+  out[11] = 0;
+  out[12] = 0;
+  out[13] = 0;
+  out[14] = 0;
+  out[15] = 1;
+  return out;
+}
+
+/**
+ * Creates a matrix from the given angle around the Y axis
+ * This is equivalent to (but much faster than):
+ *
+ *     mat4.identity(dest);
+ *     mat4.rotateY(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+function fromYRotation(out, rad) {
+  var s = Math.sin(rad);
+  var c = Math.cos(rad);
+
+  // Perform axis-specific matrix multiplication
+  out[0] = c;
+  out[1] = 0;
+  out[2] = -s;
+  out[3] = 0;
+  out[4] = 0;
+  out[5] = 1;
+  out[6] = 0;
+  out[7] = 0;
+  out[8] = s;
+  out[9] = 0;
+  out[10] = c;
+  out[11] = 0;
+  out[12] = 0;
+  out[13] = 0;
+  out[14] = 0;
+  out[15] = 1;
+  return out;
+}
+
+/**
+ * Creates a matrix from the given angle around the Z axis
+ * This is equivalent to (but much faster than):
+ *
+ *     mat4.identity(dest);
+ *     mat4.rotateZ(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+function fromZRotation(out, rad) {
+  var s = Math.sin(rad);
+  var c = Math.cos(rad);
+
+  // Perform axis-specific matrix multiplication
+  out[0] = c;
+  out[1] = s;
+  out[2] = 0;
+  out[3] = 0;
+  out[4] = -s;
+  out[5] = c;
+  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;
+}
 
 /**
  * Creates a matrix from a quaternion rotation and vector translation
@@ -3443,7 +4747,7 @@ mat4.rotateZ = function (out, a, rad) {
  *
  *     mat4.identity(dest);
  *     mat4.translate(dest, vec);
- *     var quatMat = mat4.create();
+ *     let quatMat = mat4.create();
  *     quat4.toMat4(quat, quatMat);
  *     mat4.multiply(dest, quatMat);
  *
@@ -3452,81 +4756,311 @@ mat4.rotateZ = function (out, a, rad) {
  * @param {vec3} v Translation vector
  * @returns {mat4} out
  */
-mat4.fromRotationTranslation = function (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,
+function fromRotationTranslation(out, q, v) {
+  // Quaternion math
+  var x = q[0],
+      y = q[1],
+      z = q[2],
+      w = q[3];
+  var x2 = x + x;
+  var y2 = y + y;
+  var 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;
+  var xx = x * x2;
+  var xy = x * y2;
+  var xz = x * z2;
+  var yy = y * y2;
+  var yz = y * z2;
+  var zz = z * z2;
+  var wx = w * x2;
+  var wy = w * y2;
+  var 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;
-};
+  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;
 
-mat4.fromQuat = function (out, q) {
-    var x = q[0], y = q[1], z = q[2], w = q[3],
-        x2 = x + x,
-        y2 = y + y,
-        z2 = z + z,
+  return out;
+}
 
-        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;
+/**
+ * Returns the translation vector component of a transformation
+ *  matrix. If a matrix is built with fromRotationTranslation,
+ *  the returned vector will be the same as the translation vector
+ *  originally supplied.
+ * @param  {vec3} out Vector to receive translation component
+ * @param  {mat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+function getTranslation(out, mat) {
+  out[0] = mat[12];
+  out[1] = mat[13];
+  out[2] = mat[14];
 
-    out[0] = 1 - yy - zz;
-    out[1] = yx + wz;
-    out[2] = zx - wy;
-    out[3] = 0;
+  return out;
+}
 
-    out[4] = yx - wz;
-    out[5] = 1 - xx - zz;
-    out[6] = zy + wx;
-    out[7] = 0;
+/**
+ * Returns the scaling factor component of a transformation
+ *  matrix. If a matrix is built with fromRotationTranslationScale
+ *  with a normalized Quaternion paramter, the returned vector will be
+ *  the same as the scaling vector
+ *  originally supplied.
+ * @param  {vec3} out Vector to receive scaling factor component
+ * @param  {mat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+function getScaling(out, mat) {
+  var m11 = mat[0];
+  var m12 = mat[1];
+  var m13 = mat[2];
+  var m21 = mat[4];
+  var m22 = mat[5];
+  var m23 = mat[6];
+  var m31 = mat[8];
+  var m32 = mat[9];
+  var m33 = mat[10];
 
-    out[8] = zx + wy;
-    out[9] = zy - wx;
-    out[10] = 1 - xx - yy;
-    out[11] = 0;
+  out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);
+  out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);
+  out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);
 
-    out[12] = 0;
-    out[13] = 0;
-    out[14] = 0;
-    out[15] = 1;
+  return out;
+}
 
-    return out;
-};
+/**
+ * Returns a quaternion representing the rotational component
+ *  of a transformation matrix. If a matrix is built with
+ *  fromRotationTranslation, the returned quaternion will be the
+ *  same as the quaternion originally supplied.
+ * @param {quat} out Quaternion to receive the rotation component
+ * @param {mat4} mat Matrix to be decomposed (input)
+ * @return {quat} out
+ */
+function getRotation(out, mat) {
+  // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
+  var trace = mat[0] + mat[5] + mat[10];
+  var S = 0;
+
+  if (trace > 0) {
+    S = Math.sqrt(trace + 1.0) * 2;
+    out[3] = 0.25 * S;
+    out[0] = (mat[6] - mat[9]) / S;
+    out[1] = (mat[8] - mat[2]) / S;
+    out[2] = (mat[1] - mat[4]) / S;
+  } else if (mat[0] > mat[5] & mat[0] > mat[10]) {
+    S = Math.sqrt(1.0 + mat[0] - mat[5] - mat[10]) * 2;
+    out[3] = (mat[6] - mat[9]) / S;
+    out[0] = 0.25 * S;
+    out[1] = (mat[1] + mat[4]) / S;
+    out[2] = (mat[8] + mat[2]) / S;
+  } else if (mat[5] > mat[10]) {
+    S = Math.sqrt(1.0 + mat[5] - mat[0] - mat[10]) * 2;
+    out[3] = (mat[8] - mat[2]) / S;
+    out[0] = (mat[1] + mat[4]) / S;
+    out[1] = 0.25 * S;
+    out[2] = (mat[6] + mat[9]) / S;
+  } else {
+    S = Math.sqrt(1.0 + mat[10] - mat[0] - mat[5]) * 2;
+    out[3] = (mat[1] - mat[4]) / S;
+    out[0] = (mat[8] + mat[2]) / S;
+    out[1] = (mat[6] + mat[9]) / S;
+    out[2] = 0.25 * S;
+  }
+
+  return out;
+}
+
+/**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale
+ * This is equivalent to (but much faster than):
+ *
+ *     mat4.identity(dest);
+ *     mat4.translate(dest, vec);
+ *     let quatMat = mat4.create();
+ *     quat4.toMat4(quat, quatMat);
+ *     mat4.multiply(dest, quatMat);
+ *     mat4.scale(dest, scale)
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {vec3} v Translation vector
+ * @param {vec3} s Scaling vector
+ * @returns {mat4} out
+ */
+function fromRotationTranslationScale(out, q, v, s) {
+  // Quaternion math
+  var x = q[0],
+      y = q[1],
+      z = q[2],
+      w = q[3];
+  var x2 = x + x;
+  var y2 = y + y;
+  var z2 = z + z;
+
+  var xx = x * x2;
+  var xy = x * y2;
+  var xz = x * z2;
+  var yy = y * y2;
+  var yz = y * z2;
+  var zz = z * z2;
+  var wx = w * x2;
+  var wy = w * y2;
+  var wz = w * z2;
+  var sx = s[0];
+  var sy = s[1];
+  var sz = s[2];
+
+  out[0] = (1 - (yy + zz)) * sx;
+  out[1] = (xy + wz) * sx;
+  out[2] = (xz - wy) * sx;
+  out[3] = 0;
+  out[4] = (xy - wz) * sy;
+  out[5] = (1 - (xx + zz)) * sy;
+  out[6] = (yz + wx) * sy;
+  out[7] = 0;
+  out[8] = (xz + wy) * sz;
+  out[9] = (yz - wx) * sz;
+  out[10] = (1 - (xx + yy)) * sz;
+  out[11] = 0;
+  out[12] = v[0];
+  out[13] = v[1];
+  out[14] = v[2];
+  out[15] = 1;
+
+  return out;
+}
+
+/**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
+ * This is equivalent to (but much faster than):
+ *
+ *     mat4.identity(dest);
+ *     mat4.translate(dest, vec);
+ *     mat4.translate(dest, origin);
+ *     let quatMat = mat4.create();
+ *     quat4.toMat4(quat, quatMat);
+ *     mat4.multiply(dest, quatMat);
+ *     mat4.scale(dest, scale)
+ *     mat4.translate(dest, negativeOrigin);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {vec3} v Translation vector
+ * @param {vec3} s Scaling vector
+ * @param {vec3} o The origin vector around which to scale and rotate
+ * @returns {mat4} out
+ */
+function fromRotationTranslationScaleOrigin(out, q, v, s, o) {
+  // Quaternion math
+  var x = q[0],
+      y = q[1],
+      z = q[2],
+      w = q[3];
+  var x2 = x + x;
+  var y2 = y + y;
+  var z2 = z + z;
+
+  var xx = x * x2;
+  var xy = x * y2;
+  var xz = x * z2;
+  var yy = y * y2;
+  var yz = y * z2;
+  var zz = z * z2;
+  var wx = w * x2;
+  var wy = w * y2;
+  var wz = w * z2;
+
+  var sx = s[0];
+  var sy = s[1];
+  var sz = s[2];
+
+  var ox = o[0];
+  var oy = o[1];
+  var oz = o[2];
+
+  out[0] = (1 - (yy + zz)) * sx;
+  out[1] = (xy + wz) * sx;
+  out[2] = (xz - wy) * sx;
+  out[3] = 0;
+  out[4] = (xy - wz) * sy;
+  out[5] = (1 - (xx + zz)) * sy;
+  out[6] = (yz + wx) * sy;
+  out[7] = 0;
+  out[8] = (xz + wy) * sz;
+  out[9] = (yz - wx) * sz;
+  out[10] = (1 - (xx + yy)) * sz;
+  out[11] = 0;
+  out[12] = v[0] + ox - (out[0] * ox + out[4] * oy + out[8] * oz);
+  out[13] = v[1] + oy - (out[1] * ox + out[5] * oy + out[9] * oz);
+  out[14] = v[2] + oz - (out[2] * ox + out[6] * oy + out[10] * oz);
+  out[15] = 1;
+
+  return out;
+}
+
+/**
+ * Calculates a 4x4 matrix from the given quaternion
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat} q Quaternion to create matrix from
+ *
+ * @returns {mat4} out
+ */
+function fromQuat(out, q) {
+  var x = q[0],
+      y = q[1],
+      z = q[2],
+      w = q[3];
+  var x2 = x + x;
+  var y2 = y + y;
+  var z2 = z + z;
+
+  var xx = x * x2;
+  var yx = y * x2;
+  var yy = y * y2;
+  var zx = z * x2;
+  var zy = z * y2;
+  var zz = z * z2;
+  var wx = w * x2;
+  var wy = w * y2;
+  var 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;
+}
 
 /**
  * Generates a frustum matrix with the given bounds
@@ -3540,28 +5074,28 @@ mat4.fromQuat = function (out, q) {
  * @param {Number} far Far bound of the frustum
  * @returns {mat4} out
  */
-mat4.frustum = function (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;
-};
+function frustum(out, left, right, bottom, top, near, far) {
+  var rl = 1 / (right - left);
+  var tb = 1 / (top - bottom);
+  var 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;
+}
 
 /**
  * Generates a perspective projection matrix with the given bounds
@@ -3573,27 +5107,65 @@ mat4.frustum = function (out, left, right, bottom, top, near, far) {
  * @param {number} far Far bound of the frustum
  * @returns {mat4} out
  */
-mat4.perspective = function (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;
-};
+function perspective(out, fovy, aspect, near, far) {
+  var f = 1.0 / Math.tan(fovy / 2);
+  var 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;
+}
+
+/**
+ * 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 {Object} 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);
+  var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
+  var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);
+  var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);
+  var xScale = 2.0 / (leftTan + rightTan);
+  var 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;
+}
 
 /**
  * Generates a orthogonal projection matrix with the given bounds
@@ -3607,28 +5179,28 @@ mat4.perspective = function (out, fovy, aspect, near, far) {
  * @param {number} far Far bound of the frustum
  * @returns {mat4} out
  */
-mat4.ortho = function (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;
-};
+function ortho(out, left, right, bottom, top, near, far) {
+  var lr = 1 / (left - right);
+  var bt = 1 / (bottom - top);
+  var 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;
+}
 
 /**
  * Generates a look-at matrix with the given eye position, focal point, and up axis
@@ -3639,96 +5211,152 @@ mat4.ortho = function (out, left, right, bottom, top, near, far) {
  * @param {vec3} up vec3 pointing up
  * @returns {mat4} out
  */
-mat4.lookAt = function (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];
+function lookAt(out, eye, center, up) {
+  var x0 = void 0,
+      x1 = void 0,
+      x2 = void 0,
+      y0 = void 0,
+      y1 = void 0,
+      y2 = void 0,
+      z0 = void 0,
+      z1 = void 0,
+      z2 = void 0,
+      len = void 0;
+  var eyex = eye[0];
+  var eyey = eye[1];
+  var eyez = eye[2];
+  var upx = up[0];
+  var upy = up[1];
+  var upz = up[2];
+  var centerx = center[0];
+  var centery = center[1];
+  var centerz = center[2];
 
-    if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
-        Math.abs(eyey - centery) < GLMAT_EPSILON &&
-        Math.abs(eyez - centerz) < GLMAT_EPSILON) {
-        return mat4.identity(out);
-    }
+  if (Math.abs(eyex - centerx) < glMatrix.EPSILON && Math.abs(eyey - centery) < glMatrix.EPSILON && Math.abs(eyez - centerz) < glMatrix.EPSILON) {
+    return mat4.identity(out);
+  }
 
-    z0 = eyex - centerx;
-    z1 = eyey - centery;
-    z2 = eyez - centerz;
+  z0 = eyex - centerx;
+  z1 = eyey - centery;
+  z2 = eyez - centerz;
 
-    len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
+  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;
+}
+
+/**
+ * Generates a matrix that makes something look at something else.
+ *
+ * @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 targetTo(out, eye, target, up) {
+  var eyex = eye[0],
+      eyey = eye[1],
+      eyez = eye[2],
+      upx = up[0],
+      upy = up[1],
+      upz = up[2];
+
+  var z0 = eyex - target[0],
+      z1 = eyey - target[1],
+      z2 = eyez - target[2];
+
+  var len = z0 * z0 + z1 * z1 + z2 * z2;
+  if (len > 0) {
+    len = 1 / Math.sqrt(len);
     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;
-    }
+  var x0 = upy * z2 - upz * z1,
+      x1 = upz * z0 - upx * z2,
+      x2 = upx * z1 - upy * z0;
 
-    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;
+  out[0] = x0;
+  out[1] = x1;
+  out[2] = x2;
+  out[3] = 0;
+  out[4] = z1 * x2 - z2 * x1;
+  out[5] = z2 * x0 - z0 * x2;
+  out[6] = z0 * x1 - z1 * x0;
+  out[7] = 0;
+  out[8] = z0;
+  out[9] = z1;
+  out[10] = z2;
+  out[11] = 0;
+  out[12] = eyex;
+  out[13] = eyey;
+  out[14] = eyez;
+  out[15] = 1;
+  return out;
 };
 
 /**
  * Returns a string representation of a mat4
  *
- * @param {mat4} mat matrix to represent as a string
+ * @param {mat4} a matrix to represent as a string
  * @returns {String} string representation of the matrix
  */
-mat4.str = function (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] + ')';
-};
+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] + ')';
+}
 
 /**
  * Returns Frobenius norm of a mat4
@@ -3736,173 +5364,274 @@ mat4.str = function (a) {
  * @param {mat4} a the matrix to calculate Frobenius norm of
  * @returns {Number} Frobenius norm
  */
-mat4.frob = function (a) {
-    return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
-};
-
-
-if(typeof(exports) !== 'undefined') {
-    exports.mat4 = mat4;
+function frob(a) {
+  return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2));
 }
-;
-/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-  * Redistributions of source code must retain the above copyright notice, this
-    list of conditions and the following disclaimer.
-  * Redistributions in binary form must reproduce the above copyright notice,
-    this list of conditions and the following disclaimer in the documentation 
-    and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 
 /**
- * @class Quaternion
- * @name quat
+ * Adds 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 add(out, a, b) {
+  out[0] = a[0] + b[0];
+  out[1] = a[1] + b[1];
+  out[2] = a[2] + b[2];
+  out[3] = a[3] + b[3];
+  out[4] = a[4] + b[4];
+  out[5] = a[5] + b[5];
+  out[6] = a[6] + b[6];
+  out[7] = a[7] + b[7];
+  out[8] = a[8] + b[8];
+  out[9] = a[9] + b[9];
+  out[10] = a[10] + b[10];
+  out[11] = a[11] + b[11];
+  out[12] = a[12] + b[12];
+  out[13] = a[13] + b[13];
+  out[14] = a[14] + b[14];
+  out[15] = a[15] + b[15];
+  return out;
+}
 
-var quat = {};
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the first operand
+ * @param {mat4} b the second operand
+ * @returns {mat4} out
+ */
+function subtract(out, a, b) {
+  out[0] = a[0] - b[0];
+  out[1] = a[1] - b[1];
+  out[2] = a[2] - b[2];
+  out[3] = a[3] - b[3];
+  out[4] = a[4] - b[4];
+  out[5] = a[5] - b[5];
+  out[6] = a[6] - b[6];
+  out[7] = a[7] - b[7];
+  out[8] = a[8] - b[8];
+  out[9] = a[9] - b[9];
+  out[10] = a[10] - b[10];
+  out[11] = a[11] - b[11];
+  out[12] = a[12] - b[12];
+  out[13] = a[13] - b[13];
+  out[14] = a[14] - b[14];
+  out[15] = a[15] - b[15];
+  return out;
+}
+
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat4} out
+ */
+function multiplyScalar(out, a, b) {
+  out[0] = a[0] * b;
+  out[1] = a[1] * b;
+  out[2] = a[2] * b;
+  out[3] = a[3] * b;
+  out[4] = a[4] * b;
+  out[5] = a[5] * b;
+  out[6] = a[6] * b;
+  out[7] = a[7] * b;
+  out[8] = a[8] * b;
+  out[9] = a[9] * b;
+  out[10] = a[10] * b;
+  out[11] = a[11] * b;
+  out[12] = a[12] * b;
+  out[13] = a[13] * b;
+  out[14] = a[14] * b;
+  out[15] = a[15] * b;
+  return out;
+}
+
+/**
+ * Adds two mat4's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat4} out the receiving vector
+ * @param {mat4} a the first operand
+ * @param {mat4} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat4} out
+ */
+function multiplyScalarAndAdd(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;
+  out[3] = a[3] + b[3] * scale;
+  out[4] = a[4] + b[4] * scale;
+  out[5] = a[5] + b[5] * scale;
+  out[6] = a[6] + b[6] * scale;
+  out[7] = a[7] + b[7] * scale;
+  out[8] = a[8] + b[8] * scale;
+  out[9] = a[9] + b[9] * scale;
+  out[10] = a[10] + b[10] * scale;
+  out[11] = a[11] + b[11] * scale;
+  out[12] = a[12] + b[12] * scale;
+  out[13] = a[13] + b[13] * scale;
+  out[14] = a[14] + b[14] * scale;
+  out[15] = a[15] + b[15] * scale;
+  return out;
+}
+
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {mat4} a The first matrix.
+ * @param {mat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+function exactEquals(a, b) {
+  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
+}
+
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {mat4} a The first matrix.
+ * @param {mat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+function equals(a, b) {
+  var a0 = a[0],
+      a1 = a[1],
+      a2 = a[2],
+      a3 = a[3];
+  var a4 = a[4],
+      a5 = a[5],
+      a6 = a[6],
+      a7 = a[7];
+  var a8 = a[8],
+      a9 = a[9],
+      a10 = a[10],
+      a11 = a[11];
+  var a12 = a[12],
+      a13 = a[13],
+      a14 = a[14],
+      a15 = a[15];
+
+  var b0 = b[0],
+      b1 = b[1],
+      b2 = b[2],
+      b3 = b[3];
+  var b4 = b[4],
+      b5 = b[5],
+      b6 = b[6],
+      b7 = b[7];
+  var b8 = b[8],
+      b9 = b[9],
+      b10 = b[10],
+      b11 = b[11];
+  var b12 = b[12],
+      b13 = b[13],
+      b14 = b[14],
+      b15 = b[15];
+
+  return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));
+}
+
+/**
+ * Alias for {@link mat4.multiply}
+ * @function
+ */
+var mul = exports.mul = multiply;
+
+/**
+ * Alias for {@link mat4.subtract}
+ * @function
+ */
+var sub = exports.sub = subtract;
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.setAxes = exports.sqlerp = exports.rotationTo = exports.equals = exports.exactEquals = exports.normalize = exports.sqrLen = exports.squaredLength = exports.len = exports.length = exports.lerp = exports.dot = exports.scale = exports.mul = exports.add = exports.set = exports.copy = exports.fromValues = exports.clone = undefined;
+exports.create = create;
+exports.identity = identity;
+exports.setAxisAngle = setAxisAngle;
+exports.getAxisAngle = getAxisAngle;
+exports.multiply = multiply;
+exports.rotateX = rotateX;
+exports.rotateY = rotateY;
+exports.rotateZ = rotateZ;
+exports.calculateW = calculateW;
+exports.slerp = slerp;
+exports.invert = invert;
+exports.conjugate = conjugate;
+exports.fromMat3 = fromMat3;
+exports.fromEuler = fromEuler;
+exports.str = str;
+
+var _common = __webpack_require__(0);
+
+var glMatrix = _interopRequireWildcard(_common);
+
+var _mat = __webpack_require__(1);
+
+var mat3 = _interopRequireWildcard(_mat);
+
+var _vec = __webpack_require__(2);
+
+var vec3 = _interopRequireWildcard(_vec);
+
+var _vec2 = __webpack_require__(3);
+
+var vec4 = _interopRequireWildcard(_vec2);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+/**
+ * Quaternion
+ * @module quat
+ */
 
 /**
  * Creates a new identity quat
  *
  * @returns {quat} a new quaternion
  */
-quat.create = function() {
-    var out = new GLMAT_ARRAY_TYPE(4);
-    out[0] = 0;
-    out[1] = 0;
-    out[2] = 0;
-    out[3] = 1;
-    return out;
-};
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
 
-/**
- * Sets a quaternion to represent the shortest rotation from one
- * vector to another.
- *
- * Both vectors are assumed to be unit length.
- *
- * @param {quat} out the receiving quaternion.
- * @param {vec3} a the initial vector
- * @param {vec3} b the destination vector
- * @returns {quat} out
- */
-quat.rotationTo = (function() {
-    var tmpvec3 = vec3.create();
-    var xUnitVec3 = vec3.fromValues(1,0,0);
-    var yUnitVec3 = vec3.fromValues(0,1,0);
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
-    return function(out, a, b) {
-        var dot = vec3.dot(a, b);
-        if (dot < -0.999999) {
-            vec3.cross(tmpvec3, xUnitVec3, a);
-            if (vec3.length(tmpvec3) < 0.000001)
-                vec3.cross(tmpvec3, yUnitVec3, a);
-            vec3.normalize(tmpvec3, tmpvec3);
-            quat.setAxisAngle(out, tmpvec3, Math.PI);
-            return out;
-        } else if (dot > 0.999999) {
-            out[0] = 0;
-            out[1] = 0;
-            out[2] = 0;
-            out[3] = 1;
-            return out;
-        } else {
-            vec3.cross(tmpvec3, a, b);
-            out[0] = tmpvec3[0];
-            out[1] = tmpvec3[1];
-            out[2] = tmpvec3[2];
-            out[3] = 1 + dot;
-            return quat.normalize(out, out);
-        }
-    };
-})();
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
 
-/**
- * Sets the specified quaternion with values corresponding to the given
- * axes. Each axis is a vec3 and is expected to be unit length and
- * perpendicular to all other specified axes.
- *
- * @param {vec3} view  the vector representing the viewing direction
- * @param {vec3} right the vector representing the local "right" direction
- * @param {vec3} up    the vector representing the local "up" direction
- * @returns {quat} out
- */
-quat.setAxes = (function() {
-    var matr = mat3.create();
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
 
-    return function(out, view, right, up) {
-        matr[0] = right[0];
-        matr[3] = right[1];
-        matr[6] = right[2];
-
-        matr[1] = up[0];
-        matr[4] = up[1];
-        matr[7] = up[2];
-
-        matr[2] = -view[0];
-        matr[5] = -view[1];
-        matr[8] = -view[2];
-
-        return quat.normalize(out, quat.fromMat3(out, matr));
-    };
-})();
-
-/**
- * Creates a new quat initialized with values from an existing quaternion
- *
- * @param {quat} a quaternion to clone
- * @returns {quat} a new quaternion
- * @function
- */
-quat.clone = vec4.clone;
-
-/**
- * Creates a new quat initialized with the given values
- *
- * @param {Number} x X component
- * @param {Number} y Y component
- * @param {Number} z Z component
- * @param {Number} w W component
- * @returns {quat} a new quaternion
- * @function
- */
-quat.fromValues = vec4.fromValues;
-
-/**
- * Copy the values from one quat to another
- *
- * @param {quat} out the receiving quaternion
- * @param {quat} a the source quaternion
- * @returns {quat} out
- * @function
- */
-quat.copy = vec4.copy;
-
-/**
- * Set the components of a quat to the given values
- *
- * @param {quat} out the receiving quaternion
- * @param {Number} x X component
- * @param {Number} y Y component
- * @param {Number} z Z component
- * @param {Number} w W component
- * @returns {quat} out
- * @function
- */
-quat.set = vec4.set;
+function create() {
+  var out = new glMatrix.ARRAY_TYPE(4);
+  out[0] = 0;
+  out[1] = 0;
+  out[2] = 0;
+  out[3] = 1;
+  return out;
+}
 
 /**
  * Set a quat to the identity quaternion
@@ -3910,13 +5639,13 @@ quat.set = vec4.set;
  * @param {quat} out the receiving quaternion
  * @returns {quat} out
  */
-quat.identity = function(out) {
-    out[0] = 0;
-    out[1] = 0;
-    out[2] = 0;
-    out[3] = 1;
-    return out;
-};
+function identity(out) {
+  out[0] = 0;
+  out[1] = 0;
+  out[2] = 0;
+  out[3] = 1;
+  return out;
+}
 
 /**
  * Sets a quat from the given angle and rotation axis,
@@ -3927,26 +5656,44 @@ quat.identity = function(out) {
  * @param {Number} rad the angle in radians
  * @returns {quat} out
  **/
-quat.setAxisAngle = function(out, axis, rad) {
-    rad = rad * 0.5;
-    var s = Math.sin(rad);
-    out[0] = s * axis[0];
-    out[1] = s * axis[1];
-    out[2] = s * axis[2];
-    out[3] = Math.cos(rad);
-    return out;
-};
+function setAxisAngle(out, axis, rad) {
+  rad = rad * 0.5;
+  var s = Math.sin(rad);
+  out[0] = s * axis[0];
+  out[1] = s * axis[1];
+  out[2] = s * axis[2];
+  out[3] = Math.cos(rad);
+  return out;
+}
 
 /**
- * Adds two quat's
- *
- * @param {quat} out the receiving quaternion
- * @param {quat} a the first operand
- * @param {quat} b the second operand
- * @returns {quat} out
- * @function
+ * Gets the rotation axis and angle for a given
+ *  quaternion. If a quaternion is created with
+ *  setAxisAngle, this method will return the same
+ *  values as providied in the original parameter list
+ *  OR functionally equivalent values.
+ * Example: The quaternion formed by axis [0, 0, 1] and
+ *  angle -90 is the same as the quaternion formed by
+ *  [0, 0, 1] and 270. This method favors the latter.
+ * @param  {vec3} out_axis  Vector receiving the axis of rotation
+ * @param  {quat} q     Quaternion to be decomposed
+ * @return {Number}     Angle, in radians, of the rotation
  */
-quat.add = vec4.add;
+function getAxisAngle(out_axis, q) {
+  var rad = Math.acos(q[3]) * 2.0;
+  var s = Math.sin(rad / 2.0);
+  if (s != 0.0) {
+    out_axis[0] = q[0] / s;
+    out_axis[1] = q[1] / s;
+    out_axis[2] = q[2] / s;
+  } else {
+    // If s is zero, return any axis (no rotation - axis does not matter)
+    out_axis[0] = 1;
+    out_axis[1] = 0;
+    out_axis[2] = 0;
+  }
+  return rad;
+}
 
 /**
  * Multiplies two quat's
@@ -3956,33 +5703,22 @@ quat.add = vec4.add;
  * @param {quat} b the second operand
  * @returns {quat} out
  */
-quat.multiply = function(out, a, b) {
-    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
-        bx = b[0], by = b[1], bz = b[2], bw = b[3];
+function multiply(out, a, b) {
+  var ax = a[0],
+      ay = a[1],
+      az = a[2],
+      aw = a[3];
+  var bx = b[0],
+      by = b[1],
+      bz = b[2],
+      bw = b[3];
 
-    out[0] = ax * bw + aw * bx + ay * bz - az * by;
-    out[1] = ay * bw + aw * by + az * bx - ax * bz;
-    out[2] = az * bw + aw * bz + ax * by - ay * bx;
-    out[3] = aw * bw - ax * bx - ay * by - az * bz;
-    return out;
-};
-
-/**
- * Alias for {@link quat.multiply}
- * @function
- */
-quat.mul = quat.multiply;
-
-/**
- * Scales a quat by a scalar number
- *
- * @param {quat} out the receiving vector
- * @param {quat} a the vector to scale
- * @param {Number} b amount to scale the vector by
- * @returns {quat} out
- * @function
- */
-quat.scale = vec4.scale;
+  out[0] = ax * bw + aw * bx + ay * bz - az * by;
+  out[1] = ay * bw + aw * by + az * bx - ax * bz;
+  out[2] = az * bw + aw * bz + ax * by - ay * bx;
+  out[3] = aw * bw - ax * bx - ay * by - az * bz;
+  return out;
+}
 
 /**
  * Rotates a quaternion by the given angle about the X axis
@@ -3992,18 +5728,22 @@ quat.scale = vec4.scale;
  * @param {number} rad angle (in radians) to rotate
  * @returns {quat} out
  */
-quat.rotateX = function (out, a, rad) {
-    rad *= 0.5; 
+function rotateX(out, a, rad) {
+  rad *= 0.5;
 
-    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
-        bx = Math.sin(rad), bw = Math.cos(rad);
+  var ax = a[0],
+      ay = a[1],
+      az = a[2],
+      aw = a[3];
+  var bx = Math.sin(rad),
+      bw = Math.cos(rad);
 
-    out[0] = ax * bw + aw * bx;
-    out[1] = ay * bw + az * bx;
-    out[2] = az * bw - ay * bx;
-    out[3] = aw * bw - ax * bx;
-    return out;
-};
+  out[0] = ax * bw + aw * bx;
+  out[1] = ay * bw + az * bx;
+  out[2] = az * bw - ay * bx;
+  out[3] = aw * bw - ax * bx;
+  return out;
+}
 
 /**
  * Rotates a quaternion by the given angle about the Y axis
@@ -4013,18 +5753,22 @@ quat.rotateX = function (out, a, rad) {
  * @param {number} rad angle (in radians) to rotate
  * @returns {quat} out
  */
-quat.rotateY = function (out, a, rad) {
-    rad *= 0.5; 
+function rotateY(out, a, rad) {
+  rad *= 0.5;
 
-    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
-        by = Math.sin(rad), bw = Math.cos(rad);
+  var ax = a[0],
+      ay = a[1],
+      az = a[2],
+      aw = a[3];
+  var by = Math.sin(rad),
+      bw = Math.cos(rad);
 
-    out[0] = ax * bw - az * by;
-    out[1] = ay * bw + aw * by;
-    out[2] = az * bw + ax * by;
-    out[3] = aw * bw - ay * by;
-    return out;
-};
+  out[0] = ax * bw - az * by;
+  out[1] = ay * bw + aw * by;
+  out[2] = az * bw + ax * by;
+  out[3] = aw * bw - ay * by;
+  return out;
+}
 
 /**
  * Rotates a quaternion by the given angle about the Z axis
@@ -4034,18 +5778,22 @@ quat.rotateY = function (out, a, rad) {
  * @param {number} rad angle (in radians) to rotate
  * @returns {quat} out
  */
-quat.rotateZ = function (out, a, rad) {
-    rad *= 0.5; 
+function rotateZ(out, a, rad) {
+  rad *= 0.5;
 
-    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
-        bz = Math.sin(rad), bw = Math.cos(rad);
+  var ax = a[0],
+      ay = a[1],
+      az = a[2],
+      aw = a[3];
+  var bz = Math.sin(rad),
+      bw = Math.cos(rad);
 
-    out[0] = ax * bw + ay * bz;
-    out[1] = ay * bw - ax * bz;
-    out[2] = az * bw + aw * bz;
-    out[3] = aw * bw - az * bz;
-    return out;
-};
+  out[0] = ax * bw + ay * bz;
+  out[1] = ay * bw - ax * bz;
+  out[2] = az * bw + aw * bz;
+  out[3] = aw * bw - az * bz;
+  return out;
+}
 
 /**
  * Calculates the W component of a quat from the X, Y, and Z components.
@@ -4056,37 +5804,17 @@ quat.rotateZ = function (out, a, rad) {
  * @param {quat} a quat to calculate W component of
  * @returns {quat} out
  */
-quat.calculateW = function (out, a) {
-    var x = a[0], y = a[1], z = a[2];
+function calculateW(out, a) {
+  var x = a[0],
+      y = a[1],
+      z = a[2];
 
-    out[0] = x;
-    out[1] = y;
-    out[2] = z;
-    out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
-    return out;
-};
-
-/**
- * Calculates the dot product of two quat's
- *
- * @param {quat} a the first operand
- * @param {quat} b the second operand
- * @returns {Number} dot product of a and b
- * @function
- */
-quat.dot = vec4.dot;
-
-/**
- * Performs a linear interpolation between two quat's
- *
- * @param {quat} out the receiving quaternion
- * @param {quat} a the first operand
- * @param {quat} b the second operand
- * @param {Number} t interpolation amount between the two inputs
- * @returns {quat} out
- * @function
- */
-quat.lerp = vec4.lerp;
+  out[0] = x;
+  out[1] = y;
+  out[2] = z;
+  out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
+  return out;
+}
 
 /**
  * Performs a spherical linear interpolation between two quat
@@ -4097,46 +5825,55 @@ quat.lerp = vec4.lerp;
  * @param {Number} t interpolation amount between the two inputs
  * @returns {quat} out
  */
-quat.slerp = function (out, a, b, t) {
-    // benchmarks:
-    //    http://jsperf.com/quaternion-slerp-implementations
+function slerp(out, a, b, t) {
+  // benchmarks:
+  //    http://jsperf.com/quaternion-slerp-implementations
+  var ax = a[0],
+      ay = a[1],
+      az = a[2],
+      aw = a[3];
+  var bx = b[0],
+      by = b[1],
+      bz = b[2],
+      bw = b[3];
 
-    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
-        bx = b[0], by = b[1], bz = b[2], bw = b[3];
+  var omega = void 0,
+      cosom = void 0,
+      sinom = void 0,
+      scale0 = void 0,
+      scale1 = void 0;
 
-    var        omega, cosom, sinom, scale0, scale1;
+  // calc cosine
+  cosom = ax * bx + ay * by + az * bz + aw * bw;
+  // adjust signs (if necessary)
+  if (cosom < 0.0) {
+    cosom = -cosom;
+    bx = -bx;
+    by = -by;
+    bz = -bz;
+    bw = -bw;
+  }
+  // calculate coefficients
+  if (1.0 - cosom > 0.000001) {
+    // standard case (slerp)
+    omega = Math.acos(cosom);
+    sinom = Math.sin(omega);
+    scale0 = Math.sin((1.0 - t) * omega) / sinom;
+    scale1 = Math.sin(t * omega) / sinom;
+  } else {
+    // "from" and "to" quaternions are very close
+    //  ... so we can do a linear interpolation
+    scale0 = 1.0 - t;
+    scale1 = t;
+  }
+  // calculate final values
+  out[0] = scale0 * ax + scale1 * bx;
+  out[1] = scale0 * ay + scale1 * by;
+  out[2] = scale0 * az + scale1 * bz;
+  out[3] = scale0 * aw + scale1 * bw;
 
-    // calc cosine
-    cosom = ax * bx + ay * by + az * bz + aw * bw;
-    // adjust signs (if necessary)
-    if ( cosom < 0.0 ) {
-        cosom = -cosom;
-        bx = - bx;
-        by = - by;
-        bz = - bz;
-        bw = - bw;
-    }
-    // calculate coefficients
-    if ( (1.0 - cosom) > 0.000001 ) {
-        // standard case (slerp)
-        omega  = Math.acos(cosom);
-        sinom  = Math.sin(omega);
-        scale0 = Math.sin((1.0 - t) * omega) / sinom;
-        scale1 = Math.sin(t * omega) / sinom;
-    } else {        
-        // "from" and "to" quaternions are very close 
-        //  ... so we can do a linear interpolation
-        scale0 = 1.0 - t;
-        scale1 = t;
-    }
-    // calculate final values
-    out[0] = scale0 * ax + scale1 * bx;
-    out[1] = scale0 * ay + scale1 * by;
-    out[2] = scale0 * az + scale1 * bz;
-    out[3] = scale0 * aw + scale1 * bw;
-    
-    return out;
-};
+  return out;
+}
 
 /**
  * Calculates the inverse of a quat
@@ -4145,19 +5882,22 @@ quat.slerp = function (out, a, b, t) {
  * @param {quat} a quat to calculate inverse of
  * @returns {quat} out
  */
-quat.invert = function(out, a) {
-    var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
-        dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
-        invDot = dot ? 1.0/dot : 0;
-    
-    // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
+function invert(out, a) {
+  var a0 = a[0],
+      a1 = a[1],
+      a2 = a[2],
+      a3 = a[3];
+  var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
+  var invDot = dot ? 1.0 / dot : 0;
 
-    out[0] = -a0*invDot;
-    out[1] = -a1*invDot;
-    out[2] = -a2*invDot;
-    out[3] = a3*invDot;
-    return out;
-};
+  // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
+
+  out[0] = -a0 * invDot;
+  out[1] = -a1 * invDot;
+  out[2] = -a2 * invDot;
+  out[3] = a3 * invDot;
+  return out;
+}
 
 /**
  * Calculates the conjugate of a quat
@@ -4167,53 +5907,13 @@ quat.invert = function(out, a) {
  * @param {quat} a quat to calculate conjugate of
  * @returns {quat} out
  */
-quat.conjugate = function (out, a) {
-    out[0] = -a[0];
-    out[1] = -a[1];
-    out[2] = -a[2];
-    out[3] = a[3];
-    return out;
-};
-
-/**
- * Calculates the length of a quat
- *
- * @param {quat} a vector to calculate length of
- * @returns {Number} length of a
- * @function
- */
-quat.length = vec4.length;
-
-/**
- * Alias for {@link quat.length}
- * @function
- */
-quat.len = quat.length;
-
-/**
- * Calculates the squared length of a quat
- *
- * @param {quat} a vector to calculate squared length of
- * @returns {Number} squared length of a
- * @function
- */
-quat.squaredLength = vec4.squaredLength;
-
-/**
- * Alias for {@link quat.squaredLength}
- * @function
- */
-quat.sqrLen = quat.squaredLength;
-
-/**
- * Normalize a quat
- *
- * @param {quat} out the receiving quaternion
- * @param {quat} a quaternion to normalize
- * @returns {quat} out
- * @function
- */
-quat.normalize = vec4.normalize;
+function conjugate(out, a) {
+  out[0] = -a[0];
+  out[1] = -a[1];
+  out[2] = -a[2];
+  out[3] = a[3];
+  return out;
+}
 
 /**
  * Creates a quaternion from the given 3x3 rotation matrix.
@@ -4226,67 +5926,963 @@ quat.normalize = vec4.normalize;
  * @returns {quat} out
  * @function
  */
-quat.fromMat3 = function(out, m) {
-    // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
-    // article "Quaternion Calculus and Fast Animation".
-    var fTrace = m[0] + m[4] + m[8];
-    var fRoot;
+function fromMat3(out, m) {
+  // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
+  // article "Quaternion Calculus and Fast Animation".
+  var fTrace = m[0] + m[4] + m[8];
+  var fRoot = void 0;
 
-    if ( fTrace > 0.0 ) {
-        // |w| > 1/2, may as well choose w > 1/2
-        fRoot = Math.sqrt(fTrace + 1.0);  // 2w
-        out[3] = 0.5 * fRoot;
-        fRoot = 0.5/fRoot;  // 1/(4w)
-        out[0] = (m[5]-m[7])*fRoot;
-        out[1] = (m[6]-m[2])*fRoot;
-        out[2] = (m[1]-m[3])*fRoot;
-    } else {
-        // |w| <= 1/2
-        var i = 0;
-        if ( m[4] > m[0] )
-          i = 1;
-        if ( m[8] > m[i*3+i] )
-          i = 2;
-        var j = (i+1)%3;
-        var k = (i+2)%3;
-        
-        fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
-        out[i] = 0.5 * fRoot;
-        fRoot = 0.5 / fRoot;
-        out[3] = (m[j*3+k] - m[k*3+j]) * fRoot;
-        out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
-        out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
-    }
-    
-    return out;
-};
+  if (fTrace > 0.0) {
+    // |w| > 1/2, may as well choose w > 1/2
+    fRoot = Math.sqrt(fTrace + 1.0); // 2w
+    out[3] = 0.5 * fRoot;
+    fRoot = 0.5 / fRoot; // 1/(4w)
+    out[0] = (m[5] - m[7]) * fRoot;
+    out[1] = (m[6] - m[2]) * fRoot;
+    out[2] = (m[1] - m[3]) * fRoot;
+  } else {
+    // |w| <= 1/2
+    var i = 0;
+    if (m[4] > m[0]) i = 1;
+    if (m[8] > m[i * 3 + i]) i = 2;
+    var j = (i + 1) % 3;
+    var k = (i + 2) % 3;
+
+    fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);
+    out[i] = 0.5 * fRoot;
+    fRoot = 0.5 / fRoot;
+    out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;
+    out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;
+    out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;
+  }
+
+  return out;
+}
+
+/**
+ * Creates a quaternion from the given euler angle x, y, z.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {x} Angle to rotate around X axis in degrees.
+ * @param {y} Angle to rotate around Y axis in degrees.
+ * @param {z} Angle to rotate around Z axis in degrees.
+ * @returns {quat} out
+ * @function
+ */
+function fromEuler(out, x, y, z) {
+  var halfToRad = 0.5 * Math.PI / 180.0;
+  x *= halfToRad;
+  y *= halfToRad;
+  z *= halfToRad;
+
+  var sx = Math.sin(x);
+  var cx = Math.cos(x);
+  var sy = Math.sin(y);
+  var cy = Math.cos(y);
+  var sz = Math.sin(z);
+  var cz = Math.cos(z);
+
+  out[0] = sx * cy * cz - cx * sy * sz;
+  out[1] = cx * sy * cz + sx * cy * sz;
+  out[2] = cx * cy * sz - sx * sy * cz;
+  out[3] = cx * cy * cz + sx * sy * sz;
+
+  return out;
+}
 
 /**
  * Returns a string representation of a quatenion
  *
- * @param {quat} vec vector to represent as a string
+ * @param {quat} a vector to represent as a string
  * @returns {String} string representation of the vector
  */
-quat.str = function (a) {
-    return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
+function str(a) {
+  return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
+}
+
+/**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {quat} a quaternion to clone
+ * @returns {quat} a new quaternion
+ * @function
+ */
+var clone = exports.clone = vec4.clone;
+
+/**
+ * Creates a new quat initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} a new quaternion
+ * @function
+ */
+var fromValues = exports.fromValues = vec4.fromValues;
+
+/**
+ * Copy the values from one quat to another
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the source quaternion
+ * @returns {quat} out
+ * @function
+ */
+var copy = exports.copy = vec4.copy;
+
+/**
+ * Set the components of a quat to the given values
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} out
+ * @function
+ */
+var set = exports.set = vec4.set;
+
+/**
+ * Adds two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @returns {quat} out
+ * @function
+ */
+var add = exports.add = vec4.add;
+
+/**
+ * Alias for {@link quat.multiply}
+ * @function
+ */
+var mul = exports.mul = multiply;
+
+/**
+ * Scales a quat by a scalar number
+ *
+ * @param {quat} out the receiving vector
+ * @param {quat} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {quat} out
+ * @function
+ */
+var scale = exports.scale = vec4.scale;
+
+/**
+ * Calculates the dot product of two quat's
+ *
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+var dot = exports.dot = vec4.dot;
+
+/**
+ * Performs a linear interpolation between two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {quat} out
+ * @function
+ */
+var lerp = exports.lerp = vec4.lerp;
+
+/**
+ * Calculates the length of a quat
+ *
+ * @param {quat} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+var length = exports.length = vec4.length;
+
+/**
+ * Alias for {@link quat.length}
+ * @function
+ */
+var len = exports.len = length;
+
+/**
+ * Calculates the squared length of a quat
+ *
+ * @param {quat} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+var squaredLength = exports.squaredLength = vec4.squaredLength;
+
+/**
+ * Alias for {@link quat.squaredLength}
+ * @function
+ */
+var sqrLen = exports.sqrLen = squaredLength;
+
+/**
+ * Normalize a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quaternion to normalize
+ * @returns {quat} out
+ * @function
+ */
+var normalize = exports.normalize = vec4.normalize;
+
+/**
+ * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {quat} a The first quaternion.
+ * @param {quat} b The second quaternion.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+var exactEquals = exports.exactEquals = vec4.exactEquals;
+
+/**
+ * Returns whether or not the quaternions have approximately the same elements in the same position.
+ *
+ * @param {quat} a The first vector.
+ * @param {quat} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+var equals = exports.equals = vec4.equals;
+
+/**
+ * Sets a quaternion to represent the shortest rotation from one
+ * vector to another.
+ *
+ * Both vectors are assumed to be unit length.
+ *
+ * @param {quat} out the receiving quaternion.
+ * @param {vec3} a the initial vector
+ * @param {vec3} b the destination vector
+ * @returns {quat} out
+ */
+var rotationTo = exports.rotationTo = function () {
+  var tmpvec3 = vec3.create();
+  var xUnitVec3 = vec3.fromValues(1, 0, 0);
+  var yUnitVec3 = vec3.fromValues(0, 1, 0);
+
+  return function (out, a, b) {
+    var dot = vec3.dot(a, b);
+    if (dot < -0.999999) {
+      vec3.cross(tmpvec3, xUnitVec3, a);
+      if (vec3.len(tmpvec3) < 0.000001) vec3.cross(tmpvec3, yUnitVec3, a);
+      vec3.normalize(tmpvec3, tmpvec3);
+      setAxisAngle(out, tmpvec3, Math.PI);
+      return out;
+    } else if (dot > 0.999999) {
+      out[0] = 0;
+      out[1] = 0;
+      out[2] = 0;
+      out[3] = 1;
+      return out;
+    } else {
+      vec3.cross(tmpvec3, a, b);
+      out[0] = tmpvec3[0];
+      out[1] = tmpvec3[1];
+      out[2] = tmpvec3[2];
+      out[3] = 1 + dot;
+      return normalize(out, out);
+    }
+  };
+}();
+
+/**
+ * Performs a spherical linear interpolation with two control points
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @param {quat} c the third operand
+ * @param {quat} d the fourth operand
+ * @param {Number} t interpolation amount
+ * @returns {quat} out
+ */
+var sqlerp = exports.sqlerp = function () {
+  var temp1 = create();
+  var temp2 = create();
+
+  return function (out, a, b, c, d, t) {
+    slerp(temp1, a, d, t);
+    slerp(temp2, b, c, t);
+    slerp(out, temp1, temp2, 2 * t * (1 - t));
+
+    return out;
+  };
+}();
+
+/**
+ * Sets the specified quaternion with values corresponding to the given
+ * axes. Each axis is a vec3 and is expected to be unit length and
+ * perpendicular to all other specified axes.
+ *
+ * @param {vec3} view  the vector representing the viewing direction
+ * @param {vec3} right the vector representing the local "right" direction
+ * @param {vec3} up    the vector representing the local "up" direction
+ * @returns {quat} out
+ */
+var setAxes = exports.setAxes = function () {
+  var matr = mat3.create();
+
+  return function (out, view, right, up) {
+    matr[0] = right[0];
+    matr[3] = right[1];
+    matr[6] = right[2];
+
+    matr[1] = up[0];
+    matr[4] = up[1];
+    matr[7] = up[2];
+
+    matr[2] = -view[0];
+    matr[5] = -view[1];
+    matr[8] = -view[2];
+
+    return normalize(out, fromMat3(out, matr));
+  };
+}();
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.forEach = exports.sqrLen = exports.sqrDist = exports.dist = exports.div = exports.mul = exports.sub = exports.len = undefined;
+exports.create = create;
+exports.clone = clone;
+exports.fromValues = fromValues;
+exports.copy = copy;
+exports.set = set;
+exports.add = add;
+exports.subtract = subtract;
+exports.multiply = multiply;
+exports.divide = divide;
+exports.ceil = ceil;
+exports.floor = floor;
+exports.min = min;
+exports.max = max;
+exports.round = round;
+exports.scale = scale;
+exports.scaleAndAdd = scaleAndAdd;
+exports.distance = distance;
+exports.squaredDistance = squaredDistance;
+exports.length = length;
+exports.squaredLength = squaredLength;
+exports.negate = negate;
+exports.inverse = inverse;
+exports.normalize = normalize;
+exports.dot = dot;
+exports.cross = cross;
+exports.lerp = lerp;
+exports.random = random;
+exports.transformMat2 = transformMat2;
+exports.transformMat2d = transformMat2d;
+exports.transformMat3 = transformMat3;
+exports.transformMat4 = transformMat4;
+exports.str = str;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+
+var _common = __webpack_require__(0);
+
+var glMatrix = _interopRequireWildcard(_common);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+/**
+ * 2 Dimensional Vector
+ * @module vec2
+ */
+
+/**
+ * Creates a new, empty vec2
+ *
+ * @returns {vec2} a new 2D vector
+ */
+function create() {
+  var out = new glMatrix.ARRAY_TYPE(2);
+  out[0] = 0;
+  out[1] = 0;
+  return out;
+}
+
+/**
+ * Creates a new vec2 initialized with values from an existing vector
+ *
+ * @param {vec2} a vector to clone
+ * @returns {vec2} a new 2D vector
+ */
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+function clone(a) {
+  var out = new glMatrix.ARRAY_TYPE(2);
+  out[0] = a[0];
+  out[1] = a[1];
+  return out;
+}
+
+/**
+ * Creates a new vec2 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} a new 2D vector
+ */
+function fromValues(x, y) {
+  var out = new glMatrix.ARRAY_TYPE(2);
+  out[0] = x;
+  out[1] = y;
+  return out;
+}
+
+/**
+ * Copy the values from one vec2 to another
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the source vector
+ * @returns {vec2} out
+ */
+function copy(out, a) {
+  out[0] = a[0];
+  out[1] = a[1];
+  return out;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Multiplies 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 multiply(out, a, b) {
+  out[0] = a[0] * b[0];
+  out[1] = a[1] * b[1];
+  return out;
 };
 
-if(typeof(exports) !== 'undefined') {
-    exports.quat = quat;
+/**
+ * Divides 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 divide(out, a, b) {
+  out[0] = a[0] / b[0];
+  out[1] = a[1] / b[1];
+  return out;
+};
+
+/**
+ * Math.ceil the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to ceil
+ * @returns {vec2} out
+ */
+function ceil(out, a) {
+  out[0] = Math.ceil(a[0]);
+  out[1] = Math.ceil(a[1]);
+  return out;
+};
+
+/**
+ * Math.floor the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to floor
+ * @returns {vec2} out
+ */
+function floor(out, a) {
+  out[0] = Math.floor(a[0]);
+  out[1] = Math.floor(a[1]);
+  return out;
+};
+
+/**
+ * Returns the minimum of 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 min(out, a, b) {
+  out[0] = Math.min(a[0], b[0]);
+  out[1] = Math.min(a[1], b[1]);
+  return out;
+};
+
+/**
+ * Returns the maximum of 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 max(out, a, b) {
+  out[0] = Math.max(a[0], b[0]);
+  out[1] = Math.max(a[1], b[1]);
+  return out;
+};
+
+/**
+ * Math.round the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to round
+ * @returns {vec2} out
+ */
+function round(out, a) {
+  out[0] = Math.round(a[0]);
+  out[1] = Math.round(a[1]);
+  return out;
+};
+
+/**
+ * Scales a vec2 by a scalar number
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec2} out
+ */
+function scale(out, a, b) {
+  out[0] = a[0] * b;
+  out[1] = a[1] * b;
+  return out;
+};
+
+/**
+ * Adds two vec2's after scaling the second operand by a scalar value
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec2} out
+ */
+function scaleAndAdd(out, a, b, scale) {
+  out[0] = a[0] + b[0] * scale;
+  out[1] = a[1] + b[1] * scale;
+  return out;
+};
+
+/**
+ * Calculates the euclidian distance between two vec2's
+ *
+ * @param {vec2} a the first operand
+ * @param {vec2} 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];
+  return Math.sqrt(x * x + y * y);
+};
+
+/**
+ * Calculates the squared euclidian distance between two vec2's
+ *
+ * @param {vec2} a the first operand
+ * @param {vec2} 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];
+  return x * x + y * y;
+};
+
+/**
+ * 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);
+};
+
+/**
+ * Calculates the squared length of a vec2
+ *
+ * @param {vec2} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+function squaredLength(a) {
+  var x = a[0],
+      y = a[1];
+  return x * x + y * y;
+};
+
+/**
+ * Negates the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to negate
+ * @returns {vec2} out
+ */
+function negate(out, a) {
+  out[0] = -a[0];
+  out[1] = -a[1];
+  return out;
+};
+
+/**
+ * Returns the inverse of the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to invert
+ * @returns {vec2} out
+ */
+function inverse(out, a) {
+  out[0] = 1.0 / a[0];
+  out[1] = 1.0 / a[1];
+  return out;
+};
+
+/**
+ * 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;
+};
+
+/**
+ * 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];
+};
+
+/**
+ * Computes the cross product of two vec2's
+ * Note that the cross product must by definition produce a 3D vector
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec3} out
+ */
+function cross(out, a, b) {
+  var z = a[0] * b[1] - a[1] * b[0];
+  out[0] = out[1] = 0;
+  out[2] = z;
+  return out;
+};
+
+/**
+ * Performs a linear interpolation between two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec2} out
+ */
+function lerp(out, a, b, t) {
+  var ax = a[0],
+      ay = a[1];
+  out[0] = ax + t * (b[0] - ax);
+  out[1] = ay + t * (b[1] - ay);
+  return out;
+};
+
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec2} out
+ */
+function random(out, scale) {
+  scale = scale || 1.0;
+  var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+  out[0] = Math.cos(r) * scale;
+  out[1] = Math.sin(r) * scale;
+  return out;
+};
+
+/**
+ * Transforms the vec2 with a mat2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat2} m matrix to transform with
+ * @returns {vec2} out
+ */
+function transformMat2(out, a, m) {
+  var x = a[0],
+      y = a[1];
+  out[0] = m[0] * x + m[2] * y;
+  out[1] = m[1] * x + m[3] * y;
+  return out;
+};
+
+/**
+ * Transforms the vec2 with a mat2d
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat2d} m matrix to transform with
+ * @returns {vec2} out
+ */
+function transformMat2d(out, a, m) {
+  var x = a[0],
+      y = a[1];
+  out[0] = m[0] * x + m[2] * y + m[4];
+  out[1] = m[1] * x + m[3] * y + m[5];
+  return out;
+};
+
+/**
+ * Transforms the vec2 with a mat3
+ * 3rd vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat3} m matrix to transform with
+ * @returns {vec2} out
+ */
+function transformMat3(out, a, m) {
+  var x = a[0],
+      y = a[1];
+  out[0] = m[0] * x + m[3] * y + m[6];
+  out[1] = m[1] * x + m[4] * y + m[7];
+  return out;
+};
+
+/**
+ * Transforms the vec2 with a mat4
+ * 3rd vector component is implicitly '0'
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat4} m matrix to transform with
+ * @returns {vec2} out
+ */
+function transformMat4(out, a, m) {
+  var x = a[0];
+  var y = a[1];
+  out[0] = m[0] * x + m[4] * y + m[12];
+  out[1] = m[1] * x + m[5] * y + m[13];
+  return out;
 }
-;
 
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {vec2} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+function str(a) {
+  return 'vec2(' + a[0] + ', ' + a[1] + ')';
+}
 
+/**
+ * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
+ *
+ * @param {vec2} a The first vector.
+ * @param {vec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+function exactEquals(a, b) {
+  return a[0] === b[0] && a[1] === b[1];
+}
 
+/**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {vec2} a The first vector.
+ * @param {vec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+function equals(a, b) {
+  var a0 = a[0],
+      a1 = a[1];
+  var b0 = b[0],
+      b1 = b[1];
+  return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1));
+}
 
+/**
+ * Alias for {@link vec2.length}
+ * @function
+ */
+var len = exports.len = length;
 
+/**
+ * Alias for {@link vec2.subtract}
+ * @function
+ */
+var sub = exports.sub = subtract;
 
+/**
+ * Alias for {@link vec2.multiply}
+ * @function
+ */
+var mul = exports.mul = multiply;
 
+/**
+ * Alias for {@link vec2.divide}
+ * @function
+ */
+var div = exports.div = divide;
 
+/**
+ * Alias for {@link vec2.distance}
+ * @function
+ */
+var dist = exports.dist = distance;
 
+/**
+ * Alias for {@link vec2.squaredDistance}
+ * @function
+ */
+var sqrDist = exports.sqrDist = squaredDistance;
 
+/**
+ * Alias for {@link vec2.squaredLength}
+ * @function
+ */
+var sqrLen = exports.sqrLen = squaredLength;
 
+/**
+ * Perform some operation over an array of vec2s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec2s 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
+ */
+var forEach = exports.forEach = function () {
+  var vec = create();
 
+  return function (a, stride, offset, count, fn, arg) {
+    var i = void 0,
+        l = void 0;
+    if (!stride) {
+      stride = 2;
+    }
 
-  })(shim.exports);
-})(this);
+    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];
+      fn(vec, vec, arg);
+      a[i] = vec[0];a[i + 1] = vec[1];
+    }
+
+    return a;
+  };
+}();
+
+/***/ })
+/******/ ]);
+});
\ No newline at end of file
diff --git a/code/particles/itemboxShard.js b/code/particles/itemboxShard.js
index e3e4af9..2ebbd71 100644
--- a/code/particles/itemboxShard.js
+++ b/code/particles/itemboxShard.js
@@ -5,35 +5,35 @@
 //
 
 window.ItemShard = function(scene, targ, model) {
-	var t = this;
-	t.update = update;
-	t.draw = draw;
+    var t = this;
+    t.update = update;
+    t.draw = draw;
 
-	t.time = 0;
-	t.pos = vec3.clone(targ.pos);
-	t.vel = vec3.add([], targ.vel, [(Math.random()-0.5)*5, Math.random()*7, (Math.random()-0.5)*5]);
-	t.dirVel = [(Math.random()-0.5), (Math.random()-0.5), (Math.random()-0.5)];
-	t.dir = [Math.random()*2*Math.PI, Math.random()*2*Math.PI, Math.random()*2*Math.PI];
-	t.scale = Math.random()+0.5;
-	t.scale = [t.scale, t.scale, t.scale];
+    t.time = 0;
+    t.pos = vec3.clone(targ.pos);
+    t.vel = vec3.add([], targ.vel, [(Math.random()-0.5)*5, Math.random()*7, (Math.random()-0.5)*5]);
+    t.dirVel = [(Math.random()-0.5), (Math.random()-0.5), (Math.random()-0.5)];
+    t.dir = [Math.random()*2*Math.PI, Math.random()*2*Math.PI, Math.random()*2*Math.PI];
+    t.scale = Math.random()+0.5;
+    t.scale = [t.scale, t.scale, t.scale];
 
-	function update(scene) {
-		vec3.add(t.pos, t.pos, t.vel);
-		vec3.add(t.vel, t.vel, [0, -0.17, 0]);
-		vec3.add(t.dir, t.dir, t.dirVel);
+    function update(scene) {
+        vec3.add(t.pos, t.pos, t.vel);
+        vec3.add(t.vel, t.vel, [0, -0.17, 0]);
+        vec3.add(t.dir, t.dir, t.dirVel);
 
-		if (t.time++ > 30) scene.removeParticle(t);
-	}
+        if (t.time++ > 30) scene.removeParticle(t);
+    }
 
-	function draw(view, pMatrix, gl) {
-		var mat = mat4.translate(mat4.create(), view, t.pos);
-			
-		mat4.rotateZ(mat, mat, t.dir[2]);
-		mat4.rotateY(mat, mat, t.dir[1]);
-		mat4.rotateX(mat, mat, t.dir[0]);
+    function draw(view, pMatrix, gl) {
+        var mat = mat4.translate(mat4.create(), view, t.pos);
+            
+        mat4.rotateZ(mat, mat, t.dir[2]);
+        mat4.rotateY(mat, mat, t.dir[1]);
+        mat4.rotateX(mat, mat, t.dir[0]);
 
-		mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
-		model.draw(mat, pMatrix);
-	}
+        mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
+        model.draw(mat, pMatrix);
+    }
 
 }
\ No newline at end of file
diff --git a/code/particles/nitroEmitter.js b/code/particles/nitroEmitter.js
new file mode 100644
index 0000000..d32268b
--- /dev/null
+++ b/code/particles/nitroEmitter.js
@@ -0,0 +1,173 @@
+//
+// nitroEmitter.js
+//--------------------
+// Implemtents the generic nitro particle emitter.
+// by riperiperi
+//
+
+window.NitroEmitter = function(scene, targ, emitterID, vector, offset) {
+    var t = this;
+    t.update = update;
+    t.draw = draw;
+
+    var pRes = scene.gameRes.RaceEffect;
+    var emitter = (emitterID == -1)?null:pRes.particles[emitterID];
+    t.attached = targ; //an entity with pos and vel.
+
+    if (vector == null) vector = [0, 1, 0];
+    if (offset == null) offset = [0,0,0];
+    t.offset = offset;
+    t.vector = vector;
+    t.pctParticle = 0;
+    t.time = 0;
+    t.dead = false;
+    t.curPrio = 0;
+    t.doNotDelete = (emitter == null);
+    t.pause = false;
+
+    t.setEmitter = setEmitter;
+    t.clearEmitter = clearEmitter;
+
+    var particleList = [emitterID, -1, -1, -1];
+
+    function setEmitter(emitterID, prio) {
+        particleList[prio] = emitterID;
+        if (t.curPrio <= prio) {
+            //activate this emitter immediately.
+            t.curPrio = prio;
+            t.dead = false;
+            emitter = pRes.particles[emitterID];
+            t.time = 0;
+        }
+    }
+
+    function clearEmitter(prio) {
+        //if (t.curPrio > prio) return; //this emitter cannot be unset
+        if (prio == t.curPrio) {
+            findNextEmitter();
+        } else {
+            particleList[prio] = -1;
+        }
+    }
+
+    function findNextEmitter() {
+        particleList[t.curPrio] = -1;
+        var em = t.curPrio-1;
+        while (em >= 0) {
+            if (particleList[em] != -1) {
+                t.dead = false;
+                emitter = pRes.particles[particleList[em]];
+                t.time = 0;
+                t.curPrio = em;
+                return;
+            }
+            em--;
+        }
+        if (em == -1) {
+            t.curPrio = 0;
+            emitter = null;
+            dead = true;
+        }
+        t.curPrio = em;
+    }
+
+    function update(scene) {
+        if (emitter == null || t.dead || t.pause) return;
+        if ((t.time % (emitter.frequency)) == 0 && t.time >= emitter.delay) {
+            //should we create new particles? fractional logic for doing this
+            t.pctParticle += emitter.particleChance;
+            while (t.pctParticle >= 1) {
+
+                var attach = (emitter.flag & 0x8000) > 0;
+
+                t.pctParticle -= 1;
+                //create a new particle
+                //TODO: make these transform with the target's world matrix
+                var pos = vec3.create();
+                //add offset
+                vec3.add(pos, pos, t.offset);
+                //add emitter properties
+                vec3.add(pos, pos, emitter.position);
+                var spread = [Math.random()*2-1, Math.random()*2-1, Math.random()*2-1];
+                var spreadMode = (emitter.flag & 0xF);
+                if (spreadMode == 2) {
+                    spread[1] = 0; //spread is only in xz direction
+                }
+                vec3.normalize(spread, spread);
+                if (spreadMode == 0) {
+                    spread = [0,0,0];
+                }
+                vec3.scale(spread, spread, Math.random()*emitter.areaSpread*2);
+                vec3.add(pos, pos, spread);
+
+                vec3.scale(pos, pos, 16);
+                if (!attach) {
+                    if (targ.mat != null) {
+                        vec3.transformMat4(pos, pos, targ.mat);
+                    } else {
+                        vec3.add(pos, pos, targ.pos);
+                    }
+                }
+
+                //inherit velocity
+                var vel = (attach)?vec3.create():vec3.clone(targ.vel);
+                vec3.scale(vel, vel, 1/32);
+
+                var vector = vec3.clone(t.vector);
+                if (!attach) {
+                    if (targ.mat != null) {
+                        //tranform our vector by the target matrix
+                        var mat = targ.mat;
+                        var org = [];
+                        mat4.getTranslation(org, mat);
+                        mat[12] = 0;
+                        mat[13] = 0;
+                        mat[14] = 0;
+
+                        vec3.transformMat4(vector, vector, mat);
+
+                        mat[12] = org[0];
+                        mat[13] = org[1];
+                        mat[14] = org[2];
+                    }
+                }
+                vec3.normalize(vector, vector);
+                vec3.add(vel, vel, vec3.scale([], vector, emitter.velocity));
+
+                var xz = [Math.random()*2-1, 0, Math.random()*2-1];
+                vec3.normalize(xz, xz);
+                vec3.scale(xz, xz, Math.random()*emitter.randomxz);
+                vec3.add(vel, vel, xz);
+
+                var rotVel = ((emitter.rotVelFrom + ((Math.random()*emitter.rotVelTo-emitter.rotVelFrom) | 0))/65535) * Math.PI*2;
+                var dir = ((emitter.flag & 0x2000) > 0)?(Math.random()*Math.PI*2):0;
+                var duration = emitter.duration + emitter.duration * emitter.varDuration/0xFF * (Math.random() * 2 - 1);
+                var scaleMod = (emitter.varScale/0xFF * (Math.random() * 2 - 1)) + 1;
+
+                var scale = [scaleMod * emitter.size, scaleMod * emitter.size * emitter.aspect];
+
+                var particle = new NitroParticle(scene, emitter, pos, vel, dir, rotVel, duration, scale, (attach?t.attached:null));
+                particle.ovel = (attach)?vec3.create():vec3.scale([], targ.vel, 1/32);
+
+                scene.particles.push(particle);
+            }
+
+
+            var pos = vec3.clone(targ.pos);
+
+        }
+        t.time++;
+
+        if (t.time == emitter.emitterLifetime) {
+            t.dead = true;
+            if (!t.doNotDelete) scene.removeParticle(t);
+            else {
+                findNextEmitter();
+            }
+        }
+    }
+
+    function draw(view, pMatrix, gl) {
+
+    }
+}
\ No newline at end of file
diff --git a/code/particles/nitroParticle.js b/code/particles/nitroParticle.js
new file mode 100644
index 0000000..f466ddb
--- /dev/null
+++ b/code/particles/nitroParticle.js
@@ -0,0 +1,251 @@
+//
+// nitroParticle.js
+//--------------------
+// Implements a generic nitro particle. Currently positioned and updated in software for debug
+// simplicity - but should be moved to vertex shader in future.
+// by riperiperi
+//
+
+window.NitroParticle = function(scene, emitter, pos, vel, dir, dirVel, duration, scale, attached) {
+    var t = this;
+    t.update = update;
+    t.draw = draw;
+
+    t.time = 0;
+    t.duration = duration | 0;
+    t.pos = vec3.add(pos, pos, [0, 0, 0]);
+    t.vel = vel;
+    t.dirVel = dirVel; //float
+    t.dir = dir; //float
+    t.attached = attached;
+    t.scale = scale; //vec2
+    t.emitter = emitter;
+
+    t.aScale = 1;
+    //decode 16 bit color into float
+    t.baseColor = convertCol(emitter.color);
+    t.baseColor[3] = emitter.opacity / 0x1F;
+    t.aColor = vec4.clone(t.baseColor);
+
+    t.frame = emitter.textureId;
+    if (t.emitter.texAnim)
+        t.frame = t.emitter.texAnim.textures[0];
+
+    function convertCol(col) {
+        return [
+        ((col&31)/31), 
+        (((col>>5)&31)/31),
+        (((col>>10)&31)/31),
+        1 //Math.round((col>>15)*255);
+        ];
+    }
+
+    function update(scene) {
+        var particlePct = t.time / t.duration;
+
+        t.pos[0] += t.vel[0] * 16;
+        t.pos[1] += t.vel[1] * (t.emitter.yOffIntensity/128) * 16;
+        t.pos[2] += t.vel[2] * 16;
+        if (t.emitter.gravity) {
+            vec3.add(t.vel, t.vel, t.emitter.gravity);
+        }
+        if (t.emitter.colorAnim) {
+            var ca = t.emitter.colorAnim;
+            var from = convertCol(ca.colorFrom);
+            var to = convertCol(ca.colorTo);
+            var pctFloat = (ca.framePct/0xFFFF);
+            vec4.lerp(t.aColor, from, to, Math.max(0, (particlePct - pctFloat)/(1 - pctFloat)));
+            t.aColor[3] = t.emitter.opacity/0x1F;
+        } else {
+            t.aColor = vec4.clone(t.baseColor);
+        }
+        if (t.emitter.opacityAnim) {
+            var oa = t.emitter.opacityAnim;
+            var pctFade = oa.startFade / 0xFFFF;
+            var opaMul = 1-Math.max(0, (particlePct - pctFade)/(1 - pctFade));
+            t.aColor[3] = opaMul;// * oa.intensity/0x0FFF;
+            //vec4.scale(t.aColor, t.aColor, opaMul);
+        }
+        if (t.emitter.texAnim) {
+            var ta = t.emitter.texAnim;
+            var frame = 0;
+            if ((ta.unknown1 & 128) > 0) {
+                //select frame based on particle duration
+                var frame = ta.textures[Math.min((particlePct * ta.frames) | 0, ta.frames-1)];
+            } else {
+                //repeating anim with framerate
+                //not sure what framerate is, but its likely in the unknowns.
+                var frame = ta.textures[(t.time % ta.frames)];
+            }
+            t.frame = frame;
+        }
+
+        t.dir += t.dirVel;
+
+        if (t.time++ >= t.duration) scene.removeParticle(t);
+    }
+
+    function draw(view, pMatrix, gl) {
+        var particlePct = t.time / t.duration;
+
+        let pos = t.pos;
+        let vel = t.vel;
+
+        if (t.attached != null) {
+            pos = vec3.transformMat4([], pos, t.attached.mat);
+
+            
+            //tranform our vector by the target matrix
+            var mat = t.attached.mat;
+            var org = [];
+
+            mat4.getTranslation(org, mat);
+            mat[12] = 0;
+            mat[13] = 0;
+            mat[14] = 0;
+
+            vel = vec3.transformMat4([], vel, mat);
+
+            mat[12] = org[0];
+            mat[13] = org[1];
+            mat[14] = org[2];
+            
+        }
+
+        var mat = mat4.translate(mat4.create(), view, pos);
+            
+        var bbMode = t.emitter.flag & 0xF0;
+
+        if (bbMode == 0x10) { //spark, billboards towards camera
+            var camPos = scene.camera.view.pos;
+
+            camPos = vec3.sub([], camPos, pos);
+            vec3.normalize(camPos, camPos);
+
+            var n = vec3.sub([], vel, t.ovel);
+            vec3.normalize(n,n);
+            mat4.multiply(mat, mat, mat4.invert([], mat4.lookAt([], [0,0,0], camPos, n)));
+            
+        } else if (bbMode == 0x20) { //no billboard
+            mat4.rotateY(mat, mat, t.dir);
+        } else if (bbMode == 0x30) { //spark, no billboard
+            var camPos = scene.camera.view.pos;
+
+            camPos = vec3.sub([], camPos, pos);
+            vec3.normalize(camPos, camPos);
+
+            var n = vec3.sub([], vel, t.ovel);
+            vec3.normalize(n,n);
+            mat4.multiply(mat, mat, mat4.invert([], mat4.lookAt([], [0,0,0], camPos, n)));
+            mat4.rotateY(mat, mat, t.dir);
+        } else { //billboard
+            mat4.multiply(mat, mat, nitroRender.billboardMat);
+            mat4.rotateZ(mat, mat, t.dir);
+        }
+        var finalScale = 1;
+        if (t.emitter.scaleAnim) {
+            var sa = t.emitter.scaleAnim;
+            if (particlePct < sa.fromZeroTime) {
+                var fzPct = particlePct / sa.fromZeroTime;
+                finalScale = sa.scaleFrom * fzPct;
+            } else {
+                var rescaledPct = Math.min(1, (particlePct - sa.fromZeroTime) / (1-(sa.fromZeroTime + sa.holdTime*(1-sa.fromZeroTime))));
+                finalScale = sa.scaleFrom * (1-rescaledPct) + sa.scaleTo * rescaledPct;
+            }
+        }
+        mat4.scale(mat, mat, vec3.scale([], [t.scale[0], t.scale[1], 1], 12*finalScale));
+        mat4.translate(mat, mat, [t.emitter.xScaleDelta, t.emitter.yScaleDelta, 0]);
+
+        drawGeneric(mat, pMatrix, gl);
+    }
+
+    var MAT3I = mat3.create();
+    var MAT4I = mat4.create();
+    function drawGeneric(mv, project, gl) {
+        var shader = nitroRender.nitroShader;
+        if (!nitroRender.flagShadow) {
+            gl.uniform1f(shader.shadOffUniform, 0.001);
+            gl.uniform1f(shader.lightIntensityUniform, 0);
+        }
+        if (window.VTX_PARTICLE == null) genGlobalVtx(gl);
+        var obj = window.VTX_PARTICLE;
+
+        nitroRender.setColMult(t.aColor);
+
+        gl.uniformMatrix4fv(shader.mvMatrixUniform, false, mv);
+        gl.uniformMatrix4fv(shader.pMatrixUniform, false, project);
+        //matrix stack unused, just put an identity in slot 0
+        gl.uniformMatrix4fv(shader.matStackUniform, false, MAT4I);
+
+        var frame = t.emitter.parent.getTexture(t.frame, gl);
+        gl.bindTexture(gl.TEXTURE_2D, frame);
+        //texture matrix not used
+        gl.uniformMatrix3fv(shader.texMatrixUniform, false, MAT3I);
+        if (obj != nitroRender.last.obj) {
+            gl.bindBuffer(gl.ARRAY_BUFFER, obj.vPos);
+            gl.vertexAttribPointer(shader.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
+
+            gl.bindBuffer(gl.ARRAY_BUFFER, obj.vTx);
+            gl.vertexAttribPointer(shader.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
+
+            gl.bindBuffer(gl.ARRAY_BUFFER, obj.vCol);
+            gl.vertexAttribPointer(shader.colorAttribute, 4, gl.FLOAT, false, 0, 0);
+
+            gl.bindBuffer(gl.ARRAY_BUFFER, obj.vMat);
+            gl.vertexAttribPointer(shader.matAttribute, 1, gl.FLOAT, false, 0, 0);
+
+            gl.bindBuffer(gl.ARRAY_BUFFER, obj.vNorm);
+            gl.vertexAttribPointer(shader.normAttribute, 3, gl.FLOAT, false, 0, 0);
+            nitroRender.last.obj = obj;
+        }
+
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+        nitroRender.setColMult([1, 1, 1, 1]);
+        if (!nitroRender.flagShadow) {
+            nitroRender.resetShadOff();
+            gl.uniform1f(shader.lightIntensityUniform, 0.3);
+        }
+    }
+
+    function genGlobalVtx(gl) {
+        var vecPos = [-1,-1,0, 1,-1,0, -1,1,0, 1,1,0];
+        var vecTx = [1,1, 0,1, 1,0, 0,0];
+        var vecCol = [1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1];
+        var vecMat = [0,0,0,0];
+        var vecNorm = [0,1,0, 0,1,0, 0,1,0, 0,1,0];
+
+        var pos = gl.createBuffer();
+        var col = gl.createBuffer();
+        var tx = gl.createBuffer();
+        var mat = gl.createBuffer();
+        var norm = gl.createBuffer();
+
+        var posArray = new Float32Array(vecPos);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, pos);
+        gl.bufferData(gl.ARRAY_BUFFER, posArray, gl.STATIC_DRAW);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, tx);
+        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecTx), gl.STATIC_DRAW);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, col);
+        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecCol), gl.STATIC_DRAW);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, mat);
+        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecMat), gl.STATIC_DRAW);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, norm);
+        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecNorm), gl.STATIC_DRAW);
+
+        window.VTX_PARTICLE = {
+            posArray: posArray,
+            vPos: pos,
+            vTx: tx,
+            vCol: col,
+            vMat: mat,
+            vNorm: norm,
+            verts: vecPos.length/3,
+        };
+    }
+}
\ No newline at end of file
diff --git a/code/render/nitroRender.js b/code/render/nitroRender.js
index 16c0c6f..65d8a96 100644
--- a/code/render/nitroRender.js
+++ b/code/render/nitroRender.js
@@ -246,10 +246,9 @@ window.nitroRender = new function() {
 
 		gl.uniformMatrix4fv(shader.shadowMatUniform, false, sMat);
 		gl.uniformMatrix4fv(shader.farShadowMatUniform, false, fsMat);
+		gl.uniform1f(shader.lightIntensityUniform, 0.3);
 
-		gl.uniform1f(shader.shadOffUniform, 0.00005+((mobile)?0.0005:0));
-		gl.uniform1f(shader.farShadOffUniform, 0.0005);
-
+		this.resetShadOff();
 		gl.activeTexture(gl.TEXTURE1);
 		gl.bindTexture(gl.TEXTURE_2D, sTex);
 		gl.uniform1i(shader.lightSamplerUniform, 1);
@@ -262,6 +261,12 @@ window.nitroRender = new function() {
 		this.prepareShader();
 	}
 
+	this.resetShadOff = function() {
+		var shader = shaders[1];
+		gl.uniform1f(shader.shadOffUniform, 0.00005+((mobile)?0.0005:0));
+		gl.uniform1f(shader.farShadOffUniform, 0.0005);
+	}
+
 	this.unsetShadowMode = function() {
 		this.nitroShader = shaders[0];
 		gl.useProgram(this.nitroShader);
@@ -384,7 +389,7 @@ function nitroModel(bmd, btx, remap) {
 	}
 
 	if (remap != null) {
-		setTextureRemap(remap)
+		setTextureRemap(remap);
 	}
 
 	if (btx != null) {
diff --git a/code/render/nitroShaders.js b/code/render/nitroShaders.js
index 9b9fe37..2ecd22a 100644
--- a/code/render/nitroShaders.js
+++ b/code/render/nitroShaders.js
@@ -16,9 +16,39 @@ window.nitroShaders = new (function() {
 	\n\
 	uniform sampler2D uSampler;\n\
 	\n\
+	float indexValue() {\n\
+	    int x = int(mod(gl_FragCoord.x, 4.0));\n\
+	    int y = int(mod(gl_FragCoord.y, 4.0));\n\
+	    int i = (x + y * 4);\n\
+	    if (i == 0) return 0.0;\n\
+	    else if (i == 1) return 8.0;\n\
+	    else if (i == 2) return 2.0;\n\
+	    else if (i == 3) return 10.0;\n\
+	    else if (i == 4) return 12.0;\n\
+	    else if (i == 5) return 4.0;\n\
+	    else if (i == 6) return 14.0;\n\
+	    else if (i == 7) return 6.0;\n\
+	    else if (i == 8) return 3.0;\n\
+	    else if (i == 9) return 11.0;\n\
+	    else if (i == 10) return 1.0;\n\
+	    else if (i == 11) return 9.0;\n\
+	    else if (i == 12) return 15.0;\n\
+	    else if (i == 13) return 7.0;\n\
+	    else if (i == 14) return 13.0;\n\
+	    else if (i == 15) return 5.0;\n\
+	}\n\
+	\n\
+	float dither(float color) {\n\
+	    float closestColor = (color < 0.5) ? 0.0 : 1.0;\n\
+	    float secondClosestColor = 1.0 - closestColor;\n\
+	    float d = indexValue();\n\
+	    float distance = abs(closestColor - color);\n\
+	    return (distance < d) ? closestColor : secondClosestColor;\n\
+	}\n\
+	\n\
 	void main(void) {\n\
 		gl_FragColor = texture2D(uSampler, vTextureCoord)*color;\n\
-		if (gl_FragColor.a == 0.0) discard;\n\
+		if (gl_FragColor.a < 1.0 && (gl_FragColor.a == 0.0 || dither(gl_FragColor.a) == 0.0)) discard;\n\
 	}"
 
 	this.defaultVert = "attribute vec3 aVertexPosition;\n\
@@ -62,20 +92,20 @@ window.nitroShaders = new (function() {
 	\n\
 	uniform sampler2D uSampler;\n\
 	\n\
-	float shadowCompare(sampler2D map, vec2 pos, float compare) {\n\
+	float shadowCompare(sampler2D map, vec2 pos, float compare, float so) {\n\
 		float depth = texture2D(map, pos).r;\n\
-		return step(compare, depth);\n\
+		return smoothstep(compare-so, compare, depth);\n\
 	}\n\
 	\n\
-	float shadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare){\n\
+	float shadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare, float so){\n\
 		vec2 texelSize = vec2(1.0)/size;\n\
 		vec2 f = fract(uv*size+0.5);\n\
 		vec2 centroidUV = floor(uv*size+0.5)/size;\n\
 		\n\
-		float lb = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare);\n\
-		float lt = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare);\n\
-		float rb = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare);\n\
-		float rt = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare);\n\
+		float lb = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare, so);\n\
+		float lt = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare, so);\n\
+		float rb = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare, so);\n\
+		float rt = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare, so);\n\
 		float a = mix(lb, lt, f.y);\n\
 		float b = mix(rb, rt, f.y);\n\
 		float c = mix(a, b, f.x);\n\
@@ -89,14 +119,14 @@ window.nitroShaders = new (function() {
 		float dist = max(ldNorm.x, ldNorm.y);\n\
 		\n\
 		if (dist > 0.5) {\n\
-			gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff));\n\
+			gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*2.0));\n\
 		} else if (dist > 0.4) {\n\
-			float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff);\n\
-			float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff);\n\
+			float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*2.0);\n\
+			float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*4.0);\n\
 			\n\
 			gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), mix(lerp2, lerp1, (dist-0.4)*10.0));\n\
 		} else {\n\
-			gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff));\n\
+			gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*4.0));\n\
 		}\n\
 		\n\
 		if (gl_FragColor.a == 0.0) discard;\n\
@@ -118,6 +148,7 @@ window.nitroShaders = new (function() {
 	\n\
 	uniform mat4 shadowMat;\n\
 	uniform mat4 farShadowMat;\n\
+	uniform float lightIntensity; \n\
 	\n\
 	varying vec2 vTextureCoord;\n\
 	varying vec4 color;\n\
@@ -133,7 +164,7 @@ window.nitroShaders = new (function() {
 		lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
 		fLightDist = (farShadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
 		vec3 adjNorm = normalize(vec3(uMVMatrix * matStack[int(matrixID)] * vec4(aNormal, 0.0)));\n\
-		float diffuse = 0.7-dot(adjNorm, vec3(0.0, -1.0, 0.0))*0.3;\n\
+		float diffuse = (1.0-lightIntensity)-dot(adjNorm, vec3(0.0, -1.0, 0.0))*lightIntensity;\n\
 		\n\
 		color = aColor*colMult;\n\
 		color = vec4(color.x*diffuse, color.y*diffuse, color.z*diffuse, color.w);\n\
@@ -270,6 +301,7 @@ window.nitroShaders = new (function() {
 	var shadUnif = [
 		["shadowMatUniform", "shadowMat"],
 		["farShadowMatUniform", "farShadowMat"],
+		["lightIntensityUniform", "lightIntensity"],
 
 		["shadOffUniform", "shadOff"],
 		["farShadOffUniform", "farShadOff"],
diff --git a/index.html b/index.html
index dcf0e9a..c75cc23 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-

	
	
	
	
	

	

	
	
	
	
	
	

	

	
	
	

	
	
	

	
	
	
	

	

	

	
	
	
	
	
	
	
	

	

	
	

	

	

	
	
	
	
	
	
	
	
	
	

	
	
	

	
	
	
	

	

	
	
	
	
	
	
	
	

	

	





	
	

	


\ No newline at end of file
+

	
	
	
	
	

	

	
	
	
	
	
	

	

	
	
	

	
	
	

	
	
	
	

	

	

	
	
	
	
	
	
	
	

	
	
	

	
	

	

	

	
	
	
	
	
	
	
	
	
	

	
	
	

	
	
	
	

	

	
	
	
	
	
	
	
	

	

	





	
	

	


\ No newline at end of file

From 5f89b4518bcebb6c4c27f15d83f6d7998b267074 Mon Sep 17 00:00:00 2001
From: RHY3756547 
Date: Sun, 25 Mar 2018 16:08:09 +0100
Subject: [PATCH 2/4] More race stuff

- Loop track type
- Simple respawn when falling off track
- col limit
---
 code/engine/cameras/cameraIngame.js    |  20 +++-
 code/engine/controls/controlRaceCPU.js |  27 ++++-
 code/entities/kart.js                  | 134 ++++++++++++++++++++++---
 index.html                             |   2 +-
 4 files changed, 163 insertions(+), 20 deletions(-)

diff --git a/code/engine/cameras/cameraIngame.js b/code/engine/cameras/cameraIngame.js
index eaaf0ab..b28562c 100644
--- a/code/engine/cameras/cameraIngame.js
+++ b/code/engine/cameras/cameraIngame.js
@@ -42,7 +42,14 @@ window.cameraIngame = function(kart) {
 		camNormal[2] += (kart.kartNormal[2]-camNormal[2])*0.075;
 		vec3.normalize(camNormal, camNormal);
 
-		camAngle += dirDiff(kart.physicalDir+kart.driftOff/2, camAngle)*0.075;
+		if (kart.physBasis != null) {
+			var kartA = kart.physicalDir+kart.driftOff/2;
+			var forward = [Math.sin(kartA), 0, -Math.cos(kartA)];
+			vec3.transformMat4(forward, forward, kart.physBasis.mat);
+			camAngle += dirDiff(Math.atan2(forward[0], -forward[2]), camAngle)*0.075;
+		} else {
+			camAngle += dirDiff(kart.physicalDir+kart.driftOff/2, camAngle)*0.075;
+		}
 		camAngle = fixDir(camAngle);
 
 		boostOff += (((kart.boostNorm+kart.boostMT > 0)?5:0) - boostOff)*0.075
@@ -59,7 +66,16 @@ window.cameraIngame = function(kart) {
 
 	function buildBasis() {
 		//order y, x, z
-		var basis = gramShmidt(camNormal, [Math.cos(camAngle), 0, Math.sin(camAngle)], [Math.sin(camAngle), 0, -Math.cos(camAngle)]);
+		var kart = thisObj.kart;
+		var forward = [Math.sin(camAngle), 0, -Math.cos(camAngle)];
+		var side = [Math.cos(camAngle), 0, Math.sin(camAngle)];
+		/*
+		if (kart.physBasis != null) {
+			vec3.transformMat4(forward, forward, kart.physBasis.mat);
+			vec3.transformMat4(side, side, kart.physBasis.mat);
+		}
+		*/
+		var basis = gramShmidt(camNormal, side, forward);
 		var temp = basis[0];
 		basis[0] = basis[1];
 		basis[1] = temp; //todo: cleanup
diff --git a/code/engine/controls/controlRaceCPU.js b/code/engine/controls/controlRaceCPU.js
index 4747122..adc1156 100644
--- a/code/engine/controls/controlRaceCPU.js
+++ b/code/engine/controls/controlRaceCPU.js
@@ -19,6 +19,7 @@ window.controlRaceCPU = function(nkm) {
 	}
 
 	this.fetchInput = fetchInput;
+	this.setRouteID = setRouteID;
 
 	var battleMode = (nkm.sections["EPAT"] == null);
 
@@ -53,11 +54,30 @@ window.controlRaceCPU = function(nkm) {
 
 		var dist = vec3.dot(destNorm, kart.pos) + destConst;
 		if (dist < ePoi.pointSize) advancePoint();
+		if (ePath.loop) debugger;
 
 		destPoint = vec3.add([], ePoi.pos, vec3.scale([], vec3.lerp([], posOffset, destOff, offTrans), ePoi.pointSize));
 		var dirToPt = Math.atan2(destPoint[0]-kart.pos[0], kart.pos[2]-destPoint[2]);
 
-		var diff = dirDiff(dirToPt, kart.physicalDir);
+		var physDir = kart.physicalDir;
+		if (kart.physBasis) {
+			if (kart.physBasis.loop) { 
+				return {
+					accel: true, //x
+					decel: false, //z
+					drift: false, //s
+					item: false, //a
+
+					//-1 to 1, intensity.
+					turn: 0,
+					airTurn: 0 //air excitebike turn, doesn't really have much function
+				};
+			}
+			var forward = [Math.sin(physDir), 0, -Math.cos(physDir)];
+			vec3.transformMat4(forward, forward, kart.physBasis.mat);
+			var physDir = Math.atan2(forward[0], -forward[2]);
+		}
+		var diff = dirDiff(dirToPt, physDir);
 		var turn = Math.min(Math.max(-1, (diff*3)), 1);
 
 		offTrans += 1/240;
@@ -94,6 +114,11 @@ window.controlRaceCPU = function(nkm) {
 
 	}
 
+	function setRouteID(routeID) {
+		ePoiInd = routeID-1
+		advancePoint();
+	}
+
 	function advancePoint() {
 		if (++ePoiInd < ePath.startInd+ePath.pathLen) {
 			//next within this path
diff --git a/code/entities/kart.js b/code/entities/kart.js
index 3583165..89b46a3 100644
--- a/code/entities/kart.js
+++ b/code/entities/kart.js
@@ -72,6 +72,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 
 	this.kartColVel = vec3.create();
 	this.kartColTimer = 0;
+	this.kartWallTimer = 0;
 
 	var charRes = scene.gameRes.getChar(charN);
 	var kartRes = scene.gameRes.getKart(kartN);
@@ -98,6 +99,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 	this.lapNumber = 1;
 	this.passedKTP2 = false;
 	this.checkPointNumber = 0;
+	this.OOB = 0;
 
 	this.wheelParticles = [
 		new NitroEmitter(scene, k, -1, [1, 1.5, -1]),
@@ -111,7 +113,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 	var startLine = nkm.sections["KTPS"].entries[0];
 	var passLine = nkm.sections["KTP2"].entries[0];
 	var checkpoints = nkm.sections["CPOI"].entries;
-	var respawns = nkm.sections["CPOI"].entries;
+	var respawns = nkm.sections["KTPJ"].entries;
 	var futureChecks = [1];
 
 	var hitGroundAnim = [ //length 13, on y axis
@@ -403,6 +405,17 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 			}
 		} else { //default kart mode
 
+			if (k.OOB > 0) {
+				var current = checkpoints[k.checkPointNumber];
+				var respawn = respawns[current.respawn];
+				k.physicalDir = (180-respawn.angle[1])*(Math.PI/180);
+				k.angle = k.physicalDir;
+				k.speed = 0;
+				k.vel = vec3.create();
+				k.pos = vec3.clone(respawn.pos);
+				if (k.controller.setRouteID != null) k.controller.setRouteID(respawn.id1);
+				k.OOB = 0;
+			}
 			var groundEffect = 0;
 			if (lastCollided != -1) {
 				groundEffect = MKDS_COLTYPE.PHYS_MAP[lastCollided];
@@ -608,6 +621,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 
 			if (!onGround) {
 				this.kartTargetNormal = [0, 1, 0];
+				if (k.physBasis != null) vec3.transformMat4(this.kartTargetNormal,this.kartTargetNormal,k.physBasis.mat);
 				vec3.add(k.vel, k.vel, k.gravity)
 				if (k.ylock >= 0) {
 					ylvel += k.gravity[1];
@@ -630,6 +644,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 			}
 
 			if (k.kartColTimer > 0) k.kartColTimer--;
+			if (k.kartWallTimer > 0) k.kartWallTimer--;
 
 			wheelTurn += k.speed/16;
 			wheelTurn = fixDir(wheelTurn);
@@ -648,7 +663,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 
 			var steps = 0;
 			var remainingT = 1;
-			var velSeg = vec3.clone(k.vel);
+			var baseVel = k.vel;
+			if (k.physBasis != null) {
+				if (k.physBasis.time-- < 0) exitBasis();
+				else {
+					baseVel = vec3.transformMat4([], baseVel, k.physBasis.mat);
+					k.vel[1] = -1;
+				}
+			}
+			var velSeg = vec3.clone(baseVel);
 			var posSeg = vec3.clone(k.pos);
 			var ignoreList = [];
 			while (steps++ < 10 && remainingT > 0.01) {
@@ -657,7 +680,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 					colResponse(posSeg, velSeg, result, ignoreList)
 					remainingT -= result.t;
 					if (remainingT > 0.01) {
-						velSeg = vec3.scale(vec3.create(), k.vel, remainingT);
+						if (k.physBasis != null) {
+							baseVel = vec3.transformMat4([], k.vel, k.physBasis.mat);
+						}
+						velSeg = vec3.scale(vec3.create(), baseVel, remainingT);
 					}
 				} else {
 					vec3.add(posSeg, posSeg, velSeg);
@@ -834,7 +860,13 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 	function buildBasis() {
 		//order y, x, z
 		var dir = k.physicalDir+k.driftOff+(Math.sin((COLBOUNCE_TIME-k.kartColTimer)/3)*(Math.PI/6)*(k.kartColTimer/COLBOUNCE_TIME));
-		var basis = gramShmidt(k.kartNormal, [Math.cos(dir), 0, Math.sin(dir)], [Math.sin(dir), 0, -Math.cos(dir)]);
+		var forward = [Math.sin(dir), 0, -Math.cos(dir)];
+		var side = [Math.cos(dir), 0, Math.sin(dir)];
+		if (k.physBasis != null) {
+			vec3.transformMat4(forward, forward, k.physBasis.mat);
+			vec3.transformMat4(side, side, k.physBasis.mat);
+		}
+		var basis = gramShmidt(k.kartNormal, side, forward);
 		var temp = basis[0];
 		basis[0] = basis[1];
 		basis[1] = temp; //todo: cleanup
@@ -847,6 +879,56 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 
 	}
 
+	function enterBasis(normal) {
+		//establish a new basis for the kart velocity based on this normal.
+		//used by looping and sticky track surface types.
+
+		//first let's get the forward direction in our current basis
+
+		var dir = k.angle;
+		var forward, side;
+		if (k.physBasis != null) {
+			forward = vec3.transformMat4([], [-	Math.sin(dir), 0, Math.cos(dir)], k.physBasis.mat);
+			side = vec3.transformMat4([], [Math.cos(dir), 0, Math.sin(dir)], k.physBasis.mat);
+		} else {
+			forward = [-Math.sin(dir), 0, Math.cos(dir)];
+			side = [Math.cos(dir), 0, Math.sin(dir)];
+		}
+		
+		var basis = gramShmidt(normal, side, forward);
+		var temp = basis[0];
+		basis[0] = basis[1];
+		basis[1] = temp; //todo: cleanup
+		var m4 = [
+			basis[0][0], basis[0][1], basis[0][2], 0,
+			basis[1][0], basis[1][1], basis[1][2], 0,
+			basis[2][0], basis[2][1], basis[2][2], 0,
+			0, 0, 0, 1			
+		];
+
+		k.physicalDir = dirDiff(k.physicalDir, k.angle);
+		k.angle = 0; //our front direction is now aligned with z.
+		k.vel = [Math.sin(k.angle)*k.speed, k.vel[1], -Math.cos(k.angle)*k.speed];
+
+		k.physBasis = {
+			mat: m4,
+			inv: mat4.invert([], m4),
+			time: 15,
+			loop: false
+		};
+	}
+
+	function exitBasis() {
+		//return to a normal y up, z forward basis.
+
+		var v = vec3.transformMat4([], k.vel, k.physBasis.mat);
+		k.physicalDir = dirDiff(k.physicalDir, k.angle);
+		k.angle = Math.atan2(v[0], -v[2]);
+		k.physicalDir += k.angle;
+		k.vel = v;
+		k.physBasis = null;
+	}
+
 	function sndUpdate(view) {
 		k.soundProps.pos = vec3.transformMat4([], k.pos, view);
 		if (k.soundProps.lastPos != null) k.soundProps.vel = vec3.sub([], k.soundProps.pos, k.soundProps.lastPos);
@@ -892,24 +974,34 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 		lastColSounds = colSound(lastCollided, colBE);
 
 		var n = vec3.normalize([], dat.normal);
+		var an = n;
+		if (k.physBasis != null) {
+			an = vec3.transformMat4([], n, k.physBasis.inv);
+		}
 		var gravS = Math.sqrt(vec3.dot(k.gravity, k.gravity));
 		var angle = Math.acos(vec3.dot(vec3.scale(vec3.create(), k.gravity, -1/gravS), n));
 		var adjustPos = true;
 
+		if (colType == MKDS_COLTYPE.OOB || colType == MKDS_COLTYPE.FALL) {
+			k.OOB = 1;
+		}
+
 		if (MKDS_COLTYPE.GROUP_WALL.indexOf(colType) != -1) { //wall
 			//sliding plane, except normal is transformed to be entirely on the xz plane (cannot ride on top of wall, treated as vertical)
-			var xz = Math.sqrt(n[0]*n[0]+n[2]*n[2])
-			var adjN = [n[0]/xz, 0, n[2]/xz]
+			var xz = Math.sqrt(an[0]*an[0]+an[2]*an[2])
+			var adjN = [an[0]/xz, 0, an[2]/xz]
 			var proj = vec3.dot(k.vel, adjN);
 
 			if (proj < -1) { 
-				if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k) 
-				var colObj = {pos:pos, vel:[0,0,0], mat: mat4.fromTranslation([], pos)};
-				scene.particles.push(new NitroEmitter(scene, colObj, 13));
-				scene.particles.push(new NitroEmitter(scene, colObj, 14));
+				if (k.kartWallTimer == 0) {
+					if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k) 
+					var colObj = {pos:pos, vel:[0,0,0], mat: mat4.fromTranslation([], pos)};
+					scene.particles.push(new NitroEmitter(scene, colObj, 13));
+					scene.particles.push(new NitroEmitter(scene, colObj, 14));
+				}
+				k.kartWallTimer = 15;
 			}
-			vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), adjN, proj));
-
+			vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), adjN, proj)); 
 			
 
 			//convert back to angle + speed to keep change to kart vel
@@ -923,10 +1015,21 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 				k.boostNorm = BOOSTTIME;
 			}
 
+			var stick = (colType == MKDS_COLTYPE.STICKY || colType == MKDS_COLTYPE.LOOP); 
+
 			if (k.vel[1] > 0) k.vel[1] = 0;
-			var proj = vec3.dot(k.vel, n);
-			if (proj < -4 && k.vel[1] < -2) { proj -= 1.5; }
-			vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), n, proj));
+			var proj = vec3.dot(k.vel, an);
+			if (!stick && proj < -4 && k.vel[1] < -2) { proj -= 1.5; }
+			vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), an, proj));
+
+			if (stick) {
+				enterBasis(dat.pNormal);
+				k.physBasis.loop = colType == MKDS_COLTYPE.LOOP;
+			} else {
+				if (k.physBasis != null)
+					exitBasis();
+			}
+
 			k.kartTargetNormal = dat.pNormal;
 
 			if (change) {
@@ -937,7 +1040,6 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 					setWheelParticles(particle, 0);
 			}
 			if (!onGround) {
-				console.log("ground: "+colType+", "+colBE);
 				groundAnim = 0;
 				if (lastColSounds.land != null) nitroAudio.playSound(lastColSounds.land, {volume:1}, 0, k)
 			}
diff --git a/index.html b/index.html
index c75cc23..abecd07 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-

	
	
	
	
	

	

	
	
	
	
	
	

	

	
	
	

	
	
	

	
	
	
	

	

	

	
	
	
	
	
	
	
	

	
	
	

	
	

	

	

	
	
	
	
	
	
	
	
	
	

	
	
	

	
	
	
	

	

	
	
	
	
	
	
	
	

	

	





	
	

	


\ No newline at end of file
+

	
	
	
	
	

	

	
	
	
	
	
	

	

	
	
	

	
	
	

	
	
	
	

	

	

	
	
	
	
	
	
	
	

	
	
	

	
	

	

	

	
	
	
	
	
	
	
	
	
	

	
	
	

	
	
	
	

	

	
	
	
	
	
	
	
	

	

	





	
	

	


\ No newline at end of file

From a468a7b1896e7c0634f4f645e41fd46518dec870 Mon Sep 17 00:00:00 2001
From: RHY3756547 
Date: Sun, 25 Mar 2018 23:34:16 +0100
Subject: [PATCH 3/4] Character sounds, fixes to race position

Race position is still WIP, it screws up a lot around the finish line.
---
 code/engine/ingameRes.js          | 11 ++++--
 code/engine/scenes/courseScene.js | 16 ++++++---
 code/entities/kart.js             | 56 ++++++++++++++++++++++++++++---
 3 files changed, 72 insertions(+), 11 deletions(-)

diff --git a/code/engine/ingameRes.js b/code/engine/ingameRes.js
index 0a103e7..05de045 100644
--- a/code/engine/ingameRes.js
+++ b/code/engine/ingameRes.js
@@ -31,13 +31,19 @@ window.IngameRes = function(rom) {
 		"koura_w" /*blue shell item rep*/, "f_box", "killer" /*bullet bill*/
 	]
 
+	//order
+	//donkey, toad, bowser?, luigi, mario, peach, wario, yoshi, daisy, waluigi, dry bones (karon), robo, heyho
+	var toSoundOff = [
+		4, 0, 1, 2, 5, 6, 7, 3, 10, 8, 9, 11, 12
+	];
+
 	var charNames = [
 		"mario", "donkey", "kinopio", "koopa", "peach", "wario", "yoshi", "luigi", "karon", "daisy", "waluigi", "robo", "heyho"
-	]
+	];
 
 	var charAbbrv = [
 		"MR", "DK", "KO", "KP", "PC", "WR", "YS", "LG", "KA", "DS", "WL", "RB", "HH"
-	]
+	];
 
 	var tireName = ["kart_tire_L", "kart_tire_M", "kart_tire_S"];
 
@@ -75,6 +81,7 @@ window.IngameRes = function(rom) {
 			loseA: new nsbca(r.KartModelSub.getFile(base+"_lose.nsbca")),
 			spinA: new nsbca(r.KartModelSub.getFile(base+"_spin.nsbca")),
 			winA: new nsbca(r.KartModelSub.getFile(base+"_win.nsbca")),
+			sndOff: toSoundOff[ind]*14,
 		}
 		characters[ind] = obj;
 		return characters[ind];
diff --git a/code/engine/scenes/courseScene.js b/code/engine/scenes/courseScene.js
index 39353e8..19b8356 100644
--- a/code/engine/scenes/courseScene.js
+++ b/code/engine/scenes/courseScene.js
@@ -165,6 +165,11 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
 		vec3.scale(targ, targ, 1/1024);
 		mat4.mul(scn.shadMat, mat4.ortho(mat4.create(), targ[0]-shadres, targ[0]+shadres, targ[1]-shadres, targ[1]+shadres, -targ[2]-2.5, -targ[2]+2.5), scn.lightMat);
 
+		var places = [];
+		for (var i=0; i winPercent) continue;
 					finishTuple = finishPercents[i];
+					if (finishPercents[i][0] >= winPercent) break;
 				}
 
 				kart.controller = new controlRaceCPU(scn.nkm, {});
 				kart.controller.setKart(kart);
 
-				kart.anim.setAnim(winPercent>0.5?kart.charRes.LoseA:kart.charRes.winA);
+				kart.anim.setAnim(winPercent>0.5?kart.charRes.loseA:kart.charRes.winA);
 				kart.animMode = "raceEnd";
 
 				scn.camera = (new cameraSpectator(kart, scn));
 				nitroAudio.playSound(finishTuple[1], {volume:2}, 0);
 				nitroAudio.playSound(finishTuple[2], {volume:2}, null);
 				nitroAudio.instaKill(scn.musicPlayer);
+				kart.playCharacterSound(finishTuple[4], 2);
 				musicRestartTimer = 0;
 				musicRestart = 7.5*60;
 				musicRestartType = 1;
diff --git a/code/entities/kart.js b/code/entities/kart.js
index 89b46a3..180048b 100644
--- a/code/entities/kart.js
+++ b/code/entities/kart.js
@@ -21,6 +21,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 
 	var params = scene.gameRes.kartPhys.karts[kartN];
 	var offsets = scene.gameRes.kartOff.karts[kartN];
+	this.wheelClass = (offsets.name[10] == "L")?2:((offsets.name[10] == "M")?1:0);
 
 	this.local = controller.local;
 	this.active = true;
@@ -66,6 +67,9 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 	this.drawWheels = drawWheels;
 	this.drawChar = drawChar;
 
+	this.getPosition = getPosition;
+	this.playCharacterSound = playCharacterSound;
+
 	this.trackAttach = null; //a normal for the kart to attach to (loop)
 	this.boostMT = 0;
 	this.boostNorm = 0;
@@ -73,6 +77,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 	this.kartColVel = vec3.create();
 	this.kartColTimer = 0;
 	this.kartWallTimer = 0;
+	this.charSoundTimer = 0;
+
+	this.placement = 0;
+	this.lastPlacement = 0;
 
 	var charRes = scene.gameRes.getChar(charN);
 	var kartRes = scene.gameRes.getKart(kartN);
@@ -206,7 +214,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 			mat4.rotateX(wmat, wmat, wheelTurn);
 
 			if (i>1) {
-				k.wheelParticles[i-2].offset = vec3.scale(k.wheelParticles[i-2].offset, vec3.add(k.wheelParticles[i-2].offset, offsets.wheels[i], [0, -params.colRadius, 0]), 1/16);
+				k.wheelParticles[i-2].offset = vec3.scale(k.wheelParticles[i-2].offset, vec3.add(k.wheelParticles[i-2].offset, offsets.wheels[i], [k.wheelClass*(i-2.5)*-2, (-params.colRadius)-k.wheelClass*2, 0]), 1/16);
 			}
 		}
 
@@ -281,6 +289,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 	k.lWheelParticle = null;
 
 	function update(scene) {
+		if (k.placement != k.lastPlacement) {
+			if (k.placement < k.lastPlacement) {
+				if (k.charSoundTimer == 0) {
+					playCharacterSound(5);
+					k.charSoundTimer = 60;
+				}
+			}
+			k.lastPlacement = k.placement;
+		}
 
 		var lastPos = vec3.clone(k.pos);
 		updateMat = true;
@@ -406,6 +423,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 		} else { //default kart mode
 
 			if (k.OOB > 0) {
+				playCharacterSound(0);
 				var current = checkpoints[k.checkPointNumber];
 				var respawn = respawns[current.respawn];
 				k.physicalDir = (180-respawn.angle[1])*(Math.PI/180);
@@ -413,6 +431,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 				k.speed = 0;
 				k.vel = vec3.create();
 				k.pos = vec3.clone(respawn.pos);
+				vec3.add(k.pos, k.pos, [0,16,0]);
 				if (k.controller.setRouteID != null) k.controller.setRouteID(respawn.id1);
 				k.OOB = 0;
 			}
@@ -645,6 +664,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 
 			if (k.kartColTimer > 0) k.kartColTimer--;
 			if (k.kartWallTimer > 0) k.kartWallTimer--;
+			if (k.charSoundTimer > 0) k.charSoundTimer--;
 
 			wheelTurn += k.speed/16;
 			wheelTurn = fixDir(wheelTurn);
@@ -714,8 +734,27 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 		positionChanged(lastPos, k.pos);
 	}
 
+	function playCharacterSound(sound, volume) {
+		//0 - hit
+		//1 - hit spin
+		//2 - hit ?? hit grnd
+		//3 - hit banana? race start?
+		//4 - hit spin?
+		//5 - good pass?
+		//6 - good OK!
+		//7 - use item
+		//8 - hit someone?
+		//9 = win
+		//10 = alright
+		//11 = bad
+		//12 = good record
+		//13 = bad record
+		if (volume == null) volume = 1;
+		nitroAudio.playSound(sound + charRes.sndOff, {volume: 2*volume}, 2, k);
+	}
+
 	function clearWheelParticles(prio) {
-		for (let i=0; i<2; i++) {
+		for (var i=0; i<2; i++) {
 			if (prio == null) {
 				//clear all specials
 				k.wheelParticles[i].clearEmitter(1); //drift mode
@@ -727,7 +766,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 	}
 
 	function setWheelParticles(id, prio) {
-		for (let i=0; i<2; i++) {
+		for (var i=0; i<2; i++) {
 			k.wheelParticles[i].setEmitter(id, prio);
 		}
 	}
@@ -782,6 +821,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 		}
 	}
 
+	function getPosition() {
+		if (futureChecks.length == 0) return 0;
+		var check = checkpoints[futureChecks[0]];
+		var dist = vec2.sub([], [check.x1, check.z1], [k.pos[0], k.pos[2]]);
+		var dot = vec2.dot(dist, [check.sinus, check.cosinus]);
+
+		return k.checkPointNumber + (1-(Math.abs(dot)/(0xFFFF))) + k.lapNumber*checkpoints.length;
+	}
+
 	function forwardCrossedKTP(ktp, oldPos, pos) {
 		var distOld = vec2.sub([], [ktp.pos[0], ktp.pos[2]], [oldPos[0], oldPos[2]]);
 		var dist = vec2.sub([], [ktp.pos[0], ktp.pos[2]], [pos[0], pos[2]]);
@@ -1039,7 +1087,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
 				else
 					setWheelParticles(particle, 0);
 			}
-			if (!onGround) {
+			if (!onGround && !stick) {
 				groundAnim = 0;
 				if (lastColSounds.land != null) nitroAudio.playSound(lastColSounds.land, {volume:1}, 0, k)
 			}

From 52fba675e823b20bea5e8578100f7ac227eb2f26 Mon Sep 17 00:00:00 2001
From: RHY3756547 
Date: Sun, 25 Mar 2018 23:41:51 +0100
Subject: [PATCH 4/4] Make uniformly ES5

---
 code/formats/spa.js             | 20 ++++++++++----------
 code/particles/nitroParticle.js |  4 ++--
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/code/formats/spa.js b/code/formats/spa.js
index 2b9abc5..c1a6dee 100644
--- a/code/formats/spa.js
+++ b/code/formats/spa.js
@@ -38,7 +38,7 @@ window.spa = function(input) {
         offset += 24;
         if (version == "12_1") {
             t.particles = [];
-            for (let i=0; i