!function(e){function r(e,r,o){return 4===arguments.length?t.apply(this,arguments):void n(e,{declarative:!0,deps:r,declare:o})}function t(e,r,t,o){n(e,{declarative:!1,deps:r,executingRequire:t,execute:o})}function n(e,r){r.name=e,e in v||(v[e]=r),r.normalizedDeps=r.deps}function o(e,r){if(r[e.groupIndex]=r[e.groupIndex]||[],-1==g.call(r[e.groupIndex],e)){r[e.groupIndex].push(e);for(var t=0,n=e.normalizedDeps.length;n>t;t++){var a=e.normalizedDeps[t],u=v[a];if(u&&!u.evaluated){var d=e.groupIndex+(u.declarative!=e.declarative);if(void 0===u.groupIndex||u.groupIndex<d){if(void 0!==u.groupIndex&&(r[u.groupIndex].splice(g.call(r[u.groupIndex],u),1),0==r[u.groupIndex].length))throw new TypeError("Mixed dependency cycle detected");u.groupIndex=d}o(u,r)}}}}function a(e){var r=v[e];r.groupIndex=0;var t=[];o(r,t);for(var n=!!r.declarative==t.length%2,a=t.length-1;a>=0;a--){for(var u=t[a],i=0;i<u.length;i++){var s=u[i];n?d(s):l(s)}n=!n}}function u(e){return y[e]||(y[e]={name:e,dependencies:[],exports:{},importers:[]})}function d(r){if(!r.module){var t=r.module=u(r.name),n=r.module.exports,o=r.declare.call(e,function(e,r){if(t.locked=!0,"object"==typeof e)for(var o in e)n[o]=e[o];else n[e]=r;for(var a=0,u=t.importers.length;u>a;a++){var d=t.importers[a];if(!d.locked)for(var i=0;i<d.dependencies.length;++i)d.dependencies[i]===t&&d.setters[i](n)}return t.locked=!1,r},{id:r.name});t.setters=o.setters,t.execute=o.execute;for(var a=0,i=r.normalizedDeps.length;i>a;a++){var l,s=r.normalizedDeps[a],c=v[s],f=y[s];f?l=f.exports:c&&!c.declarative?l=c.esModule:c?(d(c),f=c.module,l=f.exports):l=p(s),f&&f.importers?(f.importers.push(t),t.dependencies.push(f)):t.dependencies.push(null),t.setters[a]&&t.setters[a](l)}}}function i(e){var r,t=v[e];if(t)t.declarative?f(e,[]):t.evaluated||l(t),r=t.module.exports;else if(r=p(e),!r)throw new Error("Unable to load dependency "+e+".");return(!t||t.declarative)&&r&&r.__useDefault?r["default"]:r}function l(r){if(!r.module){var t={},n=r.module={exports:t,id:r.name};if(!r.executingRequire)for(var o=0,a=r.normalizedDeps.length;a>o;o++){var u=r.normalizedDeps[o],d=v[u];d&&l(d)}r.evaluated=!0;var c=r.execute.call(e,function(e){for(var t=0,n=r.deps.length;n>t;t++)if(r.deps[t]==e)return i(r.normalizedDeps[t]);throw new TypeError("Module "+e+" not declared as a dependency.")},t,n);void 0!==c&&(n.exports=c),t=n.exports,t&&t.__esModule?r.esModule=t:r.esModule=s(t)}}function s(r){var t={};if(("object"==typeof r||"function"==typeof r)&&r!==e)if(m)for(var n in r)"default"!==n&&c(t,r,n);else{var o=r&&r.hasOwnProperty;for(var n in r)"default"===n||o&&!r.hasOwnProperty(n)||(t[n]=r[n])}return t["default"]=r,x(t,"__useDefault",{value:!0}),t}function c(e,r,t){try{var n;(n=Object.getOwnPropertyDescriptor(r,t))&&x(e,t,n)}catch(o){return e[t]=r[t],!1}}function f(r,t){var n=v[r];if(n&&!n.evaluated&&n.declarative){t.push(r);for(var o=0,a=n.normalizedDeps.length;a>o;o++){var u=n.normalizedDeps[o];-1==g.call(t,u)&&(v[u]?f(u,t):p(u))}n.evaluated||(n.evaluated=!0,n.module.execute.call(e))}}function p(e){if(I[e])return I[e];if("@node/"==e.substr(0,6))return I[e]=s(D(e.substr(6)));var r=v[e];if(!r)throw"Module "+e+" not present.";return a(e),f(e,[]),v[e]=void 0,r.declarative&&x(r.module.exports,"__esModule",{value:!0}),I[e]=r.declarative?r.module.exports:r.esModule}var v={},g=Array.prototype.indexOf||function(e){for(var r=0,t=this.length;t>r;r++)if(this[r]===e)return r;return-1},m=!0;try{Object.getOwnPropertyDescriptor({a:0},"a")}catch(h){m=!1}var x;!function(){try{Object.defineProperty({},"a",{})&&(x=Object.defineProperty)}catch(e){x=function(e,r,t){try{e[r]=t.value||t.get.call(e)}catch(n){}}}}();var y={},D="undefined"!=typeof System&&System._nodeRequire||"undefined"!=typeof require&&"undefined"!=typeof require.resolve&&"undefined"!=typeof process&&process.platform&&require,I={"@empty":{}};return function(e,n,o,a){return function(u){u(function(u){for(var d={_nodeRequire:D,register:r,registerDynamic:t,get:p,set:function(e,r){I[e]=r},newModule:function(e){return e}},i=0;i<n.length;i++)(function(e,r){r&&r.__esModule?I[e]=r:I[e]=s(r)})(n[i],arguments[i]);a(d);var l=p(e[0]);if(e.length>1)for(var i=1;i<e.length;i++)p(e[i]);return o?l["default"]:l})}}}("undefined"!=typeof self?self:global)

(["1"], [], false, function($__System) {
var require = this.require, exports = this.exports, module = this.module;
!function(e){function n(e,n){e=e.replace(l,"");var r=e.match(u),t=(r[1].split(",")[n]||"require").replace(s,""),i=p[t]||(p[t]=new RegExp(a+t+f,"g"));i.lastIndex=0;for(var o,c=[];o=i.exec(e);)c.push(o[2]||o[3]);return c}function r(e,n,t,o){if("object"==typeof e&&!(e instanceof Array))return r.apply(null,Array.prototype.splice.call(arguments,1,arguments.length-1));if("string"==typeof e&&"function"==typeof n&&(e=[e]),!(e instanceof Array)){if("string"==typeof e){var l=i.get(e);return l.__useDefault?l["default"]:l}throw new TypeError("Invalid require")}for(var a=[],f=0;f<e.length;f++)a.push(i["import"](e[f],o));Promise.all(a).then(function(e){n&&n.apply(null,e)},t)}function t(t,l,a){"string"!=typeof t&&(a=l,l=t,t=null),l instanceof Array||(a=l,l=["require","exports","module"].splice(0,a.length)),"function"!=typeof a&&(a=function(e){return function(){return e}}(a)),void 0===l[l.length-1]&&l.pop();var f,u,s;-1!=(f=o.call(l,"require"))&&(l.splice(f,1),t||(l=l.concat(n(a.toString(),f)))),-1!=(u=o.call(l,"exports"))&&l.splice(u,1),-1!=(s=o.call(l,"module"))&&l.splice(s,1);var p={name:t,deps:l,execute:function(n,t,o){for(var p=[],c=0;c<l.length;c++)p.push(n(l[c]));o.uri=o.id,o.config=function(){},-1!=s&&p.splice(s,0,o),-1!=u&&p.splice(u,0,t),-1!=f&&p.splice(f,0,function(e,t,l){return"string"==typeof e&&"function"!=typeof t?n(e):r.call(i,e,t,l,o.id)});var d=a.apply(-1==u?e:t,p);return"undefined"==typeof d&&o&&(d=o.exports),"undefined"!=typeof d?d:void 0}};if(t)c.anonDefine||c.isBundle?c.anonDefine&&c.anonDefine.name&&(c.anonDefine=null):c.anonDefine=p,c.isBundle=!0,i.registerDynamic(p.name,p.deps,!1,p.execute);else{if(c.anonDefine&&!c.anonDefine.name)throw new Error("Multiple anonymous defines in module "+t);c.anonDefine=p}}var i=$__System,o=Array.prototype.indexOf||function(e){for(var n=0,r=this.length;r>n;n++)if(this[n]===e)return n;return-1},l=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/gm,a="(?:^|[^$_a-zA-Z\\xA0-\\uFFFF.])",f="\\s*\\(\\s*(\"([^\"]+)\"|'([^']+)')\\s*\\)",u=/\(([^\)]*)\)/,s=/^\s+|\s+$/g,p={};t.amd={};var c={isBundle:!1,anonDefine:null};i.amdDefine=t,i.amdRequire=r}("undefined"!=typeof self?self:global);
$__System.register('2', ['3', '4', '5'], function (_export) {
	var THREE, _createClass, _classCallCheck, _default;

	return {
		setters: [function (_3) {
			THREE = _3;
		}, function (_) {
			_createClass = _['default'];
		}, function (_2) {
			_classCallCheck = _2['default'];
		}],
		execute: function () {
			'use strict';

			_default = (function () {
				function _default(width, height, format, type) {
					_classCallCheck(this, _default);

					this.renderTextures = [];
					this.current = 0;
					this.count = 2;
					width = width || window.innerWidth;
					height = height || window.innerHeight;
					format = format || THREE.RGBAFormat;
					type = type || THREE.UnsignedByteType;

					for (var i = 0; i < this.count; ++i) {
						this.renderTextures.push(new THREE.WebGLRenderTarget(width, height, {
							minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: format, type: type }));
					}
				}

				_createClass(_default, [{
					key: 'getTarget',
					value: function getTarget() {
						return this.renderTextures[this.current];
					}
				}, {
					key: 'getTexture',
					value: function getTexture() {
						return this.renderTextures[this.current].texture;
					}
				}, {
					key: 'swap',
					value: function swap() {
						this.current = (this.current + 1) % this.count;
					}
				}, {
					key: 'resize',
					value: function resize(width, height) {
						for (var i = 0; i < this.renderTextures.length; ++i) {
							this.renderTextures[i].setSize(width, height);
						}
					}
				}]);

				return _default;
			})();

			_export('default', _default);
		}
	};
});

$__System.register("6", [], function (_export) {
	"use strict";

	return {
		setters: [],
		execute: function () {
			_export("default", {
				show: {
					blendLine: 1.,
					blendRaymarch: 0.,
					blendBubble: 0.,
					blendBubble1: 0.,
					blendText: 1.,
					blendTextIn: 0.,
					blendTextOut: 0.,
					blendPaper: 0.,
					blendGlitch: 0.,
					blendBlack: 0.
				}
			});
		}
	};
});

$__System.register('7', ['3', '4', '5', '8', '9', 'a', 'b'], function (_export) {
	var THREE, _createClass, _classCallCheck, _get, _inherits, assets, Scene, FilterScene;

	return {
		setters: [function (_5) {
			THREE = _5;
		}, function (_3) {
			_createClass = _3['default'];
		}, function (_4) {
			_classCallCheck = _4['default'];
		}, function (_) {
			_get = _['default'];
		}, function (_2) {
			_inherits = _2['default'];
		}, function (_a) {
			assets = _a['default'];
		}, function (_b) {
			Scene = _b['default'];
		}],
		execute: function () {
			'use strict';

			FilterScene = (function (_Scene) {
				_inherits(FilterScene, _Scene);

				function FilterScene() {
					_classCallCheck(this, FilterScene);

					_get(Object.getPrototypeOf(FilterScene.prototype), 'constructor', this).call(this);
					this.scene = new THREE.Mesh(new THREE.PlaneGeometry(1, 1, 1), assets.shaderMaterials.filter);
				}

				_createClass(FilterScene, [{
					key: 'update',
					value: function update(elapsed) {
						_get(Object.getPrototypeOf(FilterScene.prototype), 'update', this).call(this, elapsed);
					}
				}]);

				return FilterScene;
			})(Scene);

			_export('default', FilterScene);
		}
	};
});

$__System.register('c', ['3', '4', '5', '8', '9', 'a', 'd', 'b'], function (_export) {
	var THREE, _createClass, _classCallCheck, _get, _inherits, assets, renderer, Scene, RaymarchingScene;

	return {
		setters: [function (_5) {
			THREE = _5;
		}, function (_3) {
			_createClass = _3['default'];
		}, function (_4) {
			_classCallCheck = _4['default'];
		}, function (_) {
			_get = _['default'];
		}, function (_2) {
			_inherits = _2['default'];
		}, function (_a) {
			assets = _a['default'];
		}, function (_d) {
			renderer = _d['default'];
		}, function (_b) {
			Scene = _b['default'];
		}],
		execute: function () {
			'use strict';

			RaymarchingScene = (function (_Scene) {
				_inherits(RaymarchingScene, _Scene);

				function RaymarchingScene() {
					_classCallCheck(this, RaymarchingScene);

					_get(Object.getPrototypeOf(RaymarchingScene.prototype), 'constructor', this).call(this);
					this.scene = new THREE.Mesh(new THREE.PlaneGeometry(1, 1, 1), assets.shaderMaterials.raymarching);
				}

				_createClass(RaymarchingScene, [{
					key: 'update',
					value: function update(elapsed) {
						_get(Object.getPrototypeOf(RaymarchingScene.prototype), 'update', this).call(this, elapsed);
					}
				}]);

				return RaymarchingScene;
			})(Scene);

			_export('default', RaymarchingScene);
		}
	};
});

$__System.register('e', [], function (_export) {
	'use strict';

	_export('simpleText', simpleText);

	function simpleText(message, font, fontSize, resolution, center) {
		font = font || 'arial';
		font = fontSize + 'px ' + font;
		var ctx = document.createElement('canvas').getContext('2d');
		ctx.font = font;
		ctx.canvas.width = resolution;
		ctx.canvas.height = resolution;
		ctx.font = font;
		ctx.fillStyle = 'red';
		ctx.lineWidth = 2.;
		ctx.strokeStyle = 'white';
		ctx.textAlign = 'center';
		ctx.textBaseline = 'middle';
		ctx.shadowColor = "rgba(0,0,0,1.)";
		ctx.shadowBlur = 4;

		var words = message.split('\n');
		var line = '';

		var x = ctx.canvas.width / 2;
		var y = ctx.canvas.height / 2;

		if (!center) y = ctx.canvas.height - fontSize;
		y -= Math.max(0, words.length - 1) * fontSize / 2;

		for (var n = 0; n < words.length; n++) {
			line = words[n];
			ctx.fillText(line, x, y);
			ctx.strokeText(line, x, y);
			y += fontSize;
		}

		return ctx.canvas;
	}

	return {
		setters: [],
		execute: function () {}
	};
});

$__System.register('f', ['3', '4', '5', '8', '9', '10', '11', 'b', 'a', 'e'], function (_export) {
	var THREE, _createClass, _classCallCheck, _get, _inherits, Geometry, uniforms, Scene, assets, simpleText, TextScene;

	return {
		setters: [function (_5) {
			THREE = _5;
		}, function (_3) {
			_createClass = _3['default'];
		}, function (_4) {
			_classCallCheck = _4['default'];
		}, function (_) {
			_get = _['default'];
		}, function (_2) {
			_inherits = _2['default'];
		}, function (_6) {
			Geometry = _6['default'];
		}, function (_7) {
			uniforms = _7['default'];
		}, function (_b) {
			Scene = _b['default'];
		}, function (_a) {
			assets = _a['default'];
		}, function (_e) {
			simpleText = _e.simpleText;
		}],
		execute: function () {
			'use strict';

			TextScene = (function (_Scene) {
				_inherits(TextScene, _Scene);

				function TextScene() {
					_classCallCheck(this, TextScene);

					_get(Object.getPrototypeOf(TextScene.prototype), 'constructor', this).call(this);

					// grid of quads
					this.addChildren(Geometry.createQuadFromPoints(Geometry.getRandomPoints(128 * 128, 3), assets.shaderMaterials.text));

					this.message = [{ text: 'La Chimie\ndu Cookie',
						font: 'trashhand',
						size: 220 }, { text: 'artcode by ponk\nmusic by gaeel',
						font: 'trashhand',
						size: 150 }, { text: 'made with love\nfor alchimie 12',
						font: 'trashhand',
						size: 150 }, { text: 'cookie\ndemoparty',
						font: 'trashhand',
						size: 200 }, { text: '8, 9 December\nMontreuil',
						font: 'trashhand',
						size: 150 }, { text: 'BISOUS',
						font: 'trashhand',
						size: 200 }];
					this.currentMessage = 0;
					this.textures = [];
					for (var i = 0; i < this.message.length; i++) {
						this.textures.push(new THREE.Texture(simpleText(this.message[i].text, this.message[i].font, this.message[i].size, 1024, true)));
						this.textures[i].needsUpdate = true;
					}
					this.updateTexture();
				}

				_createClass(TextScene, [{
					key: 'update',
					value: function update(elapsed) {
						_get(Object.getPrototypeOf(TextScene.prototype), 'update', this).call(this, elapsed);

						var messageIndex = assets.animations.getValue('blendMessageIndex', elapsed);
						if (this.currentMessage != messageIndex) {
							this.currentMessage = messageIndex;
							this.updateTexture();
						}
					}
				}, {
					key: 'updateTexture',
					value: function updateTexture() {
						uniforms.frameTextureText.value = this.textures[this.currentMessage];
					}
				}]);

				return TextScene;
			})(Scene);

			_export('default', TextScene);
		}
	};
});

$__System.registerDynamic('12', ['13', '14'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var IObject = $__require('13'),
      defined = $__require('14');
  module.exports = function (it) {
    return IObject(defined(it));
  };
});
$__System.registerDynamic('15', ['12', '16'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var toIObject = $__require('12');
  $__require('16')('getOwnPropertyDescriptor', function ($getOwnPropertyDescriptor) {
    return function getOwnPropertyDescriptor(it, key) {
      return $getOwnPropertyDescriptor(toIObject(it), key);
    };
  });
});
$__System.registerDynamic('17', ['18', '15'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var $ = $__require('18');
  $__require('15');
  module.exports = function getOwnPropertyDescriptor(it, key) {
    return $.getDesc(it, key);
  };
});
$__System.registerDynamic("19", ["17"], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = { "default": $__require("17"), __esModule: true };
});
$__System.registerDynamic("8", ["19"], true, function ($__require, exports, module) {
  /* */
  "use strict";

  var global = this || self,
      GLOBAL = global;
  var _Object$getOwnPropertyDescriptor = $__require("19")["default"];
  exports["default"] = function get(_x, _x2, _x3) {
    var _again = true;
    _function: while (_again) {
      var object = _x,
          property = _x2,
          receiver = _x3;
      _again = false;
      if (object === null) object = Function.prototype;
      var desc = _Object$getOwnPropertyDescriptor(object, property);
      if (desc === undefined) {
        var parent = Object.getPrototypeOf(object);
        if (parent === null) {
          return undefined;
        } else {
          _x = parent;
          _x2 = property;
          _x3 = receiver;
          _again = true;
          desc = parent = undefined;
          continue _function;
        }
      } else if ("value" in desc) {
        return desc.value;
      } else {
        var getter = desc.get;
        if (getter === undefined) {
          return undefined;
        }
        return getter.call(receiver);
      }
    }
  };
  exports.__esModule = true;
});
$__System.registerDynamic('1a', [], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = function (it) {
    return typeof it === 'object' ? it !== null : typeof it === 'function';
  };
});
$__System.registerDynamic('1b', ['1a'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var isObject = $__require('1a');
  module.exports = function (it) {
    if (!isObject(it)) throw TypeError(it + ' is not an object!');
    return it;
  };
});
$__System.registerDynamic('1c', ['18', '1a', '1b', '1d'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var getDesc = $__require('18').getDesc,
      isObject = $__require('1a'),
      anObject = $__require('1b');
  var check = function (O, proto) {
    anObject(O);
    if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!");
  };
  module.exports = {
    set: Object.setPrototypeOf || ('__proto__' in {} ? function (test, buggy, set) {
      try {
        set = $__require('1d')(Function.call, getDesc(Object.prototype, '__proto__').set, 2);
        set(test, []);
        buggy = !(test instanceof Array);
      } catch (e) {
        buggy = true;
      }
      return function setPrototypeOf(O, proto) {
        check(O, proto);
        if (buggy) O.__proto__ = proto;else set(O, proto);
        return O;
      };
    }({}, false) : undefined),
    check: check
  };
});
$__System.registerDynamic('1e', ['1f', '1c'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var $export = $__require('1f');
  $export($export.S, 'Object', { setPrototypeOf: $__require('1c').set });
});
$__System.registerDynamic('20', ['1e', '21'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  $__require('1e');
  module.exports = $__require('21').Object.setPrototypeOf;
});
$__System.registerDynamic("22", ["20"], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = { "default": $__require("20"), __esModule: true };
});
$__System.registerDynamic("9", ["23", "22"], true, function ($__require, exports, module) {
  /* */
  "use strict";

  var global = this || self,
      GLOBAL = global;
  var _Object$create = $__require("23")["default"];
  var _Object$setPrototypeOf = $__require("22")["default"];
  exports["default"] = function (subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = _Object$create(superClass && superClass.prototype, { constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      } });
    if (superClass) _Object$setPrototypeOf ? _Object$setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  };
  exports.__esModule = true;
});
$__System.registerDynamic('24', ['18'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var $ = $__require('18');
  module.exports = function create(P, D) {
    return $.create(P, D);
  };
});
$__System.registerDynamic("23", ["24"], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = { "default": $__require("24"), __esModule: true };
});
$__System.registerDynamic('25', ['18'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var $ = $__require('18');
  module.exports = function defineProperties(T, D) {
    return $.setDescs(T, D);
  };
});
$__System.registerDynamic("26", ["25"], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = { "default": $__require("25"), __esModule: true };
});
$__System.register('27', ['3', '23', '26', '28'], function (_export) {
		var THREE, _Object$create, _Object$defineProperties, lerp, OrbitControls;

		return {
				setters: [function (_3) {
						THREE = _3;
				}, function (_) {
						_Object$create = _['default'];
				}, function (_2) {
						_Object$defineProperties = _2['default'];
				}, function (_4) {
						lerp = _4.lerp;
				}],
				execute: function () {
						/**
       * @author qiao / https://github.com/qiao
       * @author mrdoob / http://mrdoob.com
       * @author alteredq / http://alteredqualia.com/
       * @author WestLangley / http://github.com/WestLangley
       * @author erich666 / http://erichaines.com
       */

						// This set of controls performs orbiting, dollying (zooming), and panning.
						// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
						//
						//    Orbit - left mouse / touch: one finger move
						//    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
						//    Pan - right mouse, or arrow keys / touch: three finger swipe

						'use strict';

						OrbitControls = function OrbitControls(object, domElement) {

								this.object = object;

								this.domElement = domElement !== undefined ? domElement : document;

								// Set to false to disable this control
								this.enabled = true;

								// "target" sets the location of focus, where the object orbits around
								this.target = new THREE.Vector3();

								// How far you can dolly in and out ( PerspectiveCamera only )
								this.minDistance = 0;
								this.maxDistance = Infinity;

								// How far you can zoom in and out ( OrthographicCamera only )
								this.minZoom = 0;
								this.maxZoom = Infinity;

								// How far you can orbit vertically, upper and lower limits.
								// Range is 0 to Math.PI radians.
								this.minPolarAngle = 0; // radians
								this.maxPolarAngle = Math.PI; // radians

								// How far you can orbit horizontally, upper and lower limits.
								// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
								this.minAzimuthAngle = -Infinity; // radians
								this.maxAzimuthAngle = Infinity; // radians

								// Set to true to enable damping (inertia)
								// If damping is enabled, you must call controls.update() in your animation loop
								this.enableDamping = false;
								this.dampingFactor = 0.25;

								// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
								// Set to false to disable zooming
								this.enableZoom = true;
								this.zoomSpeed = 1.0;

								// Set to false to disable rotating
								this.enableRotate = true;
								this.rotateSpeed = 1.0;

								// Set to false to disable panning
								this.enablePan = true;
								this.keyPanSpeed = 7.0; // pixels moved per arrow key push

								// Set to true to automatically rotate around the target
								// If auto-rotate is enabled, you must call controls.update() in your animation loop
								this.autoRotate = false;
								this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60

								// Set to false to disable use of the keys
								this.enableKeys = true;

								// The four arrow keys
								this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };

								// Mouse buttons
								this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };

								// for reset
								this.target0 = this.target.clone();
								this.position0 = this.object.position.clone();
								this.zoom0 = this.object.zoom;

								this.radiusDelta = 0;

								//
								// public methods
								//

								this.getPolarAngle = function () {

										return spherical.phi;
								};

								this.getAzimuthalAngle = function () {

										return spherical.theta;
								};

								this.reset = function () {

										scope.target.copy(scope.target0);
										scope.object.position.copy(scope.position0);
										scope.object.zoom = scope.zoom0;

										scope.object.updateProjectionMatrix();
										scope.dispatchEvent(changeEvent);

										scope.update();

										state = STATE.NONE;
								};

								// this method is exposed, but perhaps it would be better if we can make it private...
								this.update = (function () {

										var offset = new THREE.Vector3();

										// so camera.up is the orbit axis
										var quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));
										var quatInverse = quat.clone().inverse();

										var lastPosition = new THREE.Vector3();
										var lastQuaternion = new THREE.Quaternion();

										return function update() {

												var position = scope.object.position;

												offset.copy(position).sub(scope.target);

												// rotate offset to "y-axis-is-up" space
												offset.applyQuaternion(quat);

												// angle from z-axis around y-axis
												spherical.setFromVector3(offset);

												if (scope.autoRotate && state === STATE.NONE) {

														rotateLeft(getAutoRotationAngle());
												}

												spherical.theta += sphericalDelta.theta;
												spherical.phi += sphericalDelta.phi;

												// restrict theta to be between desired limits
												spherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta));

												// restrict phi to be between desired limits
												spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));

												spherical.makeSafe();

												this.radiusDelta += scale - 1.;
												this.radiusDelta *= 1 - scope.dampingFactor;

												spherical.radius += this.radiusDelta;

												// restrict radius to be between desired limits
												spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));

												// move target to panned location
												scope.target.add(panOffset);

												offset.setFromSpherical(spherical);

												// rotate offset back to "camera-up-vector-is-up" space
												offset.applyQuaternion(quatInverse);

												position.copy(scope.target).add(offset);

												scope.object.lookAt(scope.target);

												if (scope.enableDamping === true) {

														sphericalDelta.theta *= 1 - scope.dampingFactor;
														sphericalDelta.phi *= 1 - scope.dampingFactor;
												} else {

														sphericalDelta.set(0, 0, 0);
												}

												scale = 1;
												panOffset.set(0, 0, 0);

												// update condition is:
												// min(camera displacement, camera rotation in radians)^2 > EPS
												// using small-angle approximation cos(x/2) = 1 - x^2 / 8

												if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {

														scope.dispatchEvent(changeEvent);

														lastPosition.copy(scope.object.position);
														lastQuaternion.copy(scope.object.quaternion);
														zoomChanged = false;

														return true;
												}

												return false;
										};
								})();

								this.dispose = function () {

										scope.domElement.removeEventListener('contextmenu', onContextMenu, false);
										scope.domElement.removeEventListener('mousedown', onMouseDown, false);
										scope.domElement.removeEventListener('wheel', onMouseWheel, false);

										scope.domElement.removeEventListener('touchstart', onTouchStart, false);
										scope.domElement.removeEventListener('touchend', onTouchEnd, false);
										scope.domElement.removeEventListener('touchmove', onTouchMove, false);

										document.removeEventListener('mousemove', onMouseMove, false);
										document.removeEventListener('mouseup', onMouseUp, false);

										window.removeEventListener('keydown', onKeyDown, false);

										//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
								};

								//
								// internals
								//

								var scope = this;

								var changeEvent = { type: 'change' };
								var startEvent = { type: 'start' };
								var endEvent = { type: 'end' };

								var STATE = { NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 };

								var state = STATE.NONE;

								var EPS = 0.000001;

								// current position in spherical coordinates
								var spherical = new THREE.Spherical();
								var sphericalDelta = new THREE.Spherical();

								var scale = 1;
								var panOffset = new THREE.Vector3();
								var zoomChanged = false;

								var rotateStart = new THREE.Vector2();
								var rotateEnd = new THREE.Vector2();
								var rotateDelta = new THREE.Vector2();

								var panStart = new THREE.Vector2();
								var panEnd = new THREE.Vector2();
								var panDelta = new THREE.Vector2();

								var dollyStart = new THREE.Vector2();
								var dollyEnd = new THREE.Vector2();
								var dollyDelta = new THREE.Vector2();

								function getAutoRotationAngle() {

										return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
								}

								function getZoomScale() {

										return Math.pow(0.95, scope.zoomSpeed);
								}

								function rotateLeft(angle) {

										sphericalDelta.theta -= angle;
								}

								function rotateUp(angle) {

										sphericalDelta.phi -= angle;
								}

								var panLeft = (function () {

										var v = new THREE.Vector3();

										return function panLeft(distance, objectMatrix) {

												v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix
												v.multiplyScalar(-distance);

												panOffset.add(v);
										};
								})();

								var panUp = (function () {

										var v = new THREE.Vector3();

										return function panUp(distance, objectMatrix) {

												v.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix
												v.multiplyScalar(distance);

												panOffset.add(v);
										};
								})();

								// deltaX and deltaY are in pixels; right and down are positive
								var pan = (function () {

										var offset = new THREE.Vector3();

										return function pan(deltaX, deltaY) {

												var element = scope.domElement === document ? scope.domElement.body : scope.domElement;

												if (scope.object instanceof THREE.PerspectiveCamera) {

														// perspective
														var position = scope.object.position;
														offset.copy(position).sub(scope.target);
														var targetDistance = offset.length();

														// half of the fov is center to top of screen
														targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180.0);

														// we actually don't use screenWidth, since perspective camera is fixed to screen height
														panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
														panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
												} else if (scope.object instanceof THREE.OrthographicCamera) {

														// orthographic
														panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
														panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);
												} else {

														// camera neither orthographic nor perspective
														console.warn('WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.');
														scope.enablePan = false;
												}
										};
								})();

								function dollyIn(dollyScale) {

										if (scope.object instanceof THREE.PerspectiveCamera) {

												scale /= dollyScale;
										} else if (scope.object instanceof THREE.OrthographicCamera) {

												scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
												scope.object.updateProjectionMatrix();
												zoomChanged = true;
										} else {

												console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');
												scope.enableZoom = false;
										}
								}

								function dollyOut(dollyScale) {

										if (scope.object instanceof THREE.PerspectiveCamera) {

												scale *= dollyScale;
										} else if (scope.object instanceof THREE.OrthographicCamera) {

												scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
												scope.object.updateProjectionMatrix();
												zoomChanged = true;
										} else {

												console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');
												scope.enableZoom = false;
										}
								}

								//
								// event callbacks - update the object state
								//

								function handleMouseDownRotate(event) {

										//console.log( 'handleMouseDownRotate' );

										rotateStart.set(event.clientX, event.clientY);
								}

								function handleMouseDownDolly(event) {

										//console.log( 'handleMouseDownDolly' );

										dollyStart.set(event.clientX, event.clientY);
								}

								function handleMouseDownPan(event) {

										//console.log( 'handleMouseDownPan' );

										panStart.set(event.clientX, event.clientY);
								}

								function handleMouseMoveRotate(event) {

										//console.log( 'handleMouseMoveRotate' );

										rotateEnd.set(event.clientX, event.clientY);
										rotateDelta.subVectors(rotateEnd, rotateStart);

										var element = scope.domElement === document ? scope.domElement.body : scope.domElement;

										// rotating across whole screen goes 360 degrees around
										rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);

										// rotating up and down along whole screen attempts to go 360, but limited to 180
										rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);

										rotateStart.copy(rotateEnd);

										scope.update();
								}

								function handleMouseMoveDolly(event) {

										//console.log( 'handleMouseMoveDolly' );

										dollyEnd.set(event.clientX, event.clientY);

										dollyDelta.subVectors(dollyEnd, dollyStart);

										if (dollyDelta.y > 0) {

												dollyIn(getZoomScale());
										} else if (dollyDelta.y < 0) {

												dollyOut(getZoomScale());
										}

										dollyStart.copy(dollyEnd);

										scope.update();
								}

								function handleMouseMovePan(event) {

										//console.log( 'handleMouseMovePan' );

										panEnd.set(event.clientX, event.clientY);

										panDelta.subVectors(panEnd, panStart);

										pan(panDelta.x, panDelta.y);

										panStart.copy(panEnd);

										scope.update();
								}

								function handleMouseUp(event) {

										// console.log( 'handleMouseUp' );

								}

								function handleMouseWheel(event) {

										// console.log( 'handleMouseWheel' );

										if (event.deltaY < 0) {

												dollyOut(getZoomScale());
										} else if (event.deltaY > 0) {

												dollyIn(getZoomScale());
										}

										scope.update();
								}

								function handleKeyDown(event) {

										//console.log( 'handleKeyDown' );

										switch (event.keyCode) {

												case scope.keys.UP:
														pan(0, scope.keyPanSpeed);
														scope.update();
														break;

												case scope.keys.BOTTOM:
														pan(0, -scope.keyPanSpeed);
														scope.update();
														break;

												case scope.keys.LEFT:
														pan(scope.keyPanSpeed, 0);
														scope.update();
														break;

												case scope.keys.RIGHT:
														pan(-scope.keyPanSpeed, 0);
														scope.update();
														break;

										}
								}

								function handleTouchStartRotate(event) {

										//console.log( 'handleTouchStartRotate' );

										rotateStart.set(event.touches[0].pageX, event.touches[0].pageY);
								}

								function handleTouchStartDolly(event) {

										//console.log( 'handleTouchStartDolly' );

										var dx = event.touches[0].pageX - event.touches[1].pageX;
										var dy = event.touches[0].pageY - event.touches[1].pageY;

										var distance = Math.sqrt(dx * dx + dy * dy);

										dollyStart.set(0, distance);
								}

								function handleTouchStartPan(event) {

										//console.log( 'handleTouchStartPan' );

										panStart.set(event.touches[0].pageX, event.touches[0].pageY);
								}

								function handleTouchMoveRotate(event) {

										//console.log( 'handleTouchMoveRotate' );

										rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
										rotateDelta.subVectors(rotateEnd, rotateStart);

										var element = scope.domElement === document ? scope.domElement.body : scope.domElement;

										// rotating across whole screen goes 360 degrees around
										rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);

										// rotating up and down along whole screen attempts to go 360, but limited to 180
										rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);

										rotateStart.copy(rotateEnd);

										scope.update();
								}

								function handleTouchMoveDolly(event) {

										//console.log( 'handleTouchMoveDolly' );

										var dx = event.touches[0].pageX - event.touches[1].pageX;
										var dy = event.touches[0].pageY - event.touches[1].pageY;

										var distance = Math.sqrt(dx * dx + dy * dy);

										dollyEnd.set(0, distance);

										dollyDelta.subVectors(dollyEnd, dollyStart);

										if (dollyDelta.y > 0) {

												dollyOut(getZoomScale());
										} else if (dollyDelta.y < 0) {

												dollyIn(getZoomScale());
										}

										dollyStart.copy(dollyEnd);

										scope.update();
								}

								function handleTouchMovePan(event) {

										//console.log( 'handleTouchMovePan' );

										panEnd.set(event.touches[0].pageX, event.touches[0].pageY);

										panDelta.subVectors(panEnd, panStart);

										pan(panDelta.x, panDelta.y);

										panStart.copy(panEnd);

										scope.update();
								}

								function handleTouchEnd(event) {}

								//console.log( 'handleTouchEnd' );

								//
								// event handlers - FSM: listen for events and reset state
								//

								function onMouseDown(event) {

										if (scope.enabled === false) return;

										event.preventDefault();

										if (event.button === scope.mouseButtons.ORBIT) {

												if (scope.enableRotate === false) return;

												handleMouseDownRotate(event);

												state = STATE.ROTATE;
										} else if (event.button === scope.mouseButtons.ZOOM) {

												if (scope.enableZoom === false) return;

												handleMouseDownDolly(event);

												state = STATE.DOLLY;
										} else if (event.button === scope.mouseButtons.PAN) {

												if (scope.enablePan === false) return;

												handleMouseDownPan(event);

												state = STATE.PAN;
										}

										if (state !== STATE.NONE) {

												document.addEventListener('mousemove', onMouseMove, false);
												document.addEventListener('mouseup', onMouseUp, false);

												scope.dispatchEvent(startEvent);
										}
								}

								function onMouseMove(event) {

										if (scope.enabled === false) return;

										event.preventDefault();

										if (state === STATE.ROTATE) {

												if (scope.enableRotate === false) return;

												handleMouseMoveRotate(event);
										} else if (state === STATE.DOLLY) {

												if (scope.enableZoom === false) return;

												handleMouseMoveDolly(event);
										} else if (state === STATE.PAN) {

												if (scope.enablePan === false) return;

												handleMouseMovePan(event);
										}
								}

								function onMouseUp(event) {

										if (scope.enabled === false) return;

										handleMouseUp(event);

										document.removeEventListener('mousemove', onMouseMove, false);
										document.removeEventListener('mouseup', onMouseUp, false);

										scope.dispatchEvent(endEvent);

										state = STATE.NONE;
								}

								function onMouseWheel(event) {

										if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE) return;

										event.preventDefault();
										event.stopPropagation();

										handleMouseWheel(event);

										scope.dispatchEvent(startEvent); // not sure why these are here...
										scope.dispatchEvent(endEvent);
								}

								function onKeyDown(event) {

										if (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false) return;

										handleKeyDown(event);
								}

								function onTouchStart(event) {

										if (scope.enabled === false) return;

										switch (event.touches.length) {

												case 1:
														// one-fingered touch: rotate

														if (scope.enableRotate === false) return;

														handleTouchStartRotate(event);

														state = STATE.TOUCH_ROTATE;

														break;

												case 2:
														// two-fingered touch: dolly

														if (scope.enableZoom === false) return;

														handleTouchStartDolly(event);

														state = STATE.TOUCH_DOLLY;

														break;

												case 3:
														// three-fingered touch: pan

														if (scope.enablePan === false) return;

														handleTouchStartPan(event);

														state = STATE.TOUCH_PAN;

														break;

												default:

														state = STATE.NONE;

										}

										if (state !== STATE.NONE) {

												scope.dispatchEvent(startEvent);
										}
								}

								function onTouchMove(event) {

										if (scope.enabled === false) return;

										event.preventDefault();
										event.stopPropagation();

										switch (event.touches.length) {

												case 1:
														// one-fingered touch: rotate

														if (scope.enableRotate === false) return;
														if (state !== STATE.TOUCH_ROTATE) return; // is this needed?...

														handleTouchMoveRotate(event);

														break;

												case 2:
														// two-fingered touch: dolly

														if (scope.enableZoom === false) return;
														if (state !== STATE.TOUCH_DOLLY) return; // is this needed?...

														handleTouchMoveDolly(event);

														break;

												case 3:
														// three-fingered touch: pan

														if (scope.enablePan === false) return;
														if (state !== STATE.TOUCH_PAN) return; // is this needed?...

														handleTouchMovePan(event);

														break;

												default:

														state = STATE.NONE;

										}
								}

								function onTouchEnd(event) {

										if (scope.enabled === false) return;

										handleTouchEnd(event);

										scope.dispatchEvent(endEvent);

										state = STATE.NONE;
								}

								function onContextMenu(event) {

										event.preventDefault();
								}

								//

								scope.domElement.addEventListener('contextmenu', onContextMenu, false);

								scope.domElement.addEventListener('mousedown', onMouseDown, false);
								scope.domElement.addEventListener('wheel', onMouseWheel, false);

								scope.domElement.addEventListener('touchstart', onTouchStart, false);
								scope.domElement.addEventListener('touchend', onTouchEnd, false);
								scope.domElement.addEventListener('touchmove', onTouchMove, false);

								window.addEventListener('keydown', onKeyDown, false);

								// force an update at start

								this.update();
						};

						_export('OrbitControls', OrbitControls);

						OrbitControls.prototype = _Object$create(THREE.EventDispatcher.prototype);
						OrbitControls.prototype.constructor = OrbitControls;

						_Object$defineProperties(OrbitControls.prototype, {

								center: {

										get: function get() {

												console.warn('OrbitControls: .center has been renamed to .target');
												return this.target;
										}

								},

								// backward compatibility

								noZoom: {

										get: function get() {

												console.warn('OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.');
												return !this.enableZoom;
										},

										set: function set(value) {

												console.warn('OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.');
												this.enableZoom = !value;
										}

								},

								noRotate: {

										get: function get() {

												console.warn('OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.');
												return !this.enableRotate;
										},

										set: function set(value) {

												console.warn('OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.');
												this.enableRotate = !value;
										}

								},

								noPan: {

										get: function get() {

												console.warn('OrbitControls: .noPan has been deprecated. Use .enablePan instead.');
												return !this.enablePan;
										},

										set: function set(value) {

												console.warn('OrbitControls: .noPan has been deprecated. Use .enablePan instead.');
												this.enablePan = !value;
										}

								},

								noKeys: {

										get: function get() {

												console.warn('OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.');
												return !this.enableKeys;
										},

										set: function set(value) {

												console.warn('OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.');
												this.enableKeys = !value;
										}

								},

								staticMoving: {

										get: function get() {

												console.warn('OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.');
												return !this.enableDamping;
										},

										set: function set(value) {

												console.warn('OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.');
												this.enableDamping = !value;
										}

								},

								dynamicDampingFactor: {

										get: function get() {

												console.warn('OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.');
												return this.dampingFactor;
										},

										set: function set(value) {

												console.warn('OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.');
												this.dampingFactor = value;
										}

								}

						});
				}
		};
});

$__System.register('d', ['3'], function (_export) {
	'use strict';

	var THREE, renderer;
	return {
		setters: [function (_) {
			THREE = _;
		}],
		execute: function () {
			renderer = new THREE.WebGLRenderer({
				logarithmicDepthBuffer: true,
				antialias: false
			});

			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(window.innerWidth, window.innerHeight);
			document.body.appendChild(renderer.domElement);

			_export('default', renderer);
		}
	};
});

$__System.register('b', ['3', '4', '5', '27', 'd'], function (_export) {
	var THREE, _createClass, _classCallCheck, OrbitControls, renderer, Scene;

	return {
		setters: [function (_3) {
			THREE = _3;
		}, function (_) {
			_createClass = _['default'];
		}, function (_2) {
			_classCallCheck = _2['default'];
		}, function (_4) {
			OrbitControls = _4.OrbitControls;
		}, function (_d) {
			renderer = _d['default'];
		}],
		execute: function () {
			'use strict';

			Scene = (function () {
				function Scene() {
					_classCallCheck(this, Scene);

					this.scene = new THREE.Scene();
					this.camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.01, 1000);
					this.camera.position.y = 1;
					this.camera.position.x = -40;

					this.controls = new OrbitControls(this.camera, renderer.domElement);
					this.controls.rotateSpeed = 0.1;
					this.controls.zoomSpeed = 2.5;
					this.controls.enableDamping = true;
					this.controls.dampingFactor = .1;
				}

				_createClass(Scene, [{
					key: 'update',
					value: function update(elapsed) {
						this.controls.update();
					}
				}, {
					key: 'add',
					value: function add(mesh) {
						this.scene.add(mesh);
					}
				}, {
					key: 'addChildren',
					value: function addChildren(meshes) {
						for (var i = 0; i < meshes.length; ++i) this.scene.add(meshes[i]);
					}
				}]);

				return Scene;
			})();

			_export('default', Scene);
		}
	};
});

$__System.registerDynamic("29", [], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var toString = {}.toString;

  module.exports = function (it) {
    return toString.call(it).slice(8, -1);
  };
});
$__System.registerDynamic('13', ['29'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var cof = $__require('29');
  module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
    return cof(it) == 'String' ? it.split('') : Object(it);
  };
});
$__System.registerDynamic('2a', ['18', '2b', '13', '2c'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var $ = $__require('18'),
      toObject = $__require('2b'),
      IObject = $__require('13');
  module.exports = $__require('2c')(function () {
    var a = Object.assign,
        A = {},
        B = {},
        S = Symbol(),
        K = 'abcdefghijklmnopqrst';
    A[S] = 7;
    K.split('').forEach(function (k) {
      B[k] = k;
    });
    return a({}, A)[S] != 7 || Object.keys(a({}, B)).join('') != K;
  }) ? function assign(target, source) {
    var T = toObject(target),
        $$ = arguments,
        $$len = $$.length,
        index = 1,
        getKeys = $.getKeys,
        getSymbols = $.getSymbols,
        isEnum = $.isEnum;
    while ($$len > index) {
      var S = IObject($$[index++]),
          keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S),
          length = keys.length,
          j = 0,
          key;
      while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key];
    }
    return T;
  } : Object.assign;
});
$__System.registerDynamic('2d', ['1f', '2a'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var $export = $__require('1f');
  $export($export.S + $export.F, 'Object', { assign: $__require('2a') });
});
$__System.registerDynamic('2e', ['2d', '21'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  $__require('2d');
  module.exports = $__require('21').Object.assign;
});
$__System.registerDynamic("2f", ["2e"], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = { "default": $__require("2e"), __esModule: true };
});
$__System.register("30", [], function (_export, _context) {
  "use strict";

  var __useDefault, animations, fonts, geometries, shaderMaterials;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = true);

      _export("__useDefault", __useDefault);

      _export("animations", animations = "animation/scene.json");

      _export("animations", animations);

      _export("fonts", fonts = {});

      _export("fonts", fonts);

      _export("geometries", geometries = {});

      _export("geometries", geometries);

      _export("shaderMaterials", shaderMaterials = { "bubble": { "vertexShader": "shader/meshes/bubble.vert", "fragmentShader": "shader/meshes/bubble.frag", "side": 2 }, "raymarching": { "vertexShader": "shader/filters/screen.vert", "fragmentShader": "shader/filters/raymarching.frag" }, "paper": { "vertexShader": "shader/meshes/paper.vert", "fragmentShader": "shader/meshes/paper.frag", "side": 2 }, "line": { "vertexShader": "shader/meshes/line.vert", "fragmentShader": "shader/meshes/line.frag", "side": 2 }, "text": { "vertexShader": "shader/meshes/text.vert", "fragmentShader": "shader/meshes/text.frag", "side": 2, "depthTest": false, "opacity": 1, "transparent": true }, "filter": { "vertexShader": "shader/filters/screen.vert", "fragmentShader": "shader/filters/filter.frag" } });

      _export("shaderMaterials", shaderMaterials);

      _export("default", {
        animations: animations,
        fonts: fonts,
        geometries: geometries,
        shaderMaterials: shaderMaterials
      });
    }
  };
});
(function() {
var define = $__System.amdDefine;
(function webpackUniversalModuleDefinition(root, factory) {
  if (typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  else if (typeof define === 'function' && define.amd)
    define("31", [], factory);
  else {
    var a = factory();
    for (var i in a)
      (typeof exports === 'object' ? exports : root)[i] = a[i];
  }
})(this, function() {
  return (function(modules) {
    var installedModules = {};
    function __webpack_require__(moduleId) {
      if (installedModules[moduleId]) {
        return installedModules[moduleId].exports;
      }
      var module = installedModules[moduleId] = {
        i: moduleId,
        l: false,
        exports: {}
      };
      modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
      module.l = true;
      return module.exports;
    }
    __webpack_require__.m = modules;
    __webpack_require__.c = installedModules;
    __webpack_require__.d = function(exports, name, getter) {
      if (!__webpack_require__.o(exports, name)) {
        Object.defineProperty(exports, name, {
          configurable: false,
          enumerable: true,
          get: getter
        });
      }
    };
    __webpack_require__.n = function(module) {
      var getter = module && module.__esModule ? function getDefault() {
        return module['default'];
      } : function getModuleExports() {
        return module;
      };
      __webpack_require__.d(getter, 'a', getter);
      return getter;
    };
    __webpack_require__.o = function(object, property) {
      return Object.prototype.hasOwnProperty.call(object, property);
    };
    __webpack_require__.p = "";
    return __webpack_require__(__webpack_require__.s = 4);
  })([(function(module, exports, __webpack_require__) {
    "use strict";
    Object.defineProperty(exports, "__esModule", {value: true});
    exports.setMatrixArrayType = setMatrixArrayType;
    exports.toRadian = toRadian;
    exports.equals = equals;
    var EPSILON = exports.EPSILON = 0.000001;
    var ARRAY_TYPE = exports.ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
    var RANDOM = exports.RANDOM = Math.random;
    function setMatrixArrayType(type) {
      exports.ARRAY_TYPE = ARRAY_TYPE = type;
    }
    var degree = Math.PI / 180;
    function toRadian(a) {
      return a * degree;
    }
    function equals(a, b) {
      return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));
    }
  }), (function(module, exports, __webpack_require__) {
    "use strict";
    Object.defineProperty(exports, "__esModule", {value: true});
    exports.sub = exports.mul = undefined;
    exports.create = create;
    exports.fromMat4 = fromMat4;
    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.rotate = rotate;
    exports.scale = scale;
    exports.fromTranslation = fromTranslation;
    exports.fromRotation = fromRotation;
    exports.fromScaling = fromScaling;
    exports.fromMat2d = fromMat2d;
    exports.fromQuat = fromQuat;
    exports.normalFromMat4 = normalFromMat4;
    exports.projection = projection;
    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;
      }
    }
    function create() {
      var out = new glMatrix.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 fromMat4(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 clone(a) {
      var out = new glMatrix.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 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];
      return out;
    }
    function fromValues(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
      var out = new glMatrix.ARRAY_TYPE(9);
      out[0] = m00;
      out[1] = m01;
      out[2] = m02;
      out[3] = m10;
      out[4] = m11;
      out[5] = m12;
      out[6] = m20;
      out[7] = m21;
      out[8] = m22;
      return out;
    }
    function set(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) {
      out[0] = m00;
      out[1] = m01;
      out[2] = m02;
      out[3] = m10;
      out[4] = m11;
      out[5] = m12;
      out[6] = m20;
      out[7] = m21;
      out[8] = m22;
      return out;
    }
    function identity(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 transpose(out, a) {
      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 invert(out, a) {
      var a00 = a[0],
          a01 = a[1],
          a02 = a[2];
      var a10 = a[3],
          a11 = a[4],
          a12 = a[5];
      var a20 = a[6],
          a21 = a[7],
          a22 = a[8];
      var b01 = a22 * a11 - a12 * a21;
      var b11 = -a22 * a10 + a12 * a20;
      var b21 = a21 * a10 - a11 * a20;
      var 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;
    }
    function adjoint(out, a) {
      var a00 = a[0],
          a01 = a[1],
          a02 = a[2];
      var a10 = a[3],
          a11 = a[4],
          a12 = a[5];
      var 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;
    }
    function determinant(a) {
      var a00 = a[0],
          a01 = a[1],
          a02 = a[2];
      var a10 = a[3],
          a11 = a[4],
          a12 = a[5];
      var 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);
    }
    function multiply(out, a, b) {
      var a00 = a[0],
          a01 = a[1],
          a02 = a[2];
      var a10 = a[3],
          a11 = a[4],
          a12 = a[5];
      var a20 = a[6],
          a21 = a[7],
          a22 = a[8];
      var b00 = b[0],
          b01 = b[1],
          b02 = b[2];
      var b10 = b[3],
          b11 = b[4],
          b12 = b[5];
      var 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;
    }
    function translate(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];
      out[0] = a00;
      out[1] = a01;
      out[2] = a02;
      out[3] = a10;
      out[4] = a11;
      out[5] = a12;
      out[6] = x * a00 + y * a10 + a20;
      out[7] = x * a01 + y * a11 + a21;
      out[8] = x * a02 + y * a12 + a22;
      return out;
    }
    function rotate(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;
    }
    ;
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
      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;
    }
    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;
    }
    function str(a) {
      return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ')';
    }
    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));
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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];
    }
    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));
    }
    var mul = exports.mul = multiply;
    var sub = exports.sub = subtract;
  }), (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.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;
      }
    }
    function create() {
      var out = new glMatrix.ARRAY_TYPE(3);
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      return out;
    }
    function clone(a) {
      var out = new glMatrix.ARRAY_TYPE(3);
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      return out;
    }
    function length(a) {
      var x = a[0];
      var y = a[1];
      var z = a[2];
      return Math.sqrt(x * x + y * y + z * z);
    }
    function fromValues(x, y, z) {
      var out = new glMatrix.ARRAY_TYPE(3);
      out[0] = x;
      out[1] = y;
      out[2] = z;
      return out;
    }
    function copy(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      return out;
    }
    function set(out, x, y, z) {
      out[0] = x;
      out[1] = y;
      out[2] = z;
      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;
    }
    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;
    }
    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;
    }
    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;
    }
    function ceil(out, a) {
      out[0] = Math.ceil(a[0]);
      out[1] = Math.ceil(a[1]);
      out[2] = Math.ceil(a[2]);
      return 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;
    }
    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;
    }
    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;
    }
    function round(out, a) {
      out[0] = Math.round(a[0]);
      out[1] = Math.round(a[1]);
      out[2] = Math.round(a[2]);
      return out;
    }
    function scale(out, a, b) {
      out[0] = a[0] * b;
      out[1] = a[1] * b;
      out[2] = a[2] * b;
      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;
    }
    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);
    }
    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;
    }
    function squaredLength(a) {
      var x = a[0];
      var y = a[1];
      var z = a[2];
      return x * x + y * y + z * z;
    }
    function negate(out, a) {
      out[0] = -a[0];
      out[1] = -a[1];
      out[2] = -a[2];
      return out;
    }
    function inverse(out, a) {
      out[0] = 1.0 / a[0];
      out[1] = 1.0 / a[1];
      out[2] = 1.0 / a[2];
      return out;
    }
    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) {
        len = 1 / Math.sqrt(len);
        out[0] = a[0] * len;
        out[1] = a[1] * len;
        out[2] = a[2] * len;
      }
      return out;
    }
    function dot(a, b) {
      return a[0] * b[0] + a[1] * b[1] + a[2] * 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;
    }
    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;
    }
    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;
    }
    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;
    }
    function random(out, scale) {
      scale = scale || 1.0;
      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;
    }
    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;
    }
    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;
    }
    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];
      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;
      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;
    }
    function rotateX(out, a, b, c) {
      var p = [],
          r = [];
      p[0] = a[0] - b[0];
      p[1] = a[1] - b[1];
      p[2] = a[2] - b[2];
      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);
      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 = [];
      p[0] = a[0] - b[0];
      p[1] = a[1] - b[1];
      p[2] = a[2] - b[2];
      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);
      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 = [];
      p[0] = a[0] - b[0];
      p[1] = a[1] - b[1];
      p[2] = a[2] - b[2];
      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];
      out[0] = r[0] + b[0];
      out[1] = r[1] + b[1];
      out[2] = r[2] + b[2];
      return out;
    }
    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);
      }
    }
    function str(a) {
      return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
    }
    function exactEquals(a, b) {
      return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
    }
    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));
    }
    var sub = exports.sub = subtract;
    var mul = exports.mul = multiply;
    var div = exports.div = divide;
    var dist = exports.dist = distance;
    var sqrDist = exports.sqrDist = squaredDistance;
    var len = exports.len = length;
    var sqrLen = exports.sqrLen = squaredLength;
    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 = 3;
        }
        if (!offset) {
          offset = 0;
        }
        if (count) {
          l = Math.min(count * stride + offset, a.length);
        } else {
          l = a.length;
        }
        for (i = offset; i < l; i += stride) {
          vec[0] = a[i];
          vec[1] = a[i + 1];
          vec[2] = a[i + 2];
          fn(vec, vec, arg);
          a[i] = vec[0];
          a[i + 1] = vec[1];
          a[i + 2] = vec[2];
        }
        return a;
      };
    }();
  }), (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;
      }
    }
    function create() {
      var out = new glMatrix.ARRAY_TYPE(4);
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      return out;
    }
    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;
    }
    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;
    }
    function copy(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      return out;
    }
    function set(out, x, y, z, w) {
      out[0] = x;
      out[1] = y;
      out[2] = z;
      out[3] = w;
      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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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);
    }
    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;
    }
    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);
    }
    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;
    }
    function negate(out, a) {
      out[0] = -a[0];
      out[1] = -a[1];
      out[2] = -a[2];
      out[3] = -a[3];
      return out;
    }
    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;
    }
    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;
    }
    function dot(a, b) {
      return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
    }
    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;
    }
    function random(out, vectorScale) {
      vectorScale = vectorScale || 1.0;
      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;
    }
    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;
    }
    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];
      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;
      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;
    }
    function str(a) {
      return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
    }
    function exactEquals(a, b) {
      return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
    }
    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));
    }
    var sub = exports.sub = subtract;
    var mul = exports.mul = multiply;
    var div = exports.div = divide;
    var dist = exports.dist = distance;
    var sqrDist = exports.sqrDist = squaredDistance;
    var len = exports.len = length;
    var sqrLen = exports.sqrLen = squaredLength;
    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 = 4;
        }
        if (!offset) {
          offset = 0;
        }
        if (count) {
          l = Math.min(count * stride + offset, a.length);
        } else {
          l = a.length;
        }
        for (i = offset; i < l; i += stride) {
          vec[0] = a[i];
          vec[1] = a[i + 1];
          vec[2] = a[i + 2];
          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;
      };
    }();
  }), (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;
  }), (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;
      }
    }
    function create() {
      var out = new glMatrix.ARRAY_TYPE(4);
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      return out;
    }
    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;
    }
    function copy(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      return out;
    }
    function identity(out) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      return out;
    }
    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;
    }
    function set(out, m00, m01, m10, m11) {
      out[0] = m00;
      out[1] = m01;
      out[2] = m10;
      out[3] = m11;
      return out;
    }
    function transpose(out, a) {
      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 invert(out, a) {
      var a0 = a[0],
          a1 = a[1],
          a2 = a[2],
          a3 = a[3];
      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;
      return out;
    }
    function adjoint(out, a) {
      var a0 = a[0];
      out[0] = a[3];
      out[1] = -a[1];
      out[2] = -a[2];
      out[3] = a0;
      return out;
    }
    function determinant(a) {
      return a[0] * a[3] - a[2] * a[1];
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    function fromScaling(out, v) {
      out[0] = v[0];
      out[1] = 0;
      out[2] = 0;
      out[3] = v[1];
      return out;
    }
    function str(a) {
      return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
    }
    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));
    }
    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];
    }
    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;
    }
    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;
    }
    function exactEquals(a, b) {
      return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
    }
    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));
    }
    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;
    }
    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;
    }
    var mul = exports.mul = multiply;
    var sub = exports.sub = subtract;
  }), (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;
      }
    }
    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;
    }
    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;
    }
    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;
    }
    function identity(out) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      out[4] = 0;
      out[5] = 0;
      return out;
    }
    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;
    }
    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;
    }
    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;
      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;
    }
    function determinant(a) {
      return a[0] * a[3] - a[1] * a[2];
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    function str(a) {
      return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ')';
    }
    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);
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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];
    }
    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));
    }
    var mul = exports.mul = multiply;
    var sub = exports.sub = subtract;
  }), (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.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;
      }
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    function transpose(out, a) {
      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;
    }
    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];
      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;
      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] = (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;
    }
    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;
    }
    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];
      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;
      return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    }
    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];
      var b0 = b[0],
          b1 = b[1],
          b2 = b[2],
          b3 = b[3];
      out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
      out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
      out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
      out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
      b0 = b[4];
      b1 = b[5];
      b2 = b[6];
      b3 = b[7];
      out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
      out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
      out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
      out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
      b0 = b[8];
      b1 = b[9];
      b2 = b[10];
      b3 = b[11];
      out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
      out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
      out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
      out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
      b0 = b[12];
      b1 = b[13];
      b2 = b[14];
      b3 = b[15];
      out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
      out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
      out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
      out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
      return out;
    }
    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];
        out[0] = a00;
        out[1] = a01;
        out[2] = a02;
        out[3] = a03;
        out[4] = a10;
        out[5] = a11;
        out[6] = a12;
        out[7] = a13;
        out[8] = a20;
        out[9] = a21;
        out[10] = a22;
        out[11] = a23;
        out[12] = a00 * x + a10 * y + a20 * z + a[12];
        out[13] = a01 * x + a11 * y + a21 * z + a[13];
        out[14] = a02 * x + a12 * y + a22 * z + a[14];
        out[15] = a03 * x + a13 * y + a23 * z + a[15];
      }
      return out;
    }
    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;
    }
    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) < glMatrix.EPSILON) {
        return null;
      }
      len = 1 / len;
      x *= len;
      y *= len;
      z *= len;
      s = Math.sin(rad);
      c = Math.cos(rad);
      t = 1 - c;
      a00 = a[0];
      a01 = a[1];
      a02 = a[2];
      a03 = a[3];
      a10 = a[4];
      a11 = a[5];
      a12 = a[6];
      a13 = a[7];
      a20 = a[8];
      a21 = a[9];
      a22 = a[10];
      a23 = a[11];
      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;
      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) {
        out[12] = a[12];
        out[13] = a[13];
        out[14] = a[14];
        out[15] = a[15];
      }
      return out;
    }
    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) {
        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];
      }
      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;
    }
    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) {
        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];
      }
      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;
    }
    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) {
        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];
      }
      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;
    }
    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;
    }
    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;
    }
    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;
      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;
    }
    function fromXRotation(out, rad) {
      var s = Math.sin(rad);
      var c = Math.cos(rad);
      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;
    }
    function fromYRotation(out, rad) {
      var s = Math.sin(rad);
      var c = Math.cos(rad);
      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;
    }
    function fromZRotation(out, rad) {
      var s = Math.sin(rad);
      var c = Math.cos(rad);
      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;
    }
    function fromRotationTranslation(out, q, v) {
      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;
      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;
    }
    function getTranslation(out, mat) {
      out[0] = mat[12];
      out[1] = mat[13];
      out[2] = mat[14];
      return 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[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);
      return out;
    }
    function getRotation(out, mat) {
      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;
    }
    function fromRotationTranslationScale(out, q, v, s) {
      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;
    }
    function fromRotationTranslationScaleOrigin(out, q, v, s, o) {
      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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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) < 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;
      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;
    }
    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;
      }
      var x0 = upy * z2 - upz * z1,
          x1 = upz * z0 - upx * z2,
          x2 = upx * z1 - upy * z0;
      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;
    }
    ;
    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] + ')';
    }
    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));
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    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];
    }
    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));
    }
    var mul = exports.mul = multiply;
    var sub = exports.sub = subtract;
  }), (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;
      }
    }
    function create() {
      var out = new glMatrix.ARRAY_TYPE(4);
      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;
    }
    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;
    }
    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 {
        out_axis[0] = 1;
        out_axis[1] = 0;
        out_axis[2] = 0;
      }
      return rad;
    }
    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;
    }
    function rotateX(out, a, rad) {
      rad *= 0.5;
      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;
    }
    function rotateY(out, a, rad) {
      rad *= 0.5;
      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;
    }
    function rotateZ(out, a, rad) {
      rad *= 0.5;
      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;
    }
    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;
    }
    function slerp(out, a, b, t) {
      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 omega = void 0,
          cosom = void 0,
          sinom = void 0,
          scale0 = void 0,
          scale1 = void 0;
      cosom = ax * bx + ay * by + az * bz + aw * bw;
      if (cosom < 0.0) {
        cosom = -cosom;
        bx = -bx;
        by = -by;
        bz = -bz;
        bw = -bw;
      }
      if (1.0 - cosom > 0.000001) {
        omega = Math.acos(cosom);
        sinom = Math.sin(omega);
        scale0 = Math.sin((1.0 - t) * omega) / sinom;
        scale1 = Math.sin(t * omega) / sinom;
      } else {
        scale0 = 1.0 - t;
        scale1 = t;
      }
      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;
    }
    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;
    }
    function conjugate(out, a) {
      out[0] = -a[0];
      out[1] = -a[1];
      out[2] = -a[2];
      out[3] = a[3];
      return out;
    }
    function fromMat3(out, m) {
      var fTrace = m[0] + m[4] + m[8];
      var fRoot = void 0;
      if (fTrace > 0.0) {
        fRoot = Math.sqrt(fTrace + 1.0);
        out[3] = 0.5 * fRoot;
        fRoot = 0.5 / fRoot;
        out[0] = (m[5] - m[7]) * fRoot;
        out[1] = (m[6] - m[2]) * fRoot;
        out[2] = (m[1] - m[3]) * fRoot;
      } else {
        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;
    }
    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;
    }
    function str(a) {
      return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
    }
    var clone = exports.clone = vec4.clone;
    var fromValues = exports.fromValues = vec4.fromValues;
    var copy = exports.copy = vec4.copy;
    var set = exports.set = vec4.set;
    var add = exports.add = vec4.add;
    var mul = exports.mul = multiply;
    var scale = exports.scale = vec4.scale;
    var dot = exports.dot = vec4.dot;
    var lerp = exports.lerp = vec4.lerp;
    var length = exports.length = vec4.length;
    var len = exports.len = length;
    var squaredLength = exports.squaredLength = vec4.squaredLength;
    var sqrLen = exports.sqrLen = squaredLength;
    var normalize = exports.normalize = vec4.normalize;
    var exactEquals = exports.exactEquals = vec4.exactEquals;
    var equals = exports.equals = vec4.equals;
    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);
        }
      };
    }();
    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;
      };
    }();
    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));
      };
    }();
  }), (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;
      }
    }
    function create() {
      var out = new glMatrix.ARRAY_TYPE(2);
      out[0] = 0;
      out[1] = 0;
      return out;
    }
    function clone(a) {
      var out = new glMatrix.ARRAY_TYPE(2);
      out[0] = a[0];
      out[1] = a[1];
      return out;
    }
    function fromValues(x, y) {
      var out = new glMatrix.ARRAY_TYPE(2);
      out[0] = x;
      out[1] = y;
      return out;
    }
    function copy(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      return out;
    }
    function set(out, x, y) {
      out[0] = x;
      out[1] = y;
      return out;
    }
    function add(out, a, b) {
      out[0] = a[0] + b[0];
      out[1] = a[1] + b[1];
      return out;
    }
    function subtract(out, a, b) {
      out[0] = a[0] - b[0];
      out[1] = a[1] - b[1];
      return out;
    }
    function multiply(out, a, b) {
      out[0] = a[0] * b[0];
      out[1] = a[1] * b[1];
      return out;
    }
    ;
    function divide(out, a, b) {
      out[0] = a[0] / b[0];
      out[1] = a[1] / b[1];
      return out;
    }
    ;
    function ceil(out, a) {
      out[0] = Math.ceil(a[0]);
      out[1] = Math.ceil(a[1]);
      return out;
    }
    ;
    function floor(out, a) {
      out[0] = Math.floor(a[0]);
      out[1] = Math.floor(a[1]);
      return out;
    }
    ;
    function min(out, a, b) {
      out[0] = Math.min(a[0], b[0]);
      out[1] = Math.min(a[1], b[1]);
      return out;
    }
    ;
    function max(out, a, b) {
      out[0] = Math.max(a[0], b[0]);
      out[1] = Math.max(a[1], b[1]);
      return out;
    }
    ;
    function round(out, a) {
      out[0] = Math.round(a[0]);
      out[1] = Math.round(a[1]);
      return out;
    }
    ;
    function scale(out, a, b) {
      out[0] = a[0] * b;
      out[1] = a[1] * b;
      return out;
    }
    ;
    function scaleAndAdd(out, a, b, scale) {
      out[0] = a[0] + b[0] * scale;
      out[1] = a[1] + b[1] * scale;
      return out;
    }
    ;
    function distance(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1];
      return Math.sqrt(x * x + y * y);
    }
    ;
    function squaredDistance(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1];
      return x * x + y * y;
    }
    ;
    function length(a) {
      var x = a[0],
          y = a[1];
      return Math.sqrt(x * x + y * y);
    }
    ;
    function squaredLength(a) {
      var x = a[0],
          y = a[1];
      return x * x + y * y;
    }
    ;
    function negate(out, a) {
      out[0] = -a[0];
      out[1] = -a[1];
      return out;
    }
    ;
    function inverse(out, a) {
      out[0] = 1.0 / a[0];
      out[1] = 1.0 / a[1];
      return out;
    }
    ;
    function normalize(out, a) {
      var x = a[0],
          y = a[1];
      var len = x * x + y * y;
      if (len > 0) {
        len = 1 / Math.sqrt(len);
        out[0] = a[0] * len;
        out[1] = a[1] * len;
      }
      return out;
    }
    ;
    function dot(a, b) {
      return a[0] * b[0] + a[1] * b[1];
    }
    ;
    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;
    }
    ;
    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;
    }
    ;
    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;
    }
    ;
    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;
    }
    ;
    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;
    }
    ;
    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;
    }
    ;
    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;
    }
    function str(a) {
      return 'vec2(' + a[0] + ', ' + a[1] + ')';
    }
    function exactEquals(a, b) {
      return a[0] === b[0] && a[1] === b[1];
    }
    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));
    }
    var len = exports.len = length;
    var sub = exports.sub = subtract;
    var mul = exports.mul = multiply;
    var div = exports.div = divide;
    var dist = exports.dist = distance;
    var sqrDist = exports.sqrDist = squaredDistance;
    var sqrLen = exports.sqrLen = squaredLength;
    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;
        }
        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;
      };
    }();
  })]);
});

})();
(function() {
var define = $__System.amdDefine;
define("32", ["31"], function(main) {
  return main;
});

})();
(function() {
var define = $__System.amdDefine;
(function webpackUniversalModuleDefinition(root, factory) {
  if (typeof exports === 'object' && typeof module === 'object')
    module.exports = factory(require("gl-matrix"));
  else if (typeof define === 'function' && define.amd)
    define("33", ["32"], factory);
  else if (typeof exports === 'object')
    exports["blenderHTML5Animations"] = factory(require("gl-matrix"));
  else
    root["blenderHTML5Animations"] = factory(root["window"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_2__) {
  return (function(modules) {
    var installedModules = {};
    function __webpack_require__(moduleId) {
      if (installedModules[moduleId])
        return installedModules[moduleId].exports;
      var module = installedModules[moduleId] = {
        exports: {},
        id: moduleId,
        loaded: false
      };
      modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
      module.loaded = true;
      return module.exports;
    }
    __webpack_require__.m = modules;
    __webpack_require__.c = installedModules;
    __webpack_require__.p = "";
    return __webpack_require__(0);
  })([function(module, exports, __webpack_require__) {
    'use strict';
    module.exports.Action = __webpack_require__(1);
    module.exports.ActionLibrary = __webpack_require__(9);
    module.exports.FCurve = __webpack_require__(4);
    module.exports.FCurveArray = __webpack_require__(3);
    module.exports.Keyframe = __webpack_require__(7);
    module.exports.Marker = __webpack_require__(8);
  }, function(module, exports, __webpack_require__) {
    'use strict';
    var glMatrixLib = __webpack_require__(2);
    var glMatrix = glMatrixLib.glMatrix;
    var mat4 = glMatrixLib.mat4;
    var vec3 = glMatrixLib.vec3;
    var FCurveArray = __webpack_require__(3);
    var Marker = __webpack_require__(8);
    function Action(data) {
      var self = this;
      this.startTime = +Infinity;
      this.endTime = -Infinity;
      function timeUpdater(fcurve) {
        if (fcurve) {
          self.startTime = Math.min(self.startTime, fcurve.keyframes[0].time);
          self.endTime = Math.max(self.endTime, fcurve.keyframes[fcurve.keyframes.length - 1].time);
        }
      }
      this.paths = {};
      for (var groupName in data[0]) {
        var path = new FCurveArray(data[0][groupName]);
        this.paths[groupName] = path;
        path.forEach(timeUpdater);
      }
      this.markers = data.length > 1 ? data[1].map(function(data) {
        return new Marker(data);
      }) : [];
    }
    Action.RotationMode = {
      QUATERNION: 0,
      EULER_XYZ: 1,
      EULER_YXZ: 3,
      EULER_XZY: 2,
      EULER_ZXY: 5,
      EULER_YZX: 4,
      EULER_ZYX: 6,
      AXIS_ANGLE: -1
    };
    Action.prototype.forEachMarker = function(startTime, endTime, callback) {
      return this.markers.forEach(function(marker, index) {
        if (marker.time >= startTime && marker.time < endTime)
          return callback(marker, index);
      });
    };
    var qmat = new glMatrix.ARRAY_TYPE(16);
    Action.prototype.toWorld = function(out, time, rotationMode) {
      mat4.identity(out);
      var paths = this.paths;
      var angles;
      function computeEulerAngles() {
        angles = vec3.fromValues(0, 0, 0);
        [paths.rotation_euler, paths.delta_rotation_euler].forEach(function(path) {
          if (path)
            vec3.add(angles, angles, path.evaluate(time, FCurveArray.DefaultValues.ROTATION));
        });
      }
      var location = vec3.fromValues(0, 0, 0);
      [paths.location, paths.delta_location].forEach(function(path) {
        if (path)
          vec3.add(location, location, path.evaluate(time, FCurveArray.DefaultValues.LOCATION));
      });
      mat4.translate(out, out, location);
      switch (rotationMode) {
        case Action.RotationMode.QUATERNION:
          [paths.rotation_quaternion, paths.delta_rotation_quaternion].forEach(function(path) {
            if (path) {
              mat4.fromQuat(qmat, path.evaluate(time, FCurveArray.DefaultValues.ROTATION_QUATERNION));
              mat4.multiply(out, out, qmat);
            }
          });
          break;
        case Action.RotationMode.EULER_XYZ:
          computeEulerAngles();
          mat4.rotateZ(out, out, angles[2]);
          mat4.rotateY(out, out, angles[1]);
          mat4.rotateX(out, out, angles[0]);
          break;
        case Action.RotationMode.EULER_XZY:
          computeEulerAngles();
          mat4.rotateY(out, out, angles[1]);
          mat4.rotateZ(out, out, angles[2]);
          mat4.rotateX(out, out, angles[0]);
          break;
        case Action.RotationMode.EULER_YXZ:
          computeEulerAngles();
          mat4.rotateZ(out, out, angles[2]);
          mat4.rotateX(out, out, angles[0]);
          mat4.rotateY(out, out, angles[1]);
          break;
        case Action.RotationMode.EULER_YZX:
          computeEulerAngles();
          mat4.rotateX(out, out, angles[0]);
          mat4.rotateZ(out, out, angles[2]);
          mat4.rotateY(out, out, angles[1]);
          break;
        case Action.RotationMode.EULER_ZXY:
          computeEulerAngles();
          mat4.rotateY(out, out, angles[1]);
          mat4.rotateX(out, out, angles[0]);
          mat4.rotateZ(out, out, angles[2]);
          break;
        case Action.RotationMode.EULER_ZYX:
          computeEulerAngles();
          mat4.rotateX(out, out, angles[0]);
          mat4.rotateY(out, out, angles[1]);
          mat4.rotateZ(out, out, angles[2]);
          break;
        case Action.RotationMode.AXIS_ANGLE:
          if (paths.rotation_axis) {
            var vec = paths.rotation_axis.evaluate(time, FCurveArray.DefaultValues.ROTATION);
            mat4.rotate(out, out, vec[3], vec);
          }
          break;
      }
      var scale = vec3.fromValues(1, 1, 1);
      [paths.scale, paths.delta_scale].forEach(function(path) {
        if (path)
          vec3.multiply(scale, scale, path.evaluate(time, FCurveArray.DefaultValues.SCALE));
      });
      mat4.scale(out, out, scale);
      return out;
    };
    Action.prototype.toLocal = function(out, time, rotationMode) {
      this.toWorld(out, time, rotationMode);
      mat4.invert(out, out);
      return out;
    };
    Action.prototype.setElementTransform = function(element, time, rotationMode) {
      var mat = new glMatrix.ARRAY_TYPE(16);
      this.toWorld(mat, time, rotationMode);
      var transform = 'matrix3d(' + mat.join(',') + ')';
      ['transform', 'mozTransform', 'oTransform', 'webkitTransform'].forEach(function(property) {
        element.style[property] = transform;
      });
    };
    module.exports = Action;
  }, function(module, exports) {
    module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
  }, function(module, exports, __webpack_require__) {
    'use strict';
    var FCurve = __webpack_require__(4);
    function FCurveArray(data) {
      var array = data.map(function(data) {
        return data && new FCurve(data);
      });
      array.evaluate = function(time, defaultValues) {
        return array.map(function(fcurve, index) {
          return fcurve ? fcurve.evaluate(time) : defaultValues(index, time);
        });
      };
      return array;
    }
    FCurveArray.DefaultValues = {
      LOCATION: function() {
        return 0;
      },
      ROTATION: function() {
        return 0;
      },
      ROTATION_QUATERNION: function(index) {
        return (index === 3 ? 1 : 0);
      },
      SCALE: function() {
        return 1;
      }
    };
    module.exports = FCurveArray;
  }, function(module, exports, __webpack_require__) {
    'use strict';
    var bezier = __webpack_require__(5);
    var easing = __webpack_require__(6);
    var Keyframe = __webpack_require__(7);
    function FCurve(data) {
      this.keyframes = data[0].map(function(data) {
        return new Keyframe(data);
      });
      this.extrapolation = data[1];
    }
    FCurve.Extrapolation = {
      CONSTANT: 0,
      LINEAR: 1
    };
    FCurve.evaluationTimeEpsilon = 0.0001;
    function areTimesAlmostEqual(t1, t2) {
      return Math.abs(t1 - t2) <= FCurve.evaluationTimeEpsilon;
    }
    FCurve.prototype.evaluate = function(time) {
      var leftIndex = 0;
      var leftKeyframe = this.keyframes[leftIndex];
      if (areTimesAlmostEqual(time, leftKeyframe.time)) {
        return leftKeyframe.value;
      }
      if (time <= leftKeyframe.time) {
        switch (this.extrapolation) {
          case FCurve.Extrapolation.LINEAR:
            return leftKeyframe.value + (leftKeyframe.leftValue - leftKeyframe.value) * (time - leftKeyframe.time) / (leftKeyframe.leftTime - leftKeyframe.time);
          default:
            return leftKeyframe.value;
        }
      }
      var rightIndex = this.keyframes.length - 1;
      var rightKeyframe = this.keyframes[rightIndex];
      if (areTimesAlmostEqual(time, rightKeyframe.time)) {
        return rightKeyframe.value;
      }
      if (time >= rightKeyframe.time) {
        switch (this.extrapolation) {
          case FCurve.Extrapolation.LINEAR:
            return rightKeyframe.value + (rightKeyframe.rightValue - rightKeyframe.value) * (time - rightKeyframe.time) / (rightKeyframe.rightTime - rightKeyframe.time);
          default:
            return rightKeyframe.value;
        }
      }
      while (rightIndex - leftIndex > 1) {
        var index = ((leftIndex + rightIndex) / 2) | 0;
        if (this.keyframes[index].time >= time)
          rightIndex = index;
        else
          leftIndex = index;
      }
      leftKeyframe = this.keyframes[leftIndex];
      if (areTimesAlmostEqual(time, leftKeyframe.time)) {
        return leftKeyframe.value;
      }
      rightKeyframe = this.keyframes[rightIndex];
      if (areTimesAlmostEqual(time, rightKeyframe.time)) {
        return rightKeyframe.value;
      }
      var relTime = time - leftKeyframe.time;
      var begin = leftKeyframe.value;
      var duration = rightKeyframe.time - leftKeyframe.time;
      var change = rightKeyframe.value - leftKeyframe.value;
      switch (leftKeyframe.interpolation) {
        case Keyframe.Interpolation.BACK:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.IN:
              return easing.backEaseIn(relTime, begin, change, duration, leftKeyframe.overshoot);
            case Keyframe.Easing.IN_OUT:
              return easing.backEaseInOut(relTime, begin, change, duration, leftKeyframe.overshoot);
            default:
              return easing.backEaseOut(relTime, begin, change, duration, leftKeyframe.overshoot);
          }
          break;
        case Keyframe.Interpolation.BEZIER:
          return bezier(time, leftKeyframe, rightKeyframe);
        case Keyframe.Interpolation.BOUNCE:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.IN:
              return easing.bounceEaseIn(relTime, begin, change, duration);
            case Keyframe.Easing.IN_OUT:
              return easing.bounceEaseInOut(relTime, begin, change, duration);
            default:
              return easing.bounceEaseOut(relTime, begin, change, duration);
          }
          break;
        case Keyframe.Interpolation.CIRCULAR:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.OUT:
              return easing.circularEaseOut(relTime, begin, change, duration);
            case Keyframe.Easing.IN_OUT:
              return easing.circularEaseInOut(relTime, begin, change, duration);
            default:
              return easing.circularEaseIn(relTime, begin, change, duration);
          }
          break;
        case Keyframe.Interpolation.CUBIC:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.OUT:
              return easing.cubicEaseOut(relTime, begin, change, duration);
            case Keyframe.Easing.IN_OUT:
              return easing.cubicEaseInOut(relTime, begin, change, duration);
            default:
              return easing.cubicEaseIn(relTime, begin, change, duration);
          }
          break;
        case Keyframe.Interpolation.ELASTIC:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.IN:
              return easing.elasticEaseIn(relTime, begin, change, duration);
            case Keyframe.Easing.IN_OUT:
              return easing.elasticEaseInOut(relTime, begin, change, duration);
            default:
              return easing.elasticEaseOut(relTime, begin, change, duration, leftKeyframe.amplitude, leftKeyframe.period);
          }
          break;
        case Keyframe.Interpolation.EXPONENTIAL:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.OUT:
              return easing.exponentialEaseOut(relTime, begin, change, duration);
            case Keyframe.Keyframe.Easing.IN_OUT:
              return easing.exponentialEaseInOut(relTime, begin, change, duration);
            default:
              return easing.exponentialEaseIn(relTime, begin, change, duration);
          }
          break;
        case Keyframe.Interpolation.LINEAR:
          return easing.linear(relTime, begin, change, duration);
        case Keyframe.Interpolation.QUADRATIC:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.OUT:
              return easing.quadraticEaseOut(relTime, begin, change, duration);
            case Keyframe.Easing.IN_OUT:
              return easing.quadraticEaseInOut(relTime, begin, change, duration);
            default:
              return easing.quadraticEaseIn(relTime, begin, change, duration);
          }
          break;
        case Keyframe.Interpolation.QUARTIC:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.OUT:
              return easing.quarticEaseOut(relTime, begin, change, duration);
            case Keyframe.Easing.IN_OUT:
              return easing.quarticEaseInOut(relTime, begin, change, duration);
            default:
              return easing.quarticEaseIn(relTime, begin, change, duration);
          }
          break;
        case Keyframe.Interpolation.QUINTIC:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.OUT:
              return easing.quinticEaseOut(relTime, begin, change, duration);
            case Keyframe.Easing.IN_OUT:
              return easing.quinticEaseInOut(relTime, begin, change, duration);
            default:
              return easing.quinticEaseIn(relTime, begin, change, duration);
          }
          break;
        case Keyframe.Interpolation.SINUSOIDAL:
          switch (leftKeyframe.easing) {
            case Keyframe.Easing.OUT:
              return easing.sinusoidalEaseOut(relTime, begin, change, duration);
            case Keyframe.Easing.IN_OUT:
              return easing.sinusoidalEaseInOut(relTime, begin, change, duration);
            default:
              return easing.sinusoidalEaseIn(relTime, begin, change, duration);
          }
          break;
        default:
          return begin;
      }
    };
    module.exports = FCurve;
  }, function(module, exports) {
    'use strict';
    function bezierInterpolation(A, B, C, D, t) {
      var T = 1 - t;
      return T * T * T * A + 3 * T * T * t * B + 3 * T * t * t * C + t * t * t * D;
    }
    function bezier(time, leftKeyframe, rightKeyframe) {
      var aT = leftKeyframe.time;
      var aV = leftKeyframe.value;
      var bT = leftKeyframe.rightTime;
      var bV = leftKeyframe.rightValue;
      var cT = rightKeyframe.leftTime;
      var cV = rightKeyframe.leftValue;
      var dT = rightKeyframe.time;
      var dV = rightKeyframe.value;
      var leftDeltaTime = bT - aT;
      var rightDeltaTime = dT - cT;
      var duration = dT - aT;
      if (leftDeltaTime + rightDeltaTime > duration) {
        var leftDeltaValue = bV - aV;
        var rightDeltaValue = dV - cV;
        var factor = duration / (leftDeltaTime + rightDeltaTime);
        bT = aT + factor * leftDeltaTime;
        bV = aV + factor * leftDeltaValue;
        cT = dT - factor * rightDeltaTime;
        cV = dV - factor * rightDeltaValue;
      }
      var uLeft = 0,
          uRight = 1;
      var u,
          T;
      do {
        u = (uLeft + uRight) / 2;
        T = bezierInterpolation(aT, bT, cT, dT, u);
        if (T > time)
          uRight = u;
        else
          uLeft = u;
      } while (Math.abs(T - time) > 0.01);
      return bezierInterpolation(aV, bV, cV, dV, u);
    }
    module.exports = bezier;
  }, function(module, exports) {
    'use strict';
    function backEaseIn(time, begin, change, duration, overshoot) {
      time /= duration;
      return change * time * time * ((overshoot + 1) * time - overshoot) + begin;
    }
    function backEaseOut(time, begin, change, duration, overshoot) {
      time = time / duration - 1;
      return change * (time * time * ((overshoot + 1) * time + overshoot) + 1) + begin;
    }
    function backEaseInOut(time, begin, change, duration, overshoot) {
      overshoot *= 1.525;
      if ((time /= duration / 2) < 1) {
        return change / 2 * (time * time * ((overshoot + 1) * time - overshoot)) + begin;
      }
      time -= 2.0;
      return change / 2 * (time * time * ((overshoot + 1) * time + overshoot) + 2) + begin;
    }
    function bounceEaseOut(time, begin, change, duration) {
      time /= duration;
      if (time < (1 / 2.75)) {
        return change * (7.5625 * time * time) + begin;
      } else if (time < (2 / 2.75)) {
        time -= (1.5 / 2.75);
        return change * ((7.5625 * time) * time + 0.75) + begin;
      } else if (time < (2.5 / 2.75)) {
        time -= (2.25 / 2.75);
        return change * ((7.5625 * time) * time + 0.9375) + begin;
      } else {
        time -= (2.625 / 2.75);
        return change * ((7.5625 * time) * time + 0.984375) + begin;
      }
    }
    function bounceEaseIn(time, begin, change, duration) {
      return change - bounceEaseOut(duration - time, 0, change, duration) + begin;
    }
    function bounceEaseInOut(time, begin, change, duration) {
      if (time < duration / 2)
        return bounceEaseIn(time * 2, 0, change, duration) * 0.5 + begin;
      else
        return bounceEaseOut(time * 2 - duration, 0, change, duration) * 0.5 + change * 0.5 + begin;
    }
    function circularEaseIn(time, begin, change, duration) {
      time /= duration;
      return -change * (Math.sqrt(1 - time * time) - 1) + begin;
    }
    function circularEaseOut(time, begin, change, duration) {
      time = time / duration - 1;
      return change * Math.sqrt(1 - time * time) + begin;
    }
    function circularEaseInOut(time, begin, change, duration) {
      if ((time /= duration / 2) < 1.0)
        return -change / 2 * (Math.sqrt(1 - time * time) - 1) + begin;
      time -= 2.0;
      return change / 2 * (Math.sqrt(1 - time * time) + 1) + begin;
    }
    function cubicEaseIn(time, begin, change, duration) {
      time /= duration;
      return change * time * time * time + begin;
    }
    function cubicEaseOut(time, begin, change, duration) {
      time = time / duration - 1;
      return change * (time * time * time + 1) + begin;
    }
    function cubicEaseInOut(time, begin, change, duration) {
      if ((time /= duration / 2) < 1.0)
        return change / 2 * time * time * time + begin;
      time -= 2.0;
      return change / 2 * (time * time * time + 2) + begin;
    }
    function elasticBlend(time, change, duration, amplitude, s, f) {
      if (change) {
        var t = Math.abs(s);
        if (amplitude) {
          f *= amplitude / Math.abs(change);
        } else {
          f = 0;
        }
        var td = Math.abs(time * duration);
        if (td < t) {
          var l = td / t;
          f = (f * l) + (1 - l);
        }
      }
      return f;
    }
    function elasticEaseIn(time, begin, change, duration, amplitude, period) {
      var s;
      var f = 1.0;
      if (time <= 0.0)
        return begin;
      if ((time /= duration) >= 1.0)
        return begin + change;
      time -= 1.0;
      if (!period)
        period = duration * 0.3;
      if (!amplitude || amplitude < Math.abs(change)) {
        s = period / 4;
        f = elasticBlend(time, change, duration, amplitude, s, f);
        amplitude = change;
      } else
        s = period / (2 * Math.PI) * Math.asin(change / amplitude);
      return (-f * (amplitude * Math.pow(2, 10 * time) * Math.sin((time * duration - s) * (2 * Math.PI) / period))) + begin;
    }
    function elasticEaseOut(time, begin, change, duration, amplitude, period) {
      var s;
      var f = 1;
      if (time <= 0)
        return begin;
      if ((time /= duration) >= 1.0)
        return begin + change;
      time = -time;
      if (!period)
        period = duration * 0.3;
      if (!amplitude || amplitude < Math.abs(change)) {
        s = period / 4;
        f = elasticBlend(time, change, duration, amplitude, s, f);
        amplitude = change;
      } else
        s = period / (2 * Math.PI) * Math.asin(change / amplitude);
      return (f * (amplitude * Math.pow(2, 10 * time) * Math.sin((time * duration - s) * (2 * Math.PI) / period))) + change + begin;
    }
    function elasticEaseInOut(time, begin, change, duration, amplitude, period) {
      var s;
      var f = 1.0;
      if (time <= 0.0)
        return begin;
      if ((time /= duration / 2) >= 2.0)
        return begin + change;
      time -= 1.0;
      if (!period)
        period = duration * (0.3 * 1.5);
      if (!amplitude || amplitude < Math.abs(change)) {
        s = period / 4;
        f = elasticBlend(time, change, duration, amplitude, s, f);
        amplitude = change;
      } else
        s = period / (2 * Math.PI) * Math.asin(change / amplitude);
      if (time < 0.0) {
        f *= -0.5;
        return (f * (amplitude * Math.pow(2, 10 * time) * Math.sin((time * duration - s) * (2 * Math.PI) / period))) + begin;
      } else {
        time = -time;
        f *= 0.5;
        return (f * (amplitude * Math.pow(2, 10 * time) * Math.sin((time * duration - s) * (2 * Math.PI) / period))) + change + begin;
      }
    }
    function exponentialEaseIn(time, begin, change, duration) {
      return (time <= 0.0) ? begin : change * Math.pow(2, 10 * (time / duration - 1)) + begin;
    }
    function exponentialEaseOut(time, begin, change, duration) {
      return (time >= duration) ? begin + change : change * (-Math.pow(2, -10 * time / duration) + 1) + begin;
    }
    function exponentialEaseInOut(time, begin, change, duration) {
      if (time <= 0.0)
        return begin;
      if (time >= duration)
        return begin + change;
      if ((time /= duration / 2) < 1)
        return change / 2 * Math.pow(2, 10 * (time - 1)) + begin;
      time -= 1.0;
      return change / 2 * (-Math.pow(2, -10 * time) + 2) + begin;
    }
    function linear(time, begin, change, duration) {
      return change * time / duration + begin;
    }
    function quadraticEaseIn(time, begin, change, duration) {
      time /= duration;
      return change * time * time + begin;
    }
    function quadraticEaseOut(time, begin, change, duration) {
      time /= duration;
      return -change * time * (time - 2) + begin;
    }
    function quadraticEaseInOut(time, begin, change, duration) {
      if ((time /= duration / 2) < 1.0)
        return change / 2 * time * time + begin;
      time -= 1.0;
      return -change / 2 * (time * (time - 2) - 1) + begin;
    }
    function quarticEaseIn(time, begin, change, duration) {
      time /= duration;
      return change * time * time * time * time + begin;
    }
    function quarticEaseOut(time, begin, change, duration) {
      time = time / duration - 1;
      return -change * (time * time * time * time - 1) + begin;
    }
    function quarticEaseInOut(time, begin, change, duration) {
      if ((time /= duration / 2) < 1.0)
        return change / 2 * time * time * time * time + begin;
      time -= 2.0;
      return -change / 2 * (time * time * time * time - 2) + begin;
    }
    function quinticEaseIn(time, begin, change, duration) {
      time /= duration;
      return change * time * time * time * time * time + begin;
    }
    function quinticEaseOut(time, begin, change, duration) {
      time = time / duration - 1;
      return change * (time * time * time * time * time + 1) + begin;
    }
    function quinticEaseInOut(time, begin, change, duration) {
      if ((time /= duration / 2) < 1.0)
        return change / 2 * time * time * time * time * time + begin;
      time -= 2.0;
      return change / 2 * (time * time * time * time * time + 2) + begin;
    }
    function sinusoidalEaseIn(time, begin, change, duration) {
      return -change * Math.cos(time / duration * Math.PI / 2) + change + begin;
    }
    function sinusoidalEaseOut(time, begin, change, duration) {
      return change * Math.sin(time / duration * Math.PI / 2) + begin;
    }
    function sinusoidalEaseInOut(time, begin, change, duration) {
      return -change / 2 * (Math.cos(Math.PI * time / duration) - 1) + begin;
    }
    module.exports.backEaseIn = backEaseIn;
    module.exports.backEaseOut = backEaseOut;
    module.exports.backEaseInOut = backEaseInOut;
    module.exports.bounceEaseOut = bounceEaseOut;
    module.exports.bounceEaseIn = bounceEaseIn;
    module.exports.bounceEaseInOut = bounceEaseInOut;
    module.exports.circularEaseIn = circularEaseIn;
    module.exports.circularEaseOut = circularEaseOut;
    module.exports.circularEaseInOut = circularEaseInOut;
    module.exports.cubicEaseIn = cubicEaseIn;
    module.exports.cubicEaseOut = cubicEaseOut;
    module.exports.cubicEaseInOut = cubicEaseInOut;
    module.exports.elasticEaseIn = elasticEaseIn;
    module.exports.elasticEaseOut = elasticEaseOut;
    module.exports.elasticEaseInOut = elasticEaseInOut;
    module.exports.exponentialEaseIn = exponentialEaseIn;
    module.exports.exponentialEaseOut = exponentialEaseOut;
    module.exports.exponentialEaseInOut = exponentialEaseInOut;
    module.exports.linear = linear;
    module.exports.quadraticEaseIn = quadraticEaseIn;
    module.exports.quadraticEaseOut = quadraticEaseOut;
    module.exports.quadraticEaseInOut = quadraticEaseInOut;
    module.exports.quarticEaseIn = quarticEaseIn;
    module.exports.quarticEaseOut = quarticEaseOut;
    module.exports.quarticEaseInOut = quarticEaseInOut;
    module.exports.quinticEaseIn = quinticEaseIn;
    module.exports.quinticEaseOut = quinticEaseOut;
    module.exports.quinticEaseInOut = quinticEaseInOut;
    module.exports.sinusoidalEaseIn = sinusoidalEaseIn;
    module.exports.sinusoidalEaseOut = sinusoidalEaseOut;
    module.exports.sinusoidalEaseInOut = sinusoidalEaseInOut;
  }, function(module, exports) {
    'use strict';
    function Keyframe(data) {
      this.time = data[0];
      this.value = data[1];
      this.leftTime = data[2];
      this.leftValue = data[3];
      this.rightTime = data[4];
      this.rightValue = data[5];
      this.interpolation = data[6];
      this.easing = data[7];
      this.overshoot = data[8];
      this.amplitude = data[8];
      this.period = data[9];
    }
    Keyframe.Easing = {
      AUTO: 0,
      IN: 1,
      OUT: 2,
      IN_OUT: 3
    };
    Keyframe.Interpolation = {
      CONSTANT: 0,
      LINEAR: 1,
      BEZIER: 2,
      BACK: 3,
      BOUNCE: 4,
      CIRCULAR: 5,
      CUBIC: 6,
      ELASTIC: 7,
      EXPONENTIAL: 8,
      QUADRATIC: 9,
      QUARTIC: 10,
      QUINTIC: 11,
      SINUSOIDAL: 12
    };
    module.exports = Keyframe;
  }, function(module, exports) {
    'use strict';
    function Marker(data) {
      this.time = data[0];
      this.name = data[1];
    }
    module.exports = Marker;
  }, function(module, exports, __webpack_require__) {
    'use strict';
    var Action = __webpack_require__(1);
    function ActionLibrary(data) {
      for (var actionName in data) {
        this[actionName] = new Action(data[actionName]);
      }
    }
    module.exports = ActionLibrary;
  }]);
});
;

})();
$__System.register('34', ['33'], function (_export) {
	'use strict';

	var blenderHTML5Animations;
	return {
		setters: [function (_) {
			blenderHTML5Animations = _['default'];
		}],
		execute: function () {
			_export('default', function (actionDescriptors) {
				var actions = new blenderHTML5Animations.ActionLibrary(actionDescriptors);

				function evaluate(matrix, actionName, time) {
					return actions[actionName].toWorld(matrix.elements, time, blenderHTML5Animations.Action.RotationMode.EULER_XYZ);
				}

				function getPosition(actionName, time) {
					return actions[actionName].paths['location'].evaluate(time, blenderHTML5Animations.FCurveArray.DefaultValues.LOCATION);
				}

				function getRotation(actionName, time) {
					return actions[actionName].paths['rotation_euler'].evaluate(time, blenderHTML5Animations.FCurveArray.DefaultValues.ROTATION);
				}

				function getValue(actionName, time) {
					var pos = actions[actionName].paths['location'].evaluate(time, blenderHTML5Animations.FCurveArray.DefaultValues.LOCATION);
					return pos[2];
				}

				return {
					actions: actions,
					evaluate: evaluate,
					getPosition: getPosition,
					getRotation: getRotation,
					getValue: getValue
				};
			});
		}
	};
});

$__System.register("11", [], function (_export) {
	"use strict";

	return {
		setters: [],
		execute: function () {
			_export("default", {
				time: { value: 1.0 },
				frameScene: { value: 0 },
				frameRaymarch: { value: 0 },
				frameText: { value: 0 },
				frameTextureText: { value: 0 },
				resolution: { value: [window.innerWidth, window.innerHeight] }
			});
		}
	};
});

$__System.register('35', ['3'], function (_export) {
				/**
     * @author mrdoob / http://mrdoob.com/
     */

				'use strict';

				var THREE, OBJLoader;
				return {
								setters: [function (_) {
												THREE = _;
								}],
								execute: function () {
												OBJLoader = function OBJLoader(manager) {

																this.manager = manager !== undefined ? manager : THREE.DefaultLoadingManager;

																this.material = null;

																this.regexp = {
																				// v float float float
																				vertex_pattern: /^v\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
																				// vn float float float
																				normal_pattern: /^vn\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
																				// vt float float
																				uv_pattern: /^vt\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
																				// f vertex vertex vertex
																				face_vertex: /^f\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)(?:\s+(-?\d+))?/,
																				// f vertex/uv vertex/uv vertex/uv
																				face_vertex_uv: /^f\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+))?/,
																				// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
																				face_vertex_uv_normal: /^f\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+)\/(-?\d+))?/,
																				// f vertex//normal vertex//normal vertex//normal
																				face_vertex_normal: /^f\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)(?:\s+(-?\d+)\/\/(-?\d+))?/,
																				// o object_name | g group_name
																				object_pattern: /^[og]\s*(.+)?/,
																				// s boolean
																				smoothing_pattern: /^s\s+(\d+|on|off)/,
																				// mtllib file_reference
																				material_library_pattern: /^mtllib /,
																				// usemtl material_name
																				material_use_pattern: /^usemtl /
																};
												};

												_export('OBJLoader', OBJLoader);

												OBJLoader.prototype = {

																constructor: OBJLoader,

																load: function load(url, onLoad, onProgress, onError) {

																				var scope = this;

																				var loader = new THREE.FileLoader(scope.manager);
																				loader.setPath(this.path);
																				loader.load(url, function (text) {

																								onLoad(scope.parse(text));
																				}, onProgress, onError);
																},

																setPath: function setPath(value) {

																				this.path = value;
																},

																setMaterials: function setMaterials(material) {

																				this.material = material;
																},

																_createParserState: function _createParserState() {

																				var state = {
																								objects: [],
																								object: {},

																								vertices: [],
																								normals: [],
																								uvs: [],

																								materialLibraries: [],

																								startObject: function startObject(name, fromDeclaration) {

																												// If the current object (initial from reset) is not from a g/o declaration in the parsed
																												// file. We need to use it for the first parsed g/o to keep things in sync.
																												if (this.object && this.object.fromDeclaration === false) {

																																this.object.name = name;
																																this.object.fromDeclaration = fromDeclaration !== false;
																																return;
																												}

																												var previousMaterial = this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined;

																												if (this.object && typeof this.object._finalize === 'function') {

																																this.object._finalize(true);
																												}

																												this.object = {
																																name: name || '',
																																fromDeclaration: fromDeclaration !== false,

																																geometry: {
																																				vertices: [],
																																				normals: [],
																																				uvs: []
																																},
																																material: [],
																																smooth: true,

																																startMaterial: function startMaterial(name, libraries) {

																																				var previous = this._finalize(false);

																																				// New usemtl declaration overwrites an inherited material, except if faces were declared
																																				// after the material, then it must be preserved for proper MultiMaterial continuation.
																																				if (previous && (previous.inherited || previous.groupCount <= 0)) {

																																								this.material.splice(previous.index, 1);
																																				}

																																				var material = {
																																								index: this.material.length,
																																								name: name || '',
																																								mtllib: Array.isArray(libraries) && libraries.length > 0 ? libraries[libraries.length - 1] : '',
																																								smooth: previous !== undefined ? previous.smooth : this.smooth,
																																								groupStart: previous !== undefined ? previous.groupEnd : 0,
																																								groupEnd: -1,
																																								groupCount: -1,
																																								inherited: false,

																																								clone: function clone(index) {
																																												var cloned = {
																																																index: typeof index === 'number' ? index : this.index,
																																																name: this.name,
																																																mtllib: this.mtllib,
																																																smooth: this.smooth,
																																																groupStart: 0,
																																																groupEnd: -1,
																																																groupCount: -1,
																																																inherited: false
																																												};
																																												cloned.clone = this.clone.bind(cloned);
																																												return cloned;
																																								}
																																				};

																																				this.material.push(material);

																																				return material;
																																},

																																currentMaterial: function currentMaterial() {

																																				if (this.material.length > 0) {
																																								return this.material[this.material.length - 1];
																																				}

																																				return undefined;
																																},

																																_finalize: function _finalize(end) {

																																				var lastMultiMaterial = this.currentMaterial();
																																				if (lastMultiMaterial && lastMultiMaterial.groupEnd === -1) {

																																								lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
																																								lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
																																								lastMultiMaterial.inherited = false;
																																				}

																																				// Ignore objects tail material if no face declarations followed them before a new o/g started.
																																				if (end && this.material.length > 1) {

																																								for (var mi = this.material.length - 1; mi >= 0; mi--) {
																																												if (this.material[mi].groupCount <= 0) {
																																																this.material.splice(mi, 1);
																																												}
																																								}
																																				}

																																				// Guarantee at least one empty material, this makes the creation later more straight forward.
																																				if (end && this.material.length === 0) {

																																								this.material.push({
																																												name: '',
																																												smooth: this.smooth
																																								});
																																				}

																																				return lastMultiMaterial;
																																}
																												};

																												// Inherit previous objects material.
																												// Spec tells us that a declared material must be set to all objects until a new material is declared.
																												// If a usemtl declaration is encountered while this new object is being parsed, it will
																												// overwrite the inherited material. Exception being that there was already face declarations
																												// to the inherited material, then it will be preserved for proper MultiMaterial continuation.

																												if (previousMaterial && previousMaterial.name && typeof previousMaterial.clone === "function") {

																																var declared = previousMaterial.clone(0);
																																declared.inherited = true;
																																this.object.material.push(declared);
																												}

																												this.objects.push(this.object);
																								},

																								finalize: function finalize() {

																												if (this.object && typeof this.object._finalize === 'function') {

																																this.object._finalize(true);
																												}
																								},

																								parseVertexIndex: function parseVertexIndex(value, len) {

																												var index = parseInt(value, 10);
																												return (index >= 0 ? index - 1 : index + len / 3) * 3;
																								},

																								parseNormalIndex: function parseNormalIndex(value, len) {

																												var index = parseInt(value, 10);
																												return (index >= 0 ? index - 1 : index + len / 3) * 3;
																								},

																								parseUVIndex: function parseUVIndex(value, len) {

																												var index = parseInt(value, 10);
																												return (index >= 0 ? index - 1 : index + len / 2) * 2;
																								},

																								addVertex: function addVertex(a, b, c) {

																												var src = this.vertices;
																												var dst = this.object.geometry.vertices;

																												dst.push(src[a + 0]);
																												dst.push(src[a + 1]);
																												dst.push(src[a + 2]);
																												dst.push(src[b + 0]);
																												dst.push(src[b + 1]);
																												dst.push(src[b + 2]);
																												dst.push(src[c + 0]);
																												dst.push(src[c + 1]);
																												dst.push(src[c + 2]);
																								},

																								addVertexLine: function addVertexLine(a) {

																												var src = this.vertices;
																												var dst = this.object.geometry.vertices;

																												dst.push(src[a + 0]);
																												dst.push(src[a + 1]);
																												dst.push(src[a + 2]);
																								},

																								addNormal: function addNormal(a, b, c) {

																												var src = this.normals;
																												var dst = this.object.geometry.normals;

																												dst.push(src[a + 0]);
																												dst.push(src[a + 1]);
																												dst.push(src[a + 2]);
																												dst.push(src[b + 0]);
																												dst.push(src[b + 1]);
																												dst.push(src[b + 2]);
																												dst.push(src[c + 0]);
																												dst.push(src[c + 1]);
																												dst.push(src[c + 2]);
																								},

																								addUV: function addUV(a, b, c) {

																												var src = this.uvs;
																												var dst = this.object.geometry.uvs;

																												dst.push(src[a + 0]);
																												dst.push(src[a + 1]);
																												dst.push(src[b + 0]);
																												dst.push(src[b + 1]);
																												dst.push(src[c + 0]);
																												dst.push(src[c + 1]);
																								},

																								addUVLine: function addUVLine(a) {

																												var src = this.uvs;
																												var dst = this.object.geometry.uvs;

																												dst.push(src[a + 0]);
																												dst.push(src[a + 1]);
																								},

																								addFace: function addFace(a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd) {

																												var vLen = this.vertices.length;

																												var ia = this.parseVertexIndex(a, vLen);
																												var ib = this.parseVertexIndex(b, vLen);
																												var ic = this.parseVertexIndex(c, vLen);
																												var id;

																												if (d === undefined) {

																																this.addVertex(ia, ib, ic);
																												} else {

																																id = this.parseVertexIndex(d, vLen);

																																this.addVertex(ia, ib, id);
																																this.addVertex(ib, ic, id);
																												}

																												if (ua !== undefined) {

																																var uvLen = this.uvs.length;

																																ia = this.parseUVIndex(ua, uvLen);
																																ib = this.parseUVIndex(ub, uvLen);
																																ic = this.parseUVIndex(uc, uvLen);

																																if (d === undefined) {

																																				this.addUV(ia, ib, ic);
																																} else {

																																				id = this.parseUVIndex(ud, uvLen);

																																				this.addUV(ia, ib, id);
																																				this.addUV(ib, ic, id);
																																}
																												}

																												if (na !== undefined) {

																																// Normals are many times the same. If so, skip function call and parseInt.
																																var nLen = this.normals.length;
																																ia = this.parseNormalIndex(na, nLen);

																																ib = na === nb ? ia : this.parseNormalIndex(nb, nLen);
																																ic = na === nc ? ia : this.parseNormalIndex(nc, nLen);

																																if (d === undefined) {

																																				this.addNormal(ia, ib, ic);
																																} else {

																																				id = this.parseNormalIndex(nd, nLen);

																																				this.addNormal(ia, ib, id);
																																				this.addNormal(ib, ic, id);
																																}
																												}
																								},

																								addLineGeometry: function addLineGeometry(vertices, uvs) {

																												this.object.geometry.type = 'Line';

																												var vLen = this.vertices.length;
																												var uvLen = this.uvs.length;

																												for (var vi = 0, l = vertices.length; vi < l; vi++) {

																																this.addVertexLine(this.parseVertexIndex(vertices[vi], vLen));
																												}

																												for (var uvi = 0, l = uvs.length; uvi < l; uvi++) {

																																this.addUVLine(this.parseUVIndex(uvs[uvi], uvLen));
																												}
																								}

																				};

																				state.startObject('', false);

																				return state;
																},

																parse: function parse(text) {

																				console.time('OBJLoader');

																				var state = this._createParserState();

																				if (text.indexOf('\r\n') !== -1) {

																								// This is faster than String.split with regex that splits on both
																								text = text.replace(/\r\n/g, '\n');
																				}

																				if (text.indexOf('\\\n') !== -1) {

																								// join lines separated by a line continuation character (\)
																								text = text.replace(/\\\n/g, '');
																				}

																				var lines = text.split('\n');
																				var line = '',
																				    lineFirstChar = '',
																				    lineSecondChar = '';
																				var lineLength = 0;
																				var result = [];

																				// Faster to just trim left side of the line. Use if available.
																				var trimLeft = typeof ''.trimLeft === 'function';

																				for (var i = 0, l = lines.length; i < l; i++) {

																								line = lines[i];

																								line = trimLeft ? line.trimLeft() : line.trim();

																								lineLength = line.length;

																								if (lineLength === 0) continue;

																								lineFirstChar = line.charAt(0);

																								// @todo invoke passed in handler if any
																								if (lineFirstChar === '#') continue;

																								if (lineFirstChar === 'v') {

																												lineSecondChar = line.charAt(1);

																												if (lineSecondChar === ' ' && (result = this.regexp.vertex_pattern.exec(line)) !== null) {

																																// 0                  1      2      3
																																// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]

																																state.vertices.push(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]));
																												} else if (lineSecondChar === 'n' && (result = this.regexp.normal_pattern.exec(line)) !== null) {

																																// 0                   1      2      3
																																// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]

																																state.normals.push(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]));
																												} else if (lineSecondChar === 't' && (result = this.regexp.uv_pattern.exec(line)) !== null) {

																																// 0               1      2
																																// ["vt 0.1 0.2", "0.1", "0.2"]

																																state.uvs.push(parseFloat(result[1]), parseFloat(result[2]));
																												} else {

																																throw new Error("Unexpected vertex/normal/uv line: '" + line + "'");
																												}
																								} else if (lineFirstChar === "f") {

																												if ((result = this.regexp.face_vertex_uv_normal.exec(line)) !== null) {

																																// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
																																// 0                        1    2    3    4    5    6    7    8    9   10         11         12
																																// ["f 1/1/1 2/2/2 3/3/3", "1", "1", "1", "2", "2", "2", "3", "3", "3", undefined, undefined, undefined]

																																state.addFace(result[1], result[4], result[7], result[10], result[2], result[5], result[8], result[11], result[3], result[6], result[9], result[12]);
																												} else if ((result = this.regexp.face_vertex_uv.exec(line)) !== null) {

																																// f vertex/uv vertex/uv vertex/uv
																																// 0                  1    2    3    4    5    6   7          8
																																// ["f 1/1 2/2 3/3", "1", "1", "2", "2", "3", "3", undefined, undefined]

																																state.addFace(result[1], result[3], result[5], result[7], result[2], result[4], result[6], result[8]);
																												} else if ((result = this.regexp.face_vertex_normal.exec(line)) !== null) {

																																// f vertex//normal vertex//normal vertex//normal
																																// 0                     1    2    3    4    5    6   7          8
																																// ["f 1//1 2//2 3//3", "1", "1", "2", "2", "3", "3", undefined, undefined]

																																state.addFace(result[1], result[3], result[5], result[7], undefined, undefined, undefined, undefined, result[2], result[4], result[6], result[8]);
																												} else if ((result = this.regexp.face_vertex.exec(line)) !== null) {

																																// f vertex vertex vertex
																																// 0            1    2    3   4
																																// ["f 1 2 3", "1", "2", "3", undefined]

																																state.addFace(result[1], result[2], result[3], result[4]);
																												} else {

																																throw new Error("Unexpected face line: '" + line + "'");
																												}
																								} else if (lineFirstChar === "l") {

																												var lineParts = line.substring(1).trim().split(" ");
																												var lineVertices = [],
																												    lineUVs = [];

																												if (line.indexOf("/") === -1) {

																																lineVertices = lineParts;
																												} else {

																																for (var li = 0, llen = lineParts.length; li < llen; li++) {

																																				var parts = lineParts[li].split("/");

																																				if (parts[0] !== "") lineVertices.push(parts[0]);
																																				if (parts[1] !== "") lineUVs.push(parts[1]);
																																}
																												}
																												state.addLineGeometry(lineVertices, lineUVs);
																								} else if ((result = this.regexp.object_pattern.exec(line)) !== null) {

																												// o object_name
																												// or
																												// g group_name

																												// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
																												// var name = result[ 0 ].substr( 1 ).trim();
																												var name = (" " + result[0].substr(1).trim()).substr(1);

																												state.startObject(name);
																								} else if (this.regexp.material_use_pattern.test(line)) {

																												// material

																												state.object.startMaterial(line.substring(7).trim(), state.materialLibraries);
																								} else if (this.regexp.material_library_pattern.test(line)) {

																												// mtl file

																												state.materialLibraries.push(line.substring(7).trim());
																								} else if ((result = this.regexp.smoothing_pattern.exec(line)) !== null) {

																												// smooth shading

																												// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
																												// but does not define a usemtl for each face set.
																												// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
																												// This requires some care to not create extra material on each smooth value for "normal" obj files.
																												// where explicit usemtl defines geometry groups.
																												// Example asset: examples/models/obj/cerberus/Cerberus.obj

																												var value = result[1].trim().toLowerCase();
																												state.object.smooth = value === '1' || value === 'on';

																												var material = state.object.currentMaterial();
																												if (material) {

																																material.smooth = state.object.smooth;
																												}
																								} else {

																												// Handle null terminated files without exception
																												if (line === '\0') continue;

																												throw new Error("Unexpected line: '" + line + "'");
																								}
																				}

																				state.finalize();

																				var container = new THREE.Group();
																				container.materialLibraries = [].concat(state.materialLibraries);

																				for (var i = 0, l = state.objects.length; i < l; i++) {

																								var object = state.objects[i];
																								var geometry = object.geometry;
																								var material = object.material;
																								var isLine = geometry.type === 'Line';

																								// Skip o/g line declarations that did not follow with any faces
																								if (geometry.vertices.length === 0) continue;

																								var buffergeometry = new THREE.BufferGeometry();

																								buffergeometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(geometry.vertices), 3));

																								if (geometry.normals.length > 0) {

																												buffergeometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(geometry.normals), 3));
																								} else {

																												buffergeometry.computeVertexNormals();
																								}

																								if (geometry.uvs.length > 0) {

																												buffergeometry.addAttribute('uv', new THREE.BufferAttribute(new Float32Array(geometry.uvs), 2));
																								}

																								// Create material

																								var createdMaterials = [];

																								for (var mi = 0, miLen = material.length; mi < miLen; mi++) {

																												var sourceMaterial = material[mi];
																												var material = undefined;

																												if (this.material !== null) {

																																material = this.material.create(sourceMaterial.name);

																																// mtl etc. loaders probably can't create line material correctly, copy properties to a line material.
																																if (isLine && material && !(material instanceof THREE.LineBasicMaterial)) {

																																				var materialLine = new THREE.LineBasicMaterial();
																																				materialLine.copy(material);
																																				material = materialLine;
																																}
																												}

																												if (!material) {

																																material = !isLine ? new THREE.MeshPhongMaterial() : new THREE.LineBasicMaterial();
																																material.name = sourceMaterial.name;
																												}

																												// material.shading = sourceMaterial.smooth ? THREE.SmoothShading : THREE.FlatShading;
																												material.flatShading = sourceMaterial.smooth;

																												createdMaterials.push(material);
																								}

																								// Create mesh

																								var mesh;

																								if (createdMaterials.length > 1) {

																												for (var mi = 0, miLen = material.length; mi < miLen; mi++) {

																																var sourceMaterial = material[mi];
																																buffergeometry.addGroup(sourceMaterial.groupStart, sourceMaterial.groupCount, mi);
																												}

																												var multiMaterial = new THREE.MultiMaterial(createdMaterials);
																												mesh = !isLine ? new THREE.Mesh(buffergeometry, multiMaterial) : new THREE.LineSegments(buffergeometry, multiMaterial);
																								} else {

																												mesh = !isLine ? new THREE.Mesh(buffergeometry, createdMaterials[0]) : new THREE.LineSegments(buffergeometry, createdMaterials[0]);
																								}

																								mesh.name = object.name;

																								container.add(mesh);
																				}

																				console.timeEnd('OBJLoader');

																				return container;
																}

												};
								}
				};
});

$__System.register('36', ['3'], function (_export) {
			/**
    * @author Wei Meng / http://about.me/menway
    *
    * Description: A THREE loader for PLY ASCII files (known as the Polygon
    * File Format or the Stanford Triangle Format).
    *
    * Limitations: ASCII decoding assumes file is UTF-8.
    *
    * Usage:
    *	var loader = new PLYLoader();
    *	loader.load('./models/ply/ascii/dolphins.ply', function (geometry) {
    *
    *		scene.add( new THREE.Mesh( geometry ) );
    *
    *	} );
    *
    * If the PLY file uses non standard property names, they can be mapped while
    * loading. For example, the following maps the properties
    * “diffuse_(red|green|blue)” in the file to standard color names.
    *
    * loader.setPropertyNameMapping( {
    *	diffuse_red: 'red',
    *	diffuse_green: 'green',
    *	diffuse_blue: 'blue'
    * } );
    *
    */

			'use strict';

			var THREE, PLYLoader;
			return {
						setters: [function (_) {
									THREE = _;
						}],
						execute: function () {
									PLYLoader = function PLYLoader(manager) {

												this.manager = manager !== undefined ? manager : THREE.DefaultLoadingManager;

												this.propertyNameMapping = {};
									};

									_export('PLYLoader', PLYLoader);

									PLYLoader.prototype = {

												constructor: PLYLoader,

												load: function load(url, onLoad, onProgress, onError) {

															var scope = this;

															var loader = new THREE.FileLoader(this.manager);
															loader.setResponseType('arraybuffer');
															loader.load(url, function (text) {

																		onLoad(scope.parse(text));
															}, onProgress, onError);
												},

												setPropertyNameMapping: function setPropertyNameMapping(mapping) {

															this.propertyNameMapping = mapping;
												},

												parse: function parse(data) {

															function isASCII(data) {

																		var header = parseHeader(bin2str(data));
																		return header.format === 'ascii';
															}

															function bin2str(buf) {

																		var array_buffer = new Uint8Array(buf);
																		var str = '';

																		for (var i = 0; i < buf.byteLength; i++) {

																					str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian
																		}

																		return str;
															}

															function parseHeader(data) {

																		var patternHeader = /ply([\s\S]*)end_header\s/;
																		var headerText = '';
																		var headerLength = 0;
																		var result = patternHeader.exec(data);

																		if (result !== null) {

																					headerText = result[1];
																					headerLength = result[0].length;
																		}

																		var header = {
																					comments: [],
																					elements: [],
																					headerLength: headerLength
																		};

																		var lines = headerText.split('\n');
																		var currentElement;
																		var lineType, lineValues;

																		function make_ply_element_property(propertValues, propertyNameMapping) {

																					var property = { type: propertValues[0] };

																					if (property.type === 'list') {

																								property.name = propertValues[3];
																								property.countType = propertValues[1];
																								property.itemType = propertValues[2];
																					} else {

																								property.name = propertValues[1];
																					}

																					if (property.name in propertyNameMapping) {

																								property.name = propertyNameMapping[property.name];
																					}

																					return property;
																		}

																		for (var i = 0; i < lines.length; i++) {

																					var line = lines[i];
																					line = line.trim();

																					if (line === '') continue;

																					lineValues = line.split(/\s+/);
																					lineType = lineValues.shift();
																					line = lineValues.join(' ');

																					switch (lineType) {

																								case 'format':

																											header.format = lineValues[0];
																											header.version = lineValues[1];

																											break;

																								case 'comment':

																											header.comments.push(line);

																											break;

																								case 'element':

																											if (currentElement !== undefined) {

																														header.elements.push(currentElement);
																											}

																											currentElement = {};
																											currentElement.name = lineValues[0];
																											currentElement.count = parseInt(lineValues[1]);
																											currentElement.properties = [];

																											break;

																								case 'property':

																											currentElement.properties.push(make_ply_element_property(lineValues, scope.propertyNameMapping));

																											break;

																								default:

																											console.log('unhandled', lineType, lineValues);

																					}
																		}

																		if (currentElement !== undefined) {

																					header.elements.push(currentElement);
																		}

																		return header;
															}

															function parseASCIINumber(n, type) {

																		switch (type) {

																					case 'char':case 'uchar':case 'short':case 'ushort':case 'int':case 'uint':
																					case 'int8':case 'uint8':case 'int16':case 'uint16':case 'int32':case 'uint32':

																								return parseInt(n);

																					case 'float':case 'double':case 'float32':case 'float64':

																								return parseFloat(n);

																		}
															}

															function parseASCIIElement(properties, line) {

																		var values = line.split(/\s+/);

																		var element = {};

																		for (var i = 0; i < properties.length; i++) {

																					if (properties[i].type === 'list') {

																								var list = [];
																								var n = parseASCIINumber(values.shift(), properties[i].countType);

																								for (var j = 0; j < n; j++) {

																											list.push(parseASCIINumber(values.shift(), properties[i].itemType));
																								}

																								element[properties[i].name] = list;
																					} else {

																								element[properties[i].name] = parseASCIINumber(values.shift(), properties[i].type);
																					}
																		}

																		return element;
															}

															function parseASCII(data) {

																		// PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)

																		var buffer = {
																					indices: [],
																					vertices: [],
																					normals: [],
																					uvs: [],
																					colors: []
																		};

																		var result;

																		var header = parseHeader(data);

																		var patternBody = /end_header\s([\s\S]*)$/;
																		var body = '';
																		if ((result = patternBody.exec(data)) !== null) {

																					body = result[1];
																		}

																		var lines = body.split('\n');
																		var currentElement = 0;
																		var currentElementCount = 0;

																		for (var i = 0; i < lines.length; i++) {

																					var line = lines[i];
																					line = line.trim();
																					if (line === '') {

																								continue;
																					}

																					if (currentElementCount >= header.elements[currentElement].count) {

																								currentElement++;
																								currentElementCount = 0;
																					}

																					var element = parseASCIIElement(header.elements[currentElement].properties, line);

																					handleElement(buffer, header.elements[currentElement].name, element);

																					currentElementCount++;
																		}

																		return postProcess(buffer);
															}

															function postProcess(buffer) {

																		var geometry = new THREE.BufferGeometry();

																		// mandatory buffer data

																		if (buffer.indices.length > 0) {

																					geometry.setIndex(buffer.indices);
																		}

																		geometry.addAttribute('position', new THREE.Float32BufferAttribute(buffer.vertices, 3));

																		// optional buffer data

																		if (buffer.normals.length > 0) {

																					geometry.addAttribute('normal', new THREE.Float32BufferAttribute(buffer.normals, 3));
																		}

																		if (buffer.uvs.length > 0) {

																					geometry.addAttribute('uv', new THREE.Float32BufferAttribute(buffer.uvs, 2));
																		}

																		if (buffer.colors.length > 0) {

																					geometry.addAttribute('color', new THREE.Float32BufferAttribute(buffer.colors, 3));
																		}

																		geometry.computeBoundingSphere();

																		return geometry;
															}

															function handleElement(buffer, elementName, element) {

																		if (elementName === 'vertex') {

																					buffer.vertices.push(element.x, element.y, element.z);

																					if ('nx' in element && 'ny' in element && 'nz' in element) {

																								buffer.normals.push(element.nx, element.ny, element.nz);
																					}

																					if ('s' in element && 't' in element) {

																								buffer.uvs.push(element.s, element.t);
																					}

																					if ('red' in element && 'green' in element && 'blue' in element) {

																								buffer.colors.push(element.red / 255.0, element.green / 255.0, element.blue / 255.0);
																					}
																		} else if (elementName === 'face') {

																					var vertex_indices = element.vertex_indices || element.vertex_index; // issue #9338

																					if (vertex_indices.length === 3) {

																								buffer.indices.push(vertex_indices[0], vertex_indices[1], vertex_indices[2]);
																					} else if (vertex_indices.length === 4) {

																								buffer.indices.push(vertex_indices[0], vertex_indices[1], vertex_indices[3]);
																								buffer.indices.push(vertex_indices[1], vertex_indices[2], vertex_indices[3]);
																					}
																		}
															}

															function binaryRead(dataview, at, type, little_endian) {

																		switch (type) {

																					// corespondences for non-specific length types here match rply:
																					case 'int8':case 'char':
																								return [dataview.getInt8(at), 1];
																					case 'uint8':case 'uchar':
																								return [dataview.getUint8(at), 1];
																					case 'int16':case 'short':
																								return [dataview.getInt16(at, little_endian), 2];
																					case 'uint16':case 'ushort':
																								return [dataview.getUint16(at, little_endian), 2];
																					case 'int32':case 'int':
																								return [dataview.getInt32(at, little_endian), 4];
																					case 'uint32':case 'uint':
																								return [dataview.getUint32(at, little_endian), 4];
																					case 'float32':case 'float':
																								return [dataview.getFloat32(at, little_endian), 4];
																					case 'float64':case 'double':
																								return [dataview.getFloat64(at, little_endian), 8];

																		}
															}

															function binaryReadElement(dataview, at, properties, little_endian) {

																		var element = {};
																		var result,
																		    read = 0;

																		for (var i = 0; i < properties.length; i++) {

																					if (properties[i].type === 'list') {

																								var list = [];

																								result = binaryRead(dataview, at + read, properties[i].countType, little_endian);
																								var n = result[0];
																								read += result[1];

																								for (var j = 0; j < n; j++) {

																											result = binaryRead(dataview, at + read, properties[i].itemType, little_endian);
																											list.push(result[0]);
																											read += result[1];
																								}

																								element[properties[i].name] = list;
																					} else {

																								result = binaryRead(dataview, at + read, properties[i].type, little_endian);
																								element[properties[i].name] = result[0];
																								read += result[1];
																					}
																		}

																		return [element, read];
															}

															function parseBinary(data) {

																		var buffer = {
																					indices: [],
																					vertices: [],
																					normals: [],
																					uvs: [],
																					colors: []
																		};

																		var header = parseHeader(bin2str(data));
																		var little_endian = header.format === 'binary_little_endian';
																		var body = new DataView(data, header.headerLength);
																		var result,
																		    loc = 0;

																		for (var currentElement = 0; currentElement < header.elements.length; currentElement++) {

																					for (var currentElementCount = 0; currentElementCount < header.elements[currentElement].count; currentElementCount++) {

																								result = binaryReadElement(body, loc, header.elements[currentElement].properties, little_endian);
																								loc += result[1];
																								var element = result[0];

																								handleElement(buffer, header.elements[currentElement].name, element);
																					}
																		}

																		return postProcess(buffer);
															}

															//

															var geometry;
															var scope = this;

															if (data instanceof ArrayBuffer) {

																		geometry = isASCII(data) ? parseASCII(bin2str(data)) : parseBinary(data);
															} else {

																		geometry = parseASCII(data);
															}

															return geometry;
												}

									};
						}
			};
});

$__System.register("37", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\n#define PI 3.1415926535897932384626433832795\r\n#define PI2 6.283185307179586476925286766559\r\n#define TAU 6.283185307179586476925286766559\r\n#define HALFPI 1.5707963267948966192313216916398\r\n#define HALF3PI 4.7123889803846898576939650749194\r\n\r\n#define waveA smoothstep(.7,.9,abs(sin(time*3.14159)))\r\n#define waveB smoothstep(.3,1.,abs(sin(time*3.145159*2.)))\r\n#define waveFast smoothstep(.0,1.,abs(sin(time*4.*3.14159)))\r\n\r\n// LJ\r\nmat2 rot (float a) { float c = cos(a), s=sin(a); return mat2(c,-s,s,c); }\r\n\r\n// mercury\r\nfloat pModPolar(inout vec2 p, float repetitions) {\r\n\tfloat angle = 2.*PI/repetitions;\r\n\tfloat a = atan(p.y, p.x) + angle/2.;\r\n\tfloat r = length(p);\r\n\tfloat c = floor(a/angle);\r\n\ta = mod(a,angle) - angle/2.;\r\n\tp = vec2(cos(a), sin(a))*r;\r\n\t// For an odd number of repetitions, fix cell index of the cell in -x direction\r\n\t// (cell index would be e.g. -5 and 5 in the two halves of the cell):\r\n\tif (abs(c) >= (repetitions/2.)) c = abs(c);\r\n\treturn c;\r\n}\r\n\r\n\r\n// raymarch toolbox\r\nfloat rng (vec2 seed) { return fract(sin(dot(seed*.1684,vec2(54.649,321.547)))*450315.); }\r\nfloat sdSphere (vec3 p, float r) { return length(p)-r; }\r\nfloat sdCylinder (vec2 p, float r) { return length(p)-r; }\r\nfloat sdDisk (vec3 p, vec3 s) { return max(max(length(p.xz)-s.x, s.y), abs(p.y)-s.z); }\r\nfloat sdIso(vec3 p, float r) { return max(0.,dot(p,normalize(sign(p))))-r; }\r\nfloat sdBox( vec3 p, vec3 b ) { vec3 d = abs(p) - b; return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); }\r\nfloat sdTorus( vec3 p, vec2 t ) { vec2 q = vec2(length(p.xz)-t.x,p.y); return length(q)-t.y; }\r\nfloat amod (inout vec2 p, float count) { float an = TAU/count; float a = atan(p.y,p.x)+an/2.; float c = floor(a/an); c = mix(c,abs(c),step(count*.5,abs(c))); a = mod(a,an)-an/2.; p.xy = vec2(cos(a),sin(a))*length(p); return c; }\r\nfloat repeat (float v, float c) { return mod(v,c)-c/2.; }\r\nvec2 repeat (vec2 v, float c) { return mod(v,c)-c/2.; }\r\nvec3 repeat (vec3 v, float c) { return mod(v,c)-c/2.; }\r\nfloat smoo (float a, float b, float r) { return clamp(.5+.5*(b-a)/r, 0., 1.); }\r\nfloat smin (float a, float b, float r) { float h = smoo(a,b,r); return mix(b,a,h)-r*h*(1.-h); }\r\nfloat smax (float a, float b, float r) { float h = smoo(a,b,r); return mix(a,b,h)+r*h*(1.-h); }\r\nvec2 displaceLoop (vec2 p, float r) { return vec2(length(p.xy)-r, atan(p.y,p.x)); }\r\n\r\nfloat colorDistance (vec4 a, vec4 b) {\r\n  return (abs(a.r-b.r)+abs(a.g-b.g)+abs(a.b-b.b))/3.0;\r\n}\r\n\r\nfloat luminance ( vec3 color )\r\n{\r\n\treturn (color.r + color.g + color.b) / 3.0;\r\n}\r\n\r\nfloat range (float fromA, float toA, float fromB, float toB, float value)\r\n{\r\n\treturn smoothstep(fromA, toA, value) * (1. - smoothstep(fromB, toB, value));\r\n}\r\n\r\n// Sam Hocevar\r\nvec3 rgb2hsv(vec3 c)\r\n{\r\n\tvec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\r\n\tvec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\r\n\tvec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\r\n\r\n\tfloat d = q.x - min(q.w, q.y);\r\n\tfloat e = 1.0e-10;\r\n\treturn vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\r\n}\r\n\r\n// Sam Hocevar\r\nvec3 hsv2rgb(vec3 c)\r\n{\r\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\r\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\r\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\r\n}\r\n\r\nvec4 edge (sampler2D bitmap, vec2 uv, vec2 dimension)\r\n{\r\n\tvec4 color = vec4(0.0, 0.0, 0.0, 0.0);\r\n\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-2, -2) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-2, -1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-2,  0) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-2,  1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-2,  2) / dimension);\r\n\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-1, -2) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-1, -1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-1,  0) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-1,  1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2(-1,  2) / dimension);\r\n\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 0, -2) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 0, -1) / dimension);\r\n\tcolor += 24.0 * texture2D(bitmap, uv + vec2( 0,  0) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 0,  1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 0,  2) / dimension);\r\n\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 1, -2) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 1, -1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 1,  0) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 1,  1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 1,  2) / dimension);\r\n\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 2, -2) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 2, -1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 2,  0) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 2,  1) / dimension);\r\n\tcolor += -1.0 * texture2D(bitmap, uv + vec2( 2,  2) / dimension);\r\n\r\n\treturn color;\r\n}\r\n\r\nfloat rand ( vec2 seed ){ return fract(sin(dot(seed.xy ,vec2(12.9898,78.233))) * 43758.5453); }\r\n\r\n// hash based 3d value noise\r\n// function taken from https://www.shadertoy.com/view/XslGRr\r\n// Created by inigo quilez - iq/2013\r\n// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.\r\n\r\n// ported from GLSL to HLSL\r\nfloat hash( float n )\r\n{\r\n\treturn fract(sin(n)*43758.5453);\r\n}\r\n\r\nfloat noiseIQ( vec3 x )\r\n{\r\n\t// The noise function returns a value in the range -1.0f -> 1.0f\r\n\tvec3 p = floor(x);\r\n\tvec3 f = fract(x);\r\n\tf       = f*f*(3.0-2.0*f);\r\n\tfloat n = p.x + p.y*57.0 + 113.0*p.z;\r\n\treturn mix(mix(mix( hash(n+0.0), hash(n+1.0),f.x),\r\n\t mix( hash(n+57.0), hash(n+58.0),f.x),f.y),\r\n\tmix(mix( hash(n+113.0), hash(n+114.0),f.x),\r\n\t mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);\r\n}\r\n\r\nfloat fbm (vec3 p, vec3 speed) {\r\n    float value = 0.0;\r\n    float amplitud = .5;\r\n    for (float i = 1.; i <= 5.; i++) {\r\n        value += amplitud * noiseIQ(p);\r\n        p *= 2.;\r\n    \tp += speed;\r\n        amplitud *= .5;\r\n    }\r\n    return value;\r\n}\r\n\r\nfloat pattern (vec3 p) {\r\n  vec3 q = vec3(noiseIQ(p), noiseIQ(p+vec3(12.5,51.5,7.5423)), noiseIQ(p+vec3(151.24,1254.324,658.6)));\r\n  return noiseIQ(p + 2. * q);\r\n}\r\n\r\nvec3 rotateY(vec3 v, float t)\r\n{\r\n\tfloat cost = cos(t); float sint = sin(t);\r\n\treturn vec3(v.x * cost + v.z * sint, v.y, -v.x * sint + v.z * cost);\r\n}\r\n\r\nvec3 rotateX(vec3 v, float t)\r\n{\r\n\tfloat cost = cos(t); float sint = sin(t);\r\n\treturn vec3(v.x, v.y * cost - v.z * sint, v.y * sint + v.z * cost);\r\n}\r\n\r\nvec3 rotateZ(vec3 p, float angle)\r\n{\r\n\tfloat c = cos(angle);\r\n\tfloat s = sin(angle);\r\n\treturn vec3(c*p.x+s*p.y, -s*p.x+c*p.y, p.z);\r\n}\r\n\r\n\r\n\r\nfloat reflectance(vec3 a, vec3 b) { return dot(normalize(a), normalize(b)) * 0.5 + 0.5; }\r\nvec2 kaelidoGrid(vec2 p) { return vec2(step(mod(p, 2.0), vec2(1.0))); }\r\n\r\nfloat sphere( vec3 p, float s ) { return length(p)-s; }\r\n\r\n\r\n\r\nvec2 lightDirection (sampler2D bitmap, vec2 uv, vec2 dimension)\r\n{\r\n  vec2 force = vec2(0.0, 0.0);\r\n  vec3 c = texture2D(bitmap, uv).rgb;\r\n  float l = luminance(c);\r\n\r\n  c = texture2D(bitmap, uv + vec2(-1.0, 0.0) / dimension).rgb;\r\n  force.x += luminance(c) - l;\r\n\r\n  c = texture2D(bitmap, uv + vec2(1.0, 0.0) / dimension).rgb;\r\n  force.x += l - luminance(c);\r\n\r\n  c = texture2D(bitmap, uv + vec2(0.0, -1.0) / dimension).rgb;\r\n  force.y += luminance(c) - l;\r\n\r\n  c = texture2D(bitmap, uv + vec2(0.0, 1.0) / dimension).rgb;\r\n  force.y += l - luminance(c);\r\n\r\n  c = texture2D(bitmap, uv + vec2(-1.0, -1.0) / dimension).rgb;\r\n  force += luminance(c) - l;\r\n\r\n  c = texture2D(bitmap, uv + vec2(-1.0, 1.0) / dimension).rgb;\r\n  force += l - luminance(c);\r\n\r\n  c = texture2D(bitmap, uv + vec2(1.0, -1.0) / dimension).rgb;\r\n  force += luminance(c) - l;\r\n\r\n  c = texture2D(bitmap, uv + vec2(1.0, 1.0) / dimension).rgb;\r\n  force += l - luminance(c);\r\n\r\n  return force;\r\n  // return normalize(force);\r\n}\r\n\r\n\r\n// vec4 displace (vec4 pos, float time)\r\n// {\r\n// \tfloat wave = sin(time + pos.x) * .5 + .5;\r\n// \twave = noiseIQ(pos.xyz * .4 + time);\r\n// \t// pos.y += wave;\r\n// \treturn pos;\r\n// }\r\n\r\n// vec4 layer (vec4 pos, vec2 resolution, float index)\r\n// {\r\n// \tvec2 aspect = vec2(resolution.y/resolution.x, 1.);\r\n// \tpos.x = pos.x * aspect.x;\r\n// \tpos.y = pos.y * aspect.y;\r\n// \tpos.z = index;\r\n// \treturn pos;\r\n// }\r\n\r\n// vec3 displace (vec3 pos, float t)\r\n// {\r\n// \tfloat wave = sin(t + pos.x) * .5 + .5;\r\n// \twave = noiseIQ(pos.xxx *.5 + t);\r\n// \tpos.y *= wave * 10.;\r\n// \tfloat a = -pos.x * .8;\r\n// \tfloat radius = 4. + sin(pos.y * .5 + t);\r\n// \tpos.x = cos(a + t) * radius;\r\n// \tpos.y += a * .5;\r\n// \tpos.z = sin(a + t) * radius;\r\n// \treturn pos;\r\n// }\r\nvec3 displaceTree (vec3 p, float t, float blend)\r\n{\r\n    float a = noiseIQ(p/3.)*PI2;\r\n    float intensity = .15*clamp(p.y*.2,0.,1.);\r\n    p.z += sin(a + t * 3.)*intensity;\r\n    p.z += cos(a + t * 3.)*intensity;\r\n\r\n    float speed = 10.;\r\n    intensity = 3.*clamp(p.y*.05,0.,1.) * blend;\r\n    p.x += (-intensity + .2*cos(t * speed)) * intensity;\r\n    p.y += .2*sin(-t * speed + length(p.xz)) * intensity;\r\n    return p;\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("38", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "{\r\n  \"blendTextIn\": [\r\n    {\r\n      \"location\": [\r\n        0, \r\n        0, \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -1.1342440287272135, \r\n              -0.9460909962654114, \r\n              1.1342440287272135, \r\n              0.9460909962654114, \r\n              1\r\n            ], \r\n            [\r\n              2.283333333333333, \r\n              1.0, \r\n              1.3918937683105468, \r\n              1.0, \r\n              3.994637044270833, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              6.666666666666667, \r\n              1.0, \r\n              6.634132385253906, \r\n              1.0, \r\n              6.673173522949218, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              6.683333333333334, \r\n              0.0, \r\n              6.032421875, \r\n              -0.9460909962654114, \r\n              8.3005126953125, \r\n              2.350548267364502, \r\n              1\r\n            ], \r\n            [\r\n              8.45, \r\n              0.0, \r\n              7.315755208333333, \r\n              -0.9460909962654114, \r\n              9.584244791666666, \r\n              0.9460909962654114, \r\n              1\r\n            ], \r\n            [\r\n              10.9, \r\n              1.0, \r\n              9.943491617838541, \r\n              1.0, \r\n              12.6113037109375, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              15.283333333333333, \r\n              1.0, \r\n              15.250798543294271, \r\n              1.0, \r\n              15.289840698242188, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              15.299999999999999, \r\n              0.0, \r\n              14.649088541666666, \r\n              -0.9460909962654114, \r\n              16.917179361979166, \r\n              2.350548267364502, \r\n              1\r\n            ], \r\n            [\r\n              16.7, \r\n              0.0, \r\n              15.565755208333334, \r\n              -0.9460909962654114, \r\n              17.834244791666666, \r\n              0.9460909962654114, \r\n              1\r\n            ], \r\n            [\r\n              18.75, \r\n              1.0, \r\n              17.949656168619793, \r\n              1.0, \r\n              20.4613037109375, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              23.133333333333333, \r\n              1.0, \r\n              23.100799560546875, \r\n              1.0, \r\n              23.13983968098958, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              23.15, \r\n              0.0, \r\n              22.499088541666666, \r\n              -0.9460909962654114, \r\n              24.767179361979167, \r\n              2.350548267364502, \r\n              1\r\n            ], \r\n            [\r\n              24.816666666666666, \r\n              0.0, \r\n              23.682421875, \r\n              -0.9460909962654114, \r\n              25.950911458333334, \r\n              0.9460909962654114, \r\n              1\r\n            ], \r\n            [\r\n              27.016666666666666, \r\n              1.0, \r\n              26.15776163736979, \r\n              1.0, \r\n              28.727970377604166, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              31.4, \r\n              1.0, \r\n              31.36746622721354, \r\n              1.0, \r\n              31.40650634765625, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              31.416666666666668, \r\n              0.0, \r\n              30.76575520833333, \r\n              -0.9460909962654114, \r\n              33.03384602864583, \r\n              2.350548267364502, \r\n              1\r\n            ], \r\n            [\r\n              32.86666666666667, \r\n              0.0, \r\n              31.732421875, \r\n              -0.9460909962654114, \r\n              34.000911458333334, \r\n              0.9460909962654114, \r\n              1\r\n            ], \r\n            [\r\n              34.666666666666664, \r\n              1.0, \r\n              33.96392618815104, \r\n              1.0, \r\n              36.377970377604164, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              39.05, \r\n              1.0, \r\n              39.01746419270833, \r\n              1.0, \r\n              39.05650634765625, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              39.06666666666666, \r\n              0.0, \r\n              38.41575520833333, \r\n              -0.9460909962654114, \r\n              40.68384602864583, \r\n              2.350548267364502, \r\n              1\r\n            ], \r\n            [\r\n              43.916666666666664, \r\n              0.0, \r\n              42.782421875, \r\n              -0.9460909962654114, \r\n              45.05091145833333, \r\n              0.9460909962654114, \r\n              1\r\n            ], \r\n            [\r\n              45.96666666666667, \r\n              1.0, \r\n              45.166324869791666, \r\n              1.0, \r\n              47.67797037760417, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              50.35, \r\n              1.0, \r\n              50.317464192708336, \r\n              1.0, \r\n              50.35650634765625, \r\n              1.0, \r\n              1\r\n            ], \r\n            [\r\n              50.36666666666667, \r\n              0.0, \r\n              49.715755208333334, \r\n              -0.9460909962654114, \r\n              51.983846028645836, \r\n              2.350548267364502, \r\n              1\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              92.88697916666666, \r\n              0.0, \r\n              96.322607421875, \r\n              0.0, \r\n              1\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              1\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendText\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              3.0, \r\n              -37.24285888671875, \r\n              3.0, \r\n              37.44285888671875, \r\n              3.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              3.0, \r\n              58.40714111328125, \r\n              3.0, \r\n              133.09285481770834, \r\n              3.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              0.0, \r\n              -37.24285888671875, \r\n              0.0, \r\n              37.44285888671875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              58.40714111328125, \r\n              0.0, \r\n              133.09285481770834, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              1.0, \r\n              -37.24285888671875, \r\n              1.0, \r\n              37.44285888671875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.88697916666666, \r\n              1.0, \r\n              96.322607421875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              0.0, \r\n              -37.24285888671875, \r\n              0.0, \r\n              37.44285888671875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              58.40714111328125, \r\n              0.0, \r\n              133.09285481770834, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              0.0, \r\n              -37.24285888671875, \r\n              0.0, \r\n              37.44285888671875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              58.40714111328125, \r\n              0.0, \r\n              133.09285481770834, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              0.0, \r\n              -37.24285888671875, \r\n              0.0, \r\n              37.44285888671875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              58.40714111328125, \r\n              0.0, \r\n              133.09285481770834, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              1.0, \r\n              -37.24285888671875, \r\n              1.0, \r\n              37.44285888671875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              58.40714111328125, \r\n              1.0, \r\n              133.09285481770834, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              1.0, \r\n              -37.24285888671875, \r\n              1.0, \r\n              37.44285888671875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              58.40714111328125, \r\n              1.0, \r\n              133.09285481770834, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              1.0, \r\n              -37.24285888671875, \r\n              1.0, \r\n              37.44285888671875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              58.40714111328125, \r\n              1.0, \r\n              133.09285481770834, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendGlitch\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              87.73333333333333, \r\n              -2.0, \r\n              84.60353190104166, \r\n              -2.0, \r\n              90.863134765625, \r\n              -2.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              -2.0, \r\n              92.62019856770833, \r\n              -2.0, \r\n              98.87980143229167, \r\n              -2.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              87.73333333333333, \r\n              0.0, \r\n              84.60353190104166, \r\n              0.0, \r\n              90.863134765625, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              92.62019856770833, \r\n              0.0, \r\n              98.87980143229167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              87.35, \r\n              0.0, \r\n              87.200341796875, \r\n              0.0, \r\n              87.499658203125, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              87.73333333333333, \r\n              1.0030776262283325, \r\n              87.58367513020833, \r\n              1.0030776262283325, \r\n              87.89600423177083, \r\n              1.0030776262283325, \r\n              2\r\n            ], \r\n            [\r\n              88.15, \r\n              0.0, \r\n              87.9873291015625, \r\n              0.0, \r\n              88.9633544921875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.9976348876953125, \r\n              95.13185221354166, \r\n              0.9858096241950989, \r\n              95.8736328125, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              96.06666666666666, \r\n              1.0, \r\n              95.94303385416667, \r\n              1.0, \r\n              96.51564127604166, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.76769205729167, \r\n              0.0, \r\n              97.66564127604167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              87.73333333333333, \r\n              0.0, \r\n              84.60353190104166, \r\n              0.0, \r\n              90.863134765625, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              92.62019856770833, \r\n              0.0, \r\n              98.87980143229167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              87.73333333333333, \r\n              0.0, \r\n              84.60353190104166, \r\n              0.0, \r\n              90.863134765625, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              92.62019856770833, \r\n              0.0, \r\n              98.87980143229167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              87.73333333333333, \r\n              0.0, \r\n              84.60353190104166, \r\n              0.0, \r\n              90.863134765625, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              92.62019856770833, \r\n              0.0, \r\n              98.87980143229167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              87.73333333333333, \r\n              1.0, \r\n              84.60353190104166, \r\n              1.0, \r\n              90.863134765625, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.62019856770833, \r\n              1.0, \r\n              98.87980143229167, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              87.73333333333333, \r\n              1.0, \r\n              84.60353190104166, \r\n              1.0, \r\n              90.863134765625, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.62019856770833, \r\n              1.0, \r\n              98.87980143229167, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              87.73333333333333, \r\n              1.0, \r\n              84.60353190104166, \r\n              1.0, \r\n              90.863134765625, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.62019856770833, \r\n              1.0, \r\n              98.87980143229167, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendBubble1\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              2.0, \r\n              -3.0363057454427085, \r\n              2.0, \r\n              3.236305745442708, \r\n              2.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              2.0, \r\n              4.997027587890625, \r\n              2.0, \r\n              23.814862060546876, \r\n              2.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              2.0, \r\n              61.543444824218746, \r\n              2.0, \r\n              129.95655924479166, \r\n              2.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              1.0, \r\n              -3.0363057454427085, \r\n              1.0, \r\n              3.236305745442708, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              1.0, \r\n              4.997027587890625, \r\n              1.0, \r\n              23.814862060546876, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              61.543444824218746, \r\n              1.0, \r\n              129.95655924479166, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              0.0, \r\n              -3.0363057454427085, \r\n              0.0, \r\n              3.236305745442708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              1.0, \r\n              4.997027587890625, \r\n              1.0, \r\n              23.814862060546876, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.88697916666666, \r\n              1.0, \r\n              96.322607421875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              0.0, \r\n              -3.0363057454427085, \r\n              0.0, \r\n              3.236305745442708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              0.0, \r\n              4.997027587890625, \r\n              0.0, \r\n              23.814862060546876, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              61.543444824218746, \r\n              0.0, \r\n              129.95655924479166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              0.0, \r\n              -3.0363057454427085, \r\n              0.0, \r\n              3.236305745442708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              0.0, \r\n              4.997027587890625, \r\n              0.0, \r\n              23.814862060546876, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              61.543444824218746, \r\n              0.0, \r\n              129.95655924479166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              0.0, \r\n              -3.0363057454427085, \r\n              0.0, \r\n              3.236305745442708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              0.0, \r\n              4.997027587890625, \r\n              0.0, \r\n              23.814862060546876, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              61.543444824218746, \r\n              0.0, \r\n              129.95655924479166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              1.0, \r\n              -3.0363057454427085, \r\n              1.0, \r\n              3.236305745442708, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              1.0, \r\n              4.997027587890625, \r\n              1.0, \r\n              23.814862060546876, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              61.543444824218746, \r\n              1.0, \r\n              129.95655924479166, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              1.0, \r\n              -3.0363057454427085, \r\n              1.0, \r\n              3.236305745442708, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              1.0, \r\n              4.997027587890625, \r\n              1.0, \r\n              23.814862060546876, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              61.543444824218746, \r\n              1.0, \r\n              129.95655924479166, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.1, \r\n              1.0, \r\n              -3.0363057454427085, \r\n              1.0, \r\n              3.236305745442708, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              8.133333333333333, \r\n              1.0, \r\n              4.997027587890625, \r\n              1.0, \r\n              23.814862060546876, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              61.543444824218746, \r\n              1.0, \r\n              129.95655924479166, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"Camera\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              38.661598205566406, \r\n              -10.345904541015624, \r\n              38.661598205566406, \r\n              10.345904541015624, \r\n              38.661598205566406, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              55.66110610961914, \r\n              16.154095458984376, \r\n              55.66110610961914, \r\n              29.271921793619793, \r\n              55.66110610961914, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              51.824161529541016, \r\n              30.82807820638021, \r\n              54.13405227661133, \r\n              37.9335693359375, \r\n              48.212921142578125, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              39.32311248779297, \r\n              40.3664306640625, \r\n              39.32311248779297, \r\n              47.061991373697914, \r\n              39.32311248779297, \r\n              2\r\n            ], \r\n            [\r\n              50.75, \r\n              39.32311248779297, \r\n              48.38800862630208, \r\n              39.32311248779297, \r\n              54.250691731770836, \r\n              39.32311248779297, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              55.03923797607422, \r\n              56.21597493489583, \r\n              55.03923797607422, \r\n              61.440983072916666, \r\n              55.03923797607422, \r\n              2\r\n            ], \r\n            [\r\n              64.13333333333333, \r\n              55.03923797607422, \r\n              62.409016927083336, \r\n              55.03923797607422, \r\n              67.41929524739584, \r\n              55.03923797607422, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              8.372152328491211, \r\n              69.2640380859375, \r\n              8.372152328491211, \r\n              78.32809244791666, \r\n              8.372152328491211, \r\n              2\r\n            ], \r\n            [\r\n              87.35, \r\n              8.372152328491211, \r\n              86.1136962890625, \r\n              8.372152328491211, \r\n              87.59725748697916, \r\n              8.372152328491211, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              2.7321929931640625, \r\n              87.73607584635417, \r\n              2.7321929931640625, \r\n              89.1545654296875, \r\n              2.7321929931640625, \r\n              2\r\n            ], \r\n            [\r\n              90.98333333333333, \r\n              2.7321929931640625, \r\n              89.81210123697916, \r\n              2.7321929931640625, \r\n              91.2305908203125, \r\n              2.7321929931640625, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              2.7321929931640625, \r\n              91.3694091796875, \r\n              2.7321929931640625, \r\n              92.78789876302083, \r\n              2.7321929931640625, \r\n              2\r\n            ], \r\n            [\r\n              94.61666666666666, \r\n              2.7321929931640625, \r\n              93.54303385416667, \r\n              2.7321929931640625, \r\n              94.831396484375, \r\n              2.7321929931640625, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              2.7321929931640625, \r\n              94.95193684895833, \r\n              2.7321929931640625, \r\n              95.381396484375, \r\n              2.7321929931640625, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -10.345904541015624, \r\n              0.0, \r\n              10.345904541015624, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              0.0, \r\n              16.154095458984376, \r\n              0.0, \r\n              29.271921793619793, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              0.0, \r\n              30.82807820638021, \r\n              0.0, \r\n              37.9335693359375, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              0.0, \r\n              40.3664306640625, \r\n              0.0, \r\n              47.061991373697914, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              50.75, \r\n              0.0, \r\n              48.38800862630208, \r\n              0.0, \r\n              54.250691731770836, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              0.0, \r\n              56.21597493489583, \r\n              0.0, \r\n              61.440983072916666, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              64.13333333333333, \r\n              0.0, \r\n              62.409016927083336, \r\n              0.0, \r\n              67.41929524739584, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              -54.54623794555664, \r\n              69.2640380859375, \r\n              -54.54623794555664, \r\n              78.32809244791666, \r\n              -54.54623794555664, \r\n              2\r\n            ], \r\n            [\r\n              87.35, \r\n              -54.54623794555664, \r\n              86.1136962890625, \r\n              -54.54623794555664, \r\n              87.59725748697916, \r\n              -54.54623794555664, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              -54.54623794555664, \r\n              87.73607584635417, \r\n              -54.54623794555664, \r\n              89.1545654296875, \r\n              -54.54623794555664, \r\n              2\r\n            ], \r\n            [\r\n              90.98333333333333, \r\n              -54.54623794555664, \r\n              89.81210123697916, \r\n              -54.54623794555664, \r\n              91.2305908203125, \r\n              -54.54623794555664, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              -55.16130065917969, \r\n              91.3694091796875, \r\n              -55.16130065917969, \r\n              92.78789876302083, \r\n              -55.16130065917969, \r\n              2\r\n            ], \r\n            [\r\n              94.61666666666666, \r\n              -55.16130065917969, \r\n              93.54303385416667, \r\n              -55.16130065917969, \r\n              94.831396484375, \r\n              -55.16130065917969, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              -55.776363372802734, \r\n              94.95193684895833, \r\n              -55.776363372802734, \r\n              95.381396484375, \r\n              -55.776363372802734, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -10.345904541015624, \r\n              0.0, \r\n              10.345904541015624, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              0.0, \r\n              16.154095458984376, \r\n              0.0, \r\n              29.271921793619793, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              0.0, \r\n              30.82807820638021, \r\n              0.0, \r\n              37.9335693359375, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              0.0, \r\n              40.3664306640625, \r\n              0.0, \r\n              47.061991373697914, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              50.75, \r\n              0.0, \r\n              48.38800862630208, \r\n              0.0, \r\n              54.250691731770836, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              0.0, \r\n              56.21597493489583, \r\n              0.0, \r\n              61.440983072916666, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              64.13333333333333, \r\n              0.0, \r\n              62.409016927083336, \r\n              0.0, \r\n              67.41929524739584, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              2.4901134967803955, \r\n              69.2640380859375, \r\n              2.4901134967803955, \r\n              78.32809244791666, \r\n              2.4901134967803955, \r\n              2\r\n            ], \r\n            [\r\n              87.35, \r\n              2.4901134967803955, \r\n              86.1136962890625, \r\n              2.4901134967803955, \r\n              87.59725748697916, \r\n              2.4901134967803955, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              -0.585191011428833, \r\n              87.73607584635417, \r\n              -0.585191011428833, \r\n              89.1545654296875, \r\n              -0.585191011428833, \r\n              2\r\n            ], \r\n            [\r\n              90.98333333333333, \r\n              -0.585191011428833, \r\n              89.81210123697916, \r\n              -0.585191011428833, \r\n              91.2305908203125, \r\n              -0.585191011428833, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              3.720235586166382, \r\n              91.3694091796875, \r\n              3.720235586166382, \r\n              92.78789876302083, \r\n              3.720235586166382, \r\n              2\r\n            ], \r\n            [\r\n              94.61666666666666, \r\n              3.720235586166382, \r\n              93.54303385416667, \r\n              3.720235586166382, \r\n              94.831396484375, \r\n              3.720235586166382, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              -4.8906168937683105, \r\n              94.95193684895833, \r\n              -4.8906168937683105, \r\n              95.381396484375, \r\n              -4.8906168937683105, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              1.5707963705062866, \r\n              -10.345904541015624, \r\n              1.5707963705062866, \r\n              10.345904541015624, \r\n              1.5707963705062866, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              1.5707963705062866, \r\n              16.154095458984376, \r\n              1.5707963705062866, \r\n              29.271921793619793, \r\n              1.5707963705062866, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              1.5707963705062866, \r\n              30.82807820638021, \r\n              1.5707963705062866, \r\n              37.9335693359375, \r\n              1.5707963705062866, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              1.5707963705062866, \r\n              40.3664306640625, \r\n              1.5707963705062866, \r\n              50.562679036458334, \r\n              1.5707963705062866, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              1.5707963705062866, \r\n              53.85398763020833, \r\n              1.5707963705062866, \r\n              64.72694905598958, \r\n              1.5707963705062866, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              1.5707963705062866, \r\n              67.53971761067709, \r\n              1.5707963705062866, \r\n              78.57534993489583, \r\n              1.5707963705062866, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              1.5707963705062866, \r\n              81.9579833984375, \r\n              1.5707963705062866, \r\n              89.4018310546875, \r\n              1.5707963705062866, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              1.5707963705062866, \r\n              90.1981689453125, \r\n              1.5707963705062866, \r\n              93.00262858072917, \r\n              1.5707963705062866, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              1.5707963705062866, \r\n              93.78070475260417, \r\n              1.5707963705062866, \r\n              96.55262858072916, \r\n              1.5707963705062866, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -10.345904541015624, \r\n              0.0, \r\n              10.345904541015624, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              0.0, \r\n              16.154095458984376, \r\n              0.0, \r\n              29.271921793619793, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              0.0, \r\n              30.82807820638021, \r\n              0.0, \r\n              37.9335693359375, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              0.0, \r\n              40.3664306640625, \r\n              0.0, \r\n              50.562679036458334, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              0.0, \r\n              53.85398763020833, \r\n              0.0, \r\n              64.72694905598958, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              0.0, \r\n              67.53971761067709, \r\n              0.0, \r\n              78.57534993489583, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              0.0, \r\n              81.9579833984375, \r\n              0.0, \r\n              89.4018310546875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              0.0, \r\n              90.1981689453125, \r\n              0.0, \r\n              93.00262858072917, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              0.0, \r\n              93.78070475260417, \r\n              0.0, \r\n              96.55262858072916, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -10.345904541015624, \r\n              0.0, \r\n              10.345904541015624, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              0.0, \r\n              16.154095458984376, \r\n              0.0, \r\n              29.271921793619793, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              0.0, \r\n              30.82807820638021, \r\n              0.0, \r\n              37.9335693359375, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              0.0, \r\n              40.3664306640625, \r\n              0.0, \r\n              50.562679036458334, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              0.0, \r\n              53.85398763020833, \r\n              0.0, \r\n              64.72694905598958, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              0.0, \r\n              67.53971761067709, \r\n              0.0, \r\n              78.57534993489583, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              0.0, \r\n              81.9579833984375, \r\n              0.0, \r\n              89.4018310546875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              0.0, \r\n              90.1981689453125, \r\n              0.0, \r\n              93.00262858072917, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              0.0, \r\n              93.78070475260417, \r\n              0.0, \r\n              96.55262858072916, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.9999988079071045, \r\n              -10.345904541015624, \r\n              0.9999988079071045, \r\n              10.345904541015624, \r\n              0.9999988079071045, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              0.9999988079071045, \r\n              16.154095458984376, \r\n              0.9999988079071045, \r\n              29.271921793619793, \r\n              0.9999988079071045, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              0.9999988079071045, \r\n              30.82807820638021, \r\n              0.9999988079071045, \r\n              37.9335693359375, \r\n              0.9999988079071045, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              0.9999988079071045, \r\n              40.3664306640625, \r\n              0.9999988079071045, \r\n              50.562679036458334, \r\n              0.9999988079071045, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              0.9999988079071045, \r\n              53.85398763020833, \r\n              0.9999988079071045, \r\n              64.72694905598958, \r\n              0.9999988079071045, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              0.9999988079071045, \r\n              67.53971761067709, \r\n              0.9999988079071045, \r\n              78.57534993489583, \r\n              0.9999988079071045, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              0.9999988079071045, \r\n              81.9579833984375, \r\n              0.9999988079071045, \r\n              89.4018310546875, \r\n              0.9999988079071045, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              0.9999988079071045, \r\n              90.1981689453125, \r\n              0.9999988079071045, \r\n              93.00262858072917, \r\n              0.9999988079071045, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              0.9999988079071045, \r\n              93.78070475260417, \r\n              0.9999988079071045, \r\n              96.55262858072916, \r\n              0.9999988079071045, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.9999992251396179, \r\n              -10.345904541015624, \r\n              0.9999992251396179, \r\n              10.345904541015624, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              0.9999992251396179, \r\n              16.154095458984376, \r\n              0.9999992251396179, \r\n              29.271921793619793, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              0.9999992251396179, \r\n              30.82807820638021, \r\n              0.9999992251396179, \r\n              37.9335693359375, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              0.9999992251396179, \r\n              40.3664306640625, \r\n              0.9999992251396179, \r\n              50.562679036458334, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              0.9999992251396179, \r\n              53.85398763020833, \r\n              0.9999992251396179, \r\n              64.72694905598958, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              0.9999992251396179, \r\n              67.53971761067709, \r\n              0.9999992251396179, \r\n              78.57534993489583, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              0.9999992251396179, \r\n              81.9579833984375, \r\n              0.9999992251396179, \r\n              89.4018310546875, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              0.9999992251396179, \r\n              90.1981689453125, \r\n              0.9999992251396179, \r\n              93.00262858072917, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              0.9999992251396179, \r\n              93.78070475260417, \r\n              0.9999992251396179, \r\n              96.55262858072916, \r\n              0.9999992251396179, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.9999992251396179, \r\n              -10.345904541015624, \r\n              0.9999992251396179, \r\n              10.345904541015624, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              26.5, \r\n              0.9999992251396179, \r\n              16.154095458984376, \r\n              0.9999992251396179, \r\n              29.271921793619793, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              33.6, \r\n              0.9999992251396179, \r\n              30.82807820638021, \r\n              0.9999992251396179, \r\n              37.9335693359375, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              44.7, \r\n              0.9999992251396179, \r\n              40.3664306640625, \r\n              0.9999992251396179, \r\n              50.562679036458334, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              59.71666666666667, \r\n              0.9999992251396179, \r\n              53.85398763020833, \r\n              0.9999992251396179, \r\n              64.72694905598958, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              72.55, \r\n              0.9999992251396179, \r\n              67.53971761067709, \r\n              0.9999992251396179, \r\n              78.57534993489583, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              87.98333333333333, \r\n              0.9999992251396179, \r\n              81.9579833984375, \r\n              0.9999992251396179, \r\n              89.4018310546875, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              91.61666666666666, \r\n              0.9999992251396179, \r\n              90.1981689453125, \r\n              0.9999992251396179, \r\n              93.00262858072917, \r\n              0.9999992251396179, \r\n              2\r\n            ], \r\n            [\r\n              95.16666666666667, \r\n              0.9999992251396179, \r\n              93.78070475260417, \r\n              0.9999992251396179, \r\n              96.55262858072916, \r\n              0.9999992251396179, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendLine\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              42.81666666666666, \r\n              0.0, \r\n              37.572139485677084, \r\n              0.0, \r\n              48.06119384765625, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              56.25, \r\n              0.0, \r\n              51.005472819010414, \r\n              0.0, \r\n              71.67125651041667, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              80.32874348958333, \r\n              0.0, \r\n              111.17125651041667, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              42.81666666666666, \r\n              0.0, \r\n              37.572139485677084, \r\n              0.0, \r\n              48.06119384765625, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              56.25, \r\n              0.0, \r\n              51.005472819010414, \r\n              0.0, \r\n              71.67125651041667, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              80.32874348958333, \r\n              0.0, \r\n              111.17125651041667, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              42.81666666666666, \r\n              0.0, \r\n              37.572139485677084, \r\n              0.0, \r\n              48.06119384765625, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              56.25, \r\n              1.0, \r\n              51.005472819010414, \r\n              1.0, \r\n              71.67125651041667, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.88697916666666, \r\n              1.0, \r\n              96.322607421875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              56.25, \r\n              0.0, \r\n              40.82874348958333, \r\n              0.0, \r\n              71.67125651041667, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              80.32874348958333, \r\n              0.0, \r\n              111.17125651041667, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              56.25, \r\n              0.0, \r\n              40.82874348958333, \r\n              0.0, \r\n              71.67125651041667, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              80.32874348958333, \r\n              0.0, \r\n              111.17125651041667, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              56.25, \r\n              0.0, \r\n              40.82874348958333, \r\n              0.0, \r\n              71.67125651041667, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              80.32874348958333, \r\n              0.0, \r\n              111.17125651041667, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              56.25, \r\n              1.0, \r\n              40.82874348958333, \r\n              1.0, \r\n              71.67125651041667, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              80.32874348958333, \r\n              1.0, \r\n              111.17125651041667, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              56.25, \r\n              1.0, \r\n              40.82874348958333, \r\n              1.0, \r\n              71.67125651041667, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              80.32874348958333, \r\n              1.0, \r\n              111.17125651041667, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              56.25, \r\n              1.0, \r\n              40.82874348958333, \r\n              1.0, \r\n              71.67125651041667, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              80.32874348958333, \r\n              1.0, \r\n              111.17125651041667, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendMessageIndex\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              41.7, \r\n              3.0, \r\n              41.68333333333333, \r\n              3.0, \r\n              41.71666666666667, \r\n              3.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              41.7, \r\n              -1.0, \r\n              41.68333333333333, \r\n              -1.0, \r\n              41.71666666666667, \r\n              -1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -2.947606913248698, \r\n              0.0, \r\n              2.947606913248698, \r\n              0.0, \r\n              0\r\n            ], \r\n            [\r\n              7.55, \r\n              1.0, \r\n              4.602393086751302, \r\n              0.631744921207428, \r\n              10.875004069010416, \r\n              1.4154047966003418, \r\n              0\r\n            ], \r\n            [\r\n              16.066666666666666, \r\n              2.0, \r\n              12.74166259765625, \r\n              1.5925599336624146, \r\n              19.12489013671875, \r\n              2.374749183654785, \r\n              0\r\n            ], \r\n            [\r\n              23.9, \r\n              3.0, \r\n              20.841776529947918, \r\n              2.617556095123291, \r\n              27.088360595703126, \r\n              3.3987181186676025, \r\n              0\r\n            ], \r\n            [\r\n              32.06666666666666, \r\n              4.0, \r\n              28.878306070963543, \r\n              3.639308452606201, \r\n              35.827632649739584, \r\n              4.425468921661377, \r\n              0\r\n            ], \r\n            [\r\n              41.7, \r\n              5.0, \r\n              37.93903401692708, \r\n              5.0, \r\n              60.504817708333334, \r\n              5.0, \r\n              0\r\n            ], \r\n            [\r\n              95.75, \r\n              4.0, \r\n              92.88697916666666, \r\n              5.0, \r\n              96.322607421875, \r\n              3.7999987602233887, \r\n              0\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              0\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              41.7, \r\n              0.0, \r\n              41.68333333333333, \r\n              0.0, \r\n              41.71666666666667, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              41.7, \r\n              0.0, \r\n              41.68333333333333, \r\n              0.0, \r\n              41.71666666666667, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              41.7, \r\n              0.0, \r\n              41.68333333333333, \r\n              0.0, \r\n              41.71666666666667, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              41.7, \r\n              1.0, \r\n              41.68333333333333, \r\n              1.0, \r\n              41.71666666666667, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              41.7, \r\n              1.0, \r\n              41.68333333333333, \r\n              1.0, \r\n              41.71666666666667, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              41.7, \r\n              1.0, \r\n              41.68333333333333, \r\n              1.0, \r\n              41.71666666666667, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendPaper\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              -1.0, \r\n              -10.371906534830728, \r\n              -1.0, \r\n              10.371943155924479, \r\n              -1.0, \r\n              2\r\n            ], \r\n            [\r\n              26.566666666666666, \r\n              -1.0, \r\n              16.194741821289064, \r\n              -1.0, \r\n              30.58790486653646, \r\n              -1.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              -1.0, \r\n              32.845428466796875, \r\n              -1.0, \r\n              56.972859700520836, \r\n              -1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              -1.0, \r\n              72.76127115885417, \r\n              -1.0, \r\n              118.73872884114583, \r\n              -1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              0.0, \r\n              -10.371906534830728, \r\n              0.0, \r\n              10.371943155924479, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              26.566666666666666, \r\n              0.0, \r\n              16.194741821289064, \r\n              0.0, \r\n              30.58790486653646, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              0.0, \r\n              32.845428466796875, \r\n              0.0, \r\n              56.972859700520836, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              72.76127115885417, \r\n              0.0, \r\n              118.73872884114583, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              0.0, \r\n              -10.371906534830728, \r\n              0.0, \r\n              10.371943155924479, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              26.566666666666666, \r\n              0.0, \r\n              16.194741821289064, \r\n              0.0, \r\n              30.58790486653646, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              1.0, \r\n              32.845428466796875, \r\n              1.0, \r\n              56.972859700520836, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.88697916666666, \r\n              1.0, \r\n              96.322607421875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              0.0, \r\n              -14.39314473470052, \r\n              0.0, \r\n              14.393182373046875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              0.0, \r\n              22.473502604166665, \r\n              0.0, \r\n              59.855395507812496, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              72.76127115885417, \r\n              0.0, \r\n              118.73872884114583, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              0.0, \r\n              -14.39314473470052, \r\n              0.0, \r\n              14.393182373046875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              0.0, \r\n              22.473502604166665, \r\n              0.0, \r\n              59.855395507812496, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              72.76127115885417, \r\n              0.0, \r\n              118.73872884114583, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              0.0, \r\n              -14.39314473470052, \r\n              0.0, \r\n              14.393182373046875, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              0.0, \r\n              22.473502604166665, \r\n              0.0, \r\n              59.855395507812496, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              72.76127115885417, \r\n              0.0, \r\n              118.73872884114583, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              1.0, \r\n              -14.39314473470052, \r\n              1.0, \r\n              14.393182373046875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              1.0, \r\n              22.473502604166665, \r\n              1.0, \r\n              59.855395507812496, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              72.76127115885417, \r\n              1.0, \r\n              118.73872884114583, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              1.0, \r\n              -14.39314473470052, \r\n              1.0, \r\n              14.393182373046875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              1.0, \r\n              22.473502604166665, \r\n              1.0, \r\n              59.855395507812496, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              72.76127115885417, \r\n              1.0, \r\n              118.73872884114583, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.8036365509033204e-05, \r\n              1.0, \r\n              -14.39314473470052, \r\n              1.0, \r\n              14.393182373046875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              36.86666666666667, \r\n              1.0, \r\n              22.473502604166665, \r\n              1.0, \r\n              59.855395507812496, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              72.76127115885417, \r\n              1.0, \r\n              118.73872884114583, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendRaymarch\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              1.0, \r\n              -12.928444417317708, \r\n              1.0, \r\n              15.428444417317708, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              1.0, \r\n              23.388222249348956, \r\n              1.0, \r\n              60.282108561197916, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              73.03455403645833, \r\n              1.0, \r\n              118.46544596354167, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              0.0, \r\n              -12.928444417317708, \r\n              0.0, \r\n              15.428444417317708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              0.0, \r\n              23.388222249348956, \r\n              0.0, \r\n              60.282108561197916, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              73.03455403645833, \r\n              0.0, \r\n              118.46544596354167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              0.0, \r\n              -12.928444417317708, \r\n              0.0, \r\n              15.428444417317708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              1.0, \r\n              23.388222249348956, \r\n              1.0, \r\n              60.282108561197916, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.88697916666666, \r\n              1.0, \r\n              96.322607421875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              0.0, \r\n              -12.928444417317708, \r\n              0.0, \r\n              15.428444417317708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              0.0, \r\n              23.388222249348956, \r\n              0.0, \r\n              60.282108561197916, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              73.03455403645833, \r\n              0.0, \r\n              118.46544596354167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              0.0, \r\n              -12.928444417317708, \r\n              0.0, \r\n              15.428444417317708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              0.0, \r\n              23.388222249348956, \r\n              0.0, \r\n              60.282108561197916, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              73.03455403645833, \r\n              0.0, \r\n              118.46544596354167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              0.0, \r\n              -12.928444417317708, \r\n              0.0, \r\n              15.428444417317708, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              0.0, \r\n              23.388222249348956, \r\n              0.0, \r\n              60.282108561197916, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              73.03455403645833, \r\n              0.0, \r\n              118.46544596354167, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              1.0, \r\n              -12.928444417317708, \r\n              1.0, \r\n              15.428444417317708, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              1.0, \r\n              23.388222249348956, \r\n              1.0, \r\n              60.282108561197916, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              73.03455403645833, \r\n              1.0, \r\n              118.46544596354167, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              1.0, \r\n              -12.928444417317708, \r\n              1.0, \r\n              15.428444417317708, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              1.0, \r\n              23.388222249348956, \r\n              1.0, \r\n              60.282108561197916, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              73.03455403645833, \r\n              1.0, \r\n              118.46544596354167, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              1.25, \r\n              1.0, \r\n              -12.928444417317708, \r\n              1.0, \r\n              15.428444417317708, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              37.56666666666666, \r\n              1.0, \r\n              23.388222249348956, \r\n              1.0, \r\n              60.282108561197916, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              73.03455403645833, \r\n              1.0, \r\n              118.46544596354167, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"Target\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              54.266666666666666, \r\n              0.0, \r\n              43.60843098958333, \r\n              0.0, \r\n              64.92490234375, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              81.56666666666666, \r\n              0.0, \r\n              70.90843098958334, \r\n              0.0, \r\n              92.22490234375, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              54.266666666666666, \r\n              0.0, \r\n              43.60843098958333, \r\n              0.0, \r\n              64.92490234375, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              81.56666666666666, \r\n              0.0, \r\n              70.90843098958334, \r\n              0.0, \r\n              92.22490234375, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              54.266666666666666, \r\n              0.0, \r\n              43.60843098958333, \r\n              0.0, \r\n              64.92490234375, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              81.56666666666666, \r\n              0.0, \r\n              70.90843098958334, \r\n              0.0, \r\n              92.22490234375, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendTextOut\": [\r\n    {\r\n      \"location\": [\r\n        0, \r\n        0, \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -0.7739524841308594, \r\n              -0.729889452457428, \r\n              1.9404202779134114, \r\n              1.8299473524093628, \r\n              1\r\n            ], \r\n            [\r\n              3.5833333333333335, \r\n              0.0, \r\n              2.2260477701822916, \r\n              -0.7299238443374634, \r\n              4.940620930989583, \r\n              0.7299249768257141, \r\n              1\r\n            ], \r\n            [\r\n              6.666666666666667, \r\n              1.0, \r\n              5.314290364583333, \r\n              0.221549391746521, \r\n              8.01904296875, \r\n              1.778450608253479, \r\n              1\r\n            ], \r\n            [\r\n              6.683333333333334, \r\n              0.0, \r\n              5.791960652669271, \r\n              -0.2753373682498932, \r\n              8.54135538736979, \r\n              0.5739270448684692, \r\n              1\r\n            ], \r\n            [\r\n              8.45, \r\n              0.0, \r\n              7.676047770182292, \r\n              -0.729889452457428, \r\n              10.390421549479166, \r\n              1.8299490213394165, \r\n              1\r\n            ], \r\n            [\r\n              13.233333333333333, \r\n              0.0, \r\n              11.876047770182291, \r\n              -0.7299148440361023, \r\n              14.590620930989584, \r\n              0.729915976524353, \r\n              1\r\n            ], \r\n            [\r\n              15.283333333333333, \r\n              1.0, \r\n              13.93095703125, \r\n              0.221549391746521, \r\n              16.635709635416667, \r\n              1.778450608253479, \r\n              1\r\n            ], \r\n            [\r\n              15.299999999999999, \r\n              0.0, \r\n              14.408626302083333, \r\n              -0.2753373682498932, \r\n              17.158024088541666, \r\n              0.5739270448684692, \r\n              1\r\n            ], \r\n            [\r\n              16.7, \r\n              0.0, \r\n              15.9260498046875, \r\n              -0.729889452457428, \r\n              18.640421549479168, \r\n              1.8299541473388672, \r\n              1\r\n            ], \r\n            [\r\n              20.05, \r\n              0.0, \r\n              18.692716471354167, \r\n              -0.7298950552940369, \r\n              21.40728759765625, \r\n              0.7298972010612488, \r\n              1\r\n            ], \r\n            [\r\n              23.133333333333333, \r\n              1.0, \r\n              21.78095703125, \r\n              0.221549391746521, \r\n              24.485709635416665, \r\n              1.778450608253479, \r\n              1\r\n            ], \r\n            [\r\n              23.15, \r\n              0.0, \r\n              22.258626302083332, \r\n              -0.2753373682498932, \r\n              25.008024088541667, \r\n              0.5739270448684692, \r\n              1\r\n            ], \r\n            [\r\n              24.816666666666666, \r\n              0.0, \r\n              24.042716471354165, \r\n              -0.729889452457428, \r\n              26.75708821614583, \r\n              1.8299541473388672, \r\n              1\r\n            ], \r\n            [\r\n              28.316666666666666, \r\n              0.0, \r\n              26.959383138020833, \r\n              -0.7298950552940369, \r\n              29.673954264322916, \r\n              0.7298972010612488, \r\n              1\r\n            ], \r\n            [\r\n              31.4, \r\n              1.0, \r\n              30.047623697916666, \r\n              0.221549391746521, \r\n              32.752376302083334, \r\n              1.778450608253479, \r\n              1\r\n            ], \r\n            [\r\n              31.416666666666668, \r\n              0.0, \r\n              30.525292968749998, \r\n              -0.2753373682498932, \r\n              33.27469075520833, \r\n              0.5739270448684692, \r\n              1\r\n            ], \r\n            [\r\n              32.86666666666667, \r\n              0.0, \r\n              32.092716471354166, \r\n              -0.729889452457428, \r\n              34.807088216145836, \r\n              1.8299541473388672, \r\n              1\r\n            ], \r\n            [\r\n              35.96666666666667, \r\n              0.0, \r\n              34.60938313802083, \r\n              -0.7298950552940369, \r\n              37.32395833333333, \r\n              0.7298994660377502, \r\n              1\r\n            ], \r\n            [\r\n              39.05, \r\n              1.0, \r\n              37.69762369791667, \r\n              0.221549391746521, \r\n              40.40237630208333, \r\n              1.778450608253479, \r\n              1\r\n            ], \r\n            [\r\n              39.06666666666666, \r\n              0.0, \r\n              38.17529296875, \r\n              -0.2753373682498932, \r\n              40.92469075520833, \r\n              0.5739270448684692, \r\n              1\r\n            ], \r\n            [\r\n              43.916666666666664, \r\n              0.0, \r\n              43.14271647135416, \r\n              -0.729889452457428, \r\n              45.85708821614583, \r\n              1.8299541473388672, \r\n              1\r\n            ], \r\n            [\r\n              47.266666666666666, \r\n              0.0, \r\n              45.909383138020836, \r\n              -0.7298950552940369, \r\n              48.623958333333334, \r\n              0.7298994660377502, \r\n              1\r\n            ], \r\n            [\r\n              50.35, \r\n              1.0, \r\n              48.997623697916666, \r\n              0.221549391746521, \r\n              51.70237630208333, \r\n              1.778450608253479, \r\n              1\r\n            ], \r\n            [\r\n              50.36666666666667, \r\n              0.0, \r\n              49.47529296875, \r\n              -0.2753373682498932, \r\n              52.224690755208336, \r\n              0.5739270448684692, \r\n              1\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              92.88697916666666, \r\n              0.0, \r\n              96.322607421875, \r\n              0.0, \r\n              1\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              1\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendBlack\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              97.21666666666667, \r\n              -3.0, \r\n              97.2, \r\n              -3.0, \r\n              97.23333333333333, \r\n              -3.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              97.2, \r\n              0.0, \r\n              97.23333333333333, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -0.19520575205485025, \r\n              0.0, \r\n              0.19520575205485025, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5, \r\n              1.0, \r\n              0.30479424794514975, \r\n              1.0, \r\n              1.4760286966959635, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.0, \r\n              1.0, \r\n              96.57705078125, \r\n              1.0, \r\n              97.08458658854167, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              97.132080078125, \r\n              0.0, \r\n              97.30125325520834, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              97.2, \r\n              0.0, \r\n              97.23333333333333, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              97.2, \r\n              0.0, \r\n              97.23333333333333, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              97.2, \r\n              0.0, \r\n              97.23333333333333, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              97.21666666666667, \r\n              1.0, \r\n              97.2, \r\n              1.0, \r\n              97.23333333333333, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              97.21666666666667, \r\n              1.0, \r\n              97.2, \r\n              1.0, \r\n              97.23333333333333, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              97.21666666666667, \r\n              1.0, \r\n              97.2, \r\n              1.0, \r\n              97.23333333333333, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ], \r\n  \"blendBubble\": [\r\n    {\r\n      \"location\": [\r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              2.0, \r\n              -0.20171260833740234, \r\n              2.0, \r\n              0.20171260833740234, \r\n              2.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              2.0, \r\n              0.3149540583292643, \r\n              2.0, \r\n              1.5252296447753906, \r\n              2.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              2.0, \r\n              58.569812011718746, \r\n              2.0, \r\n              132.93019205729166, \r\n              2.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -0.20171260833740234, \r\n              0.0, \r\n              0.20171260833740234, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              0.0, \r\n              0.3149540583292643, \r\n              0.0, \r\n              1.5252296447753906, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              58.569812011718746, \r\n              0.0, \r\n              132.93019205729166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -0.20171260833740234, \r\n              0.0, \r\n              0.20171260833740234, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              1.0, \r\n              0.3149540583292643, \r\n              1.0, \r\n              1.5252296447753906, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              92.88697916666666, \r\n              1.0, \r\n              96.322607421875, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              97.21666666666667, \r\n              0.0, \r\n              96.64405924479166, \r\n              0.0, \r\n              97.78927408854166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"rotation_euler\": [\r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -0.20171260833740234, \r\n              0.0, \r\n              0.20171260833740234, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              0.0, \r\n              0.3149540583292643, \r\n              0.0, \r\n              1.5252296447753906, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              58.569812011718746, \r\n              0.0, \r\n              132.93019205729166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -0.20171260833740234, \r\n              0.0, \r\n              0.20171260833740234, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              0.0, \r\n              0.3149540583292643, \r\n              0.0, \r\n              1.5252296447753906, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              58.569812011718746, \r\n              0.0, \r\n              132.93019205729166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              0.0, \r\n              -0.20171260833740234, \r\n              0.0, \r\n              0.20171260833740234, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              0.0, \r\n              0.3149540583292643, \r\n              0.0, \r\n              1.5252296447753906, \r\n              0.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              0.0, \r\n              58.569812011718746, \r\n              0.0, \r\n              132.93019205729166, \r\n              0.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ], \r\n      \"scale\": [\r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              1.0, \r\n              -0.20171260833740234, \r\n              1.0, \r\n              0.20171260833740234, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              1.0, \r\n              0.3149540583292643, \r\n              1.0, \r\n              1.5252296447753906, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              58.569812011718746, \r\n              1.0, \r\n              132.93019205729166, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              1.0, \r\n              -0.20171260833740234, \r\n              1.0, \r\n              0.20171260833740234, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              1.0, \r\n              0.3149540583292643, \r\n              1.0, \r\n              1.5252296447753906, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              58.569812011718746, \r\n              1.0, \r\n              132.93019205729166, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ], \r\n        [\r\n          [\r\n            [\r\n              0.0, \r\n              1.0, \r\n              -0.20171260833740234, \r\n              1.0, \r\n              0.20171260833740234, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              0.5166666666666666, \r\n              1.0, \r\n              0.3149540583292643, \r\n              1.0, \r\n              1.5252296447753906, \r\n              1.0, \r\n              2\r\n            ], \r\n            [\r\n              95.75, \r\n              1.0, \r\n              58.569812011718746, \r\n              1.0, \r\n              132.93019205729166, \r\n              1.0, \r\n              2\r\n            ]\r\n          ], \r\n          0\r\n        ]\r\n      ]\r\n    }\r\n  ]\r\n}");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("39", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nuniform sampler2D frameScene, frameRaymarch, frameText;\r\nuniform float blendTextIn, blendTextOut, blendGlitch, blendBlack;\r\nuniform float time;\r\nuniform vec2 resolution;\r\nvarying vec2 vUv;\r\n\r\nvoid main ()\t{\r\n\tvec2 uv = vUv;\r\n\r\n\t// scanline glitch\r\n\tuv.x += (rand(uv.yy)*2.-1.)*blendGlitch * smoothstep(.5*(1.-blendGlitch),1.,noiseIQ(uv.yyy*10.+time*blendGlitch));\r\n\r\n\t// frames\r\n\tvec4 scene = texture2D(frameScene, uv);\r\n\tvec4 raymarch = texture2D(frameRaymarch, uv);\r\n\tvec4 text = texture2D(frameText, uv);\r\n\r\n\t// blend raymarch and meshes\r\n\tfloat depthScene = scene.a;\r\n\tdepthScene += 1000. * (1.-depthScene) * step(depthScene, .01);\r\n\tgl_FragColor = mix(scene, raymarch, step(raymarch.a, depthScene));\r\n\r\n\t// blend meshes with grayscale\r\n\tfloat lum = luminance(scene.rgb);\r\n\tgl_FragColor = mix(gl_FragColor, raymarch, 1.-lum);\r\n\r\n\t// shade background for better reading\r\n\tfloat textShadow = .5+ .5*clamp(length(uv.y-.5)*2., 0., 1.);\r\n\ttextShadow = mix(1., textShadow, blendTextIn);\r\n\ttextShadow = mix(textShadow, 1., blendTextOut);\r\n\tgl_FragColor *= textShadow;\r\n\r\n\t// add text\r\n\tgl_FragColor = mix(gl_FragColor, text, text.a);\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("3a", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nuniform vec2 resolution;\r\nuniform float time;\r\nuniform float blendRaymarch;\r\nvarying vec2 vUv;\r\n\r\n#define STEPS 30.\r\n#define VOLUME_BIAS .1\r\n#define STEP_MIN .001\r\n\r\nfloat shape (vec3 pos, float radius, float margin) {\r\n\tfloat shape = 1000.;\r\n\tfloat twist = .1;\r\n\tvec3 p;\r\n\r\n\t// twist it\r\n\tpos.xy *= rot(pos.z*twist + time * 3.);\r\n\r\n\t// squarish tube\r\n  p = pos;\r\n  radius *= 1. + .5 * sin(p.z * .05 - time * 2.);\r\n  shape = sdBox(p, vec3(radius,radius,1000));\r\n  p.xy *= rot(PI/4.);\r\n  shape = max(shape, -sdBox(p, vec3(radius*margin, radius*margin, 1000)));\r\n\r\n\t// cross tubes\r\n  amod(p.yx, 4.);\r\n  p.z = repeat(p.z+time*10., TAU * 2.);\r\n  shape = smin(shape, max(sdCylinder(p.xz, .1*radius), abs(length(p.xy))-radius*margin), .25*radius);\r\n\r\n\t// iso inside tubes\r\n  shape = smin(shape, sdIso(p, .5 * radius * (.5+.5*waveB)), .1*radius);\r\n  shape = smin(shape, sdCylinder(p.xy, .2 * radius * (.5+.5*waveB)), .25*radius);\r\n\r\n\t// sphere tubes\r\n\tp = pos;\r\n\tp.z = repeat(p.z, TAU);\r\n\tfloat a = p.z * .1;\r\n\tvec3 pp = p;\r\n\tamod(p.xy, 4.);\r\n\tp.x -= 1. * radius;\r\n\tshape = smin(shape, sdSphere(p, .25 * radius), .1 * radius);\r\n\tshape = smin(shape, max(sdCylinder(p.yz, .05 * radius), abs(length(pp.xy))-radius), .1 * radius);\r\n\r\n  return shape;\r\n}\r\n\r\nfloat map (vec3 pos) {\r\n\tfloat scene = 1000.;\r\n\tvec3 p;\r\n\r\n\t// shape parameter\r\n\tfloat margin = 1.3 - .1 * waveB;\r\n\r\n\t// create a negative sphere around camera\r\n\tfloat shell = sdSphere(pos-cameraPosition, 10.);\r\n\r\n\t// twist it\r\n\tfloat a = pos.z* .05  + time;\r\n\tpos.xy += vec2(cos(a),sin(a)) * 10.;\r\n\r\n\t// appearing animation\r\n\tfloat fade = smoothstep(0., 200., -pos.z - 410. * (blendRaymarch*2.-1.));\r\n\r\n\t// horizontal tube\r\n  p = pos;\r\n  scene = shape(p, 5., margin);\r\n\r\n\t// donuts\r\n  p.yz *= rot(PI/2.+sin(time)*.3);\r\n  p.xz *= rot(sin(time)*.2);\r\n  p.xz = displaceLoop(p.xz, 20.);\r\n  p.z *= 20.;\r\n  p.y = repeat(p.y+time*10., 60.);\r\n  scene = min(scene, shape(p, 2., margin));\r\n\r\n\t// background donuts\r\n\tp = pos;\r\n  p.yz *= rot(PI/2.);\r\n  p.xz = displaceLoop(p.xz, 100.);\r\n  p.z *= 20.;\r\n\tp.y += p.z * PI;\r\n  p.y = repeat(p.y+time*10., 100.);\r\n  scene = min(scene, shape(p, 10., margin));\r\n\r\n\tscene += fade * 10.;\r\n\tscene = max(scene, -shell);\r\n\r\n\treturn scene;\r\n}\r\n\r\nvec3 getNormal (vec3 p) {\r\n\tvec2 e = vec2(.01,0.);\r\n\treturn normalize(vec3(map(p+e.xyy)-map(p-e.xyy), map(p+e.yxy)-map(p-e.yxy), map(p+e.yyx)-map(p-e.yyx)));\r\n}\r\n\r\nvoid main ()\t{\r\n\tvec2 uv = vUv*2.-1.;\r\n\tuv.x *= resolution.x/resolution.y;\r\n\tvec3 eye = cameraPosition;\r\n\tvec3 forward = -normalize(cameraPosition);\r\n\tvec3 right = normalize(cross(forward, vec3(0,1,0)));\r\n\tvec3 up = normalize(cross(right, forward));\r\n\tvec3 ray = normalize(right * uv.x + up * uv.y + forward);\r\n\tvec3 pos = eye;\r\n\tvec2 seed = vUv + fract(time);\r\n\tfloat shade = 0.;\r\n\tfloat dist = 0.;\r\n\tfor (float i = 0.; i <= 1.; i += 1./STEPS) {\r\n\t\tfloat d = map(pos);\r\n\t\tif (d < VOLUME_BIAS) {\r\n\t\t\tshade = 1.-i;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\td *= .9+.1*rand(seed*vec2(i));\r\n\t\td = max(d, STEP_MIN);\r\n\t\tdist += d;\r\n\t\tif (dist > 400.) {\r\n\t\t\tshade = 0.;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tpos = eye + ray * dist;\r\n\t}\r\n\tvec4 color = vec4(1.);\r\n\tcolor.rgb *= shade;\r\n\tcolor.a = dist;\r\n\tgl_FragColor = color;\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("3b", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nvarying vec2 vUv;\r\n\r\nvoid main()\t{\r\n\tvUv = uv;\r\n\tgl_Position = vec4(mix(-1., 1., uv.x), mix(-1., 1., uv.y), 0., 1.);\r\n}");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("3c", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nuniform float time;\r\n\r\nvarying vec2 vAnchor;\r\nvarying float vDepth;\r\nvarying float vShould;\r\n\r\nvoid main()\t{\r\n\r\n\t// circle or bubble sphape\r\n\tfloat dist = length(vAnchor+.5);\r\n\tdist -= .25 * vShould;\r\n\tif (abs(dist) > mix(.5, .02, vShould)) discard;\r\n\r\n\tgl_FragColor = vec4(vec3(1), vDepth);\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("3d", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nattribute vec2 anchor;\r\nattribute vec2 indexMap;\r\n\r\nuniform float time;\r\nuniform float blendBubble, blendBubble1;\r\nuniform vec2 resolution;\r\n\r\nvarying vec2 vAnchor;\r\nvarying float vDepth;\r\nvarying float vShould;\r\n\r\n\r\nvoid main()\t{\r\n\tvAnchor = anchor;\r\n\tvec3 pos = position*2.-1.;\r\n\tvec2 size = vec2(.25);\r\n\tvec2 aspect = vec2(resolution.y / resolution.x, 1.);\r\n\r\n\t// arrange points on a cylinder\r\n\tfloat a = indexMap.y*PI;\r\n\tpos.xy = vec2(cos(a),sin(a));\r\n\tpos.z = (indexMap.x*2.-1.)*10.;\r\n\tpos.z += atan(pos.x,pos.y)*.5;\r\n\r\n\t// animation\r\n\tfloat waveGrow = .1+.9*clamp(cos(pos.z*2.+time*.5), 0.,1.);\r\n\r\n\t// displacement\r\n\tfloat seed = noiseIQ(pos*2.);\r\n\tfloat dist = length(pos);\r\n\tvec3 offset = vec3(seed);\r\n\ta = noiseIQ(pos*5.)*PI2;\r\n\toffset.xz = vec2(cos(a),sin(a));\r\n\toffset.xz *= rot(time);\r\n\toffset.xy *= rot(time);\r\n\tpos += offset*.5*(.5 + waveB * .5)*waveGrow * blendBubble1;\r\n\r\n\t// translate and repeat\r\n\tpos.z = repeat(pos.z*2.+time*.5, TAU*2.);\r\n\r\n\t// twist it\r\n\tpos.xy *= rot(pos.z * waveGrow + time);\r\n\r\n\t// apparition animation\r\n\tsize *= smoothstep(0., 10., pos.z + (blendBubble*2.-1.) * 10.);\r\n\r\n\t// bounce it\r\n\tfloat should = waveB * smoothstep(.6,1.,seed);\r\n\tvShould = step(.1, should);\r\n\tsize *= 2. + 1. * seed + 20. * should;\r\n\r\n\t// sqeeze it\r\n\tpos.xy *= .8+.2*cos(abs(pos.z));\r\n\r\n\t// scale it\r\n\tpos *= 20.;\r\n\r\n\t// send depth to alpha channel\r\n\tvDepth = length(cameraPosition - pos);\r\n\r\n\t// pos it\r\n\tgl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(pos, 1);\r\n\r\n\t// spread quad on screenspace\r\n\tgl_Position.x += anchor.x * aspect.x * size.x;\r\n\tgl_Position.y += anchor.y * aspect.y * size.y;\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("3e", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nuniform float time;\r\n\r\nvarying vec3 vDirection;\r\nvarying vec3 vView;\r\nvarying vec3 vNormal;\r\nvarying vec2 vAnchor;\r\nvarying float vDepth;\r\nvarying float vSeed;\r\n\r\nvoid main()\t{\r\n\t// dot line shape\r\n\tfloat dist = length(vAnchor+.5);\r\n\tif (fract(vAnchor.y*10.) > .1+waveB*.1) discard;\r\n\r\n\tfloat shade = dot(vView, vNormal)*.5+.5;\r\n\tgl_FragColor = vec4(vec3(1.)*(.8+.2*shade), vDepth);\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("3f", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nattribute vec2 anchor;\r\nattribute vec2 indexMap;\r\n\r\nuniform float time;\r\nuniform float blendLine;\r\nuniform vec2 resolution;\r\n\r\nvarying float vSeed;\r\nvarying vec3 vView;\r\nvarying vec3 vDirection;\r\nvarying vec3 vNormal;\r\nvarying vec2 vAnchor;\r\nvarying float vDepth;\r\n\r\n\r\nvec3 displace (vec3 pos, float ratio) {\r\n  vec3 p = pos;\r\n\r\n  // displace\r\n  float dist = length(p);\r\n  vec3 offset = vec3(noiseIQ(pos));\r\n  float a = noiseIQ(pos)*PI2;\r\n  offset.xz = vec2(cos(a),sin(a));\r\n  offset.xz *= rot(ratio * PI2 + dist + time);\r\n  offset.xy *= rot(ratio * PI2 + dist + time);\r\n  p += offset * 5.;\r\n\r\n  // expansion animation\r\n  float range = 60.;\r\n  dist = mod(length(p.xyz)/range*10.+time*.5+ratio, 1.);\r\n  dist *= range;\r\n  p.xyz = normalize(p.xyz)*(dist);\r\n\r\n  return p;\r\n}\r\nvoid main()  {\r\n\r\n  vAnchor = anchor;\r\n  float a = indexMap.y * PI2;\r\n  vec3 pos = vec3(cos(a),sin(a), indexMap.x*2.-1.);\r\n  vec2 size = vec2(.4) * blendLine;\r\n  vec2 aspect = vec2(resolution.y / resolution.x, 1.);\r\n  float ratio = mod(rand(pos.xz) + anchor.y/2., 1.);\r\n\r\n  // find out neighbors\r\n  float delta = .001;\r\n  vec3 prev = displace(pos, mod(ratio+1.-delta, 1.));\r\n  vec3 next = displace(pos, mod(ratio+delta, 1.));\r\n\r\n  // directions vectors\r\n  vec3 up = normalize(-pos);\r\n  vDirection = normalize(next-prev);\r\n  vNormal = cross(vDirection, up);\r\n\r\n  // displace it\r\n  pos = displace(pos, ratio);\r\n\r\n  vDepth = length(cameraPosition - pos);\r\n  vView = normalize(cameraPosition - pos);\r\n\r\n  // pos it\r\n  gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(pos, 1);\r\n\r\n\t// spread quad on screenspace\r\n  gl_Position.x += anchor.x * aspect.x * size.x;\r\n  gl_Position.y += anchor.y * aspect.y * size.y;\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("40", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nuniform float time;\r\n\r\nvarying vec3 vView;\r\nvarying vec3 vNormal;\r\nvarying float vDepth;\r\n\r\nvoid main()\t{\r\n\tfloat shade = dot(vView, vNormal)*.5+.5;\r\n\tshade = .8 + .2 * shade;\r\n\tgl_FragColor = vec4(vec3(shade), vDepth);\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("41", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nattribute vec2 anchor;\r\nattribute vec2 indexMap;\r\n\r\nuniform float time;\r\nuniform float blendPaper;\r\nuniform vec2 resolution;\r\n\r\nvarying vec3 vView;\r\nvarying vec3 vNormal;\r\nvarying float vDepth;\r\n\r\nvec3 displace (vec3 pos, float ratio) {\r\n  vec3 p = pos;\r\n  float dist = length(p);\r\n  vec3 offset = vec3(noiseIQ(pos));\r\n  float a = noiseIQ(pos)*PI2;\r\n  offset.xz = vec2(cos(a),sin(a));\r\n  offset.xz *= rot(ratio * PI2 + time);\r\n  offset.xy *= rot(ratio * PI2 + time);\r\n  p += offset * 5.;\r\n  p.xy *= rot(ratio + time + p.z*.2);\r\n  return p;\r\n}\r\n\r\nvoid main()  {\r\n  vec2 size = vec2(1.);\r\n  vec3 pos = position;\r\n\r\n  float a = indexMap.y * PI2;\r\n  pos.xy = vec2(cos(a),sin(a));\r\n  pos.z = (indexMap.x*2.-1.)*10.;\r\n  pos.z = repeat(pos.z+time*.2, 20.);\r\n\r\n  float ratio = mod(rand(pos.xy) + (anchor.y*.5+.5)/20., 1.);\r\n  pos *= 7.;\r\n\r\n  float delta = .001;\r\n  vec3 prev = displace(pos, mod(ratio+1.-delta, 1.));\r\n  vec3 next = displace(pos, mod(ratio+delta, 1.));\r\n  vec3 up = normalize(-pos);\r\n  vec3 direction = normalize(next-prev);\r\n  vNormal = cross(direction, up);\r\n  pos = displace(pos, ratio);\r\n\r\n  pos.xy *= 2.;\r\n  size *= blendPaper;\r\n  pos += direction *  size.y;\r\n  pos += vNormal * anchor.x * size.x;\r\n  pos += up * waveB * anchor.x * 2. * blendPaper;\r\n\r\n  vDepth = length(cameraPosition - pos);\r\n  vView = normalize(cameraPosition - pos);\r\n\r\n  gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(pos, 1);\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("42", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nuniform float time;\r\nuniform float blendText;\r\n\r\nvarying float vFadeOut;\r\nvarying vec2 vAnchor;\r\n\r\nvoid main()\t{\r\n\tif (length(vAnchor+.5) > 0.5) discard;\r\n\tgl_FragColor = vec4(vec3(1), (1.-vFadeOut) * blendText);\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("43", [], function (_export, _context) {
  "use strict";

  var __useDefault;

  return {
    setters: [],
    execute: function () {
      _export("__useDefault", __useDefault = "\r\nattribute vec2 anchor;\r\nattribute vec2 indexMap;\r\n\r\nuniform float time;\r\nuniform float blendTextIn, blendTextOut;\r\nuniform vec2 resolution;\r\nuniform sampler2D frameTextureText;\r\n\r\nvarying vec2 vAnchor;\r\nvarying float vFadeOut;\r\n\r\nvoid main()\t{\r\n\tvAnchor = anchor;\r\n\tvec2 pivot = anchor * rot(PI/4.);\r\n\tvec2 aspect = vec2(resolution.y / resolution.x, 1.);\r\n\tvec2 size = vec2(.025);\r\n\r\n\t// size from texture grayscale\r\n\tfloat lum = luminance(texture2D(frameTextureText, indexMap).rgb);\r\n\tsize *= clamp(lum*3., 0., 1.);\r\n\r\n\t// position from index map\r\n\tvec3 pos = vec3(indexMap*2.-1., 0.1+lum*.5);\r\n\tfloat seed = rand(pos.xy);\r\n\tfloat a = seed*PI2*5.;\r\n\r\n\tsize *= .5+.5*seed;\r\n\r\n\tfloat fadeIn = smoothstep(0., 1., pos.x + (blendTextIn*2.-1.)*2.);\r\n\tfloat fadeOut = smoothstep(0., 1., rand(pos.xy) + (blendTextOut*2.-1.)*2.);\r\n\tvFadeOut = fadeOut;\r\n\r\n\t// fall animation\r\n\tvec2 offset = vec2(cos(a),sin(a)) * .5 * fadeOut;\r\n\toffset.y += sin(fadeOut*PI)*.25;\r\n\toffset.y -= fadeOut*.25;\r\n\tpos.xy += offset;\r\n\r\n\t// bounce it\r\n\tfloat should = waveB * smoothstep(.9,1.,seed);\r\n\tpos.xy += .5 * normalize(pos.xy) * should * fadeIn * (1.-fadeOut);\r\n\tsize *= 1.+2.*fadeOut+2.*waveB*should;\r\n\r\n\t// wave animation\r\n\tpos.y += .05 * sin(pos.x*5.+time*2.);\r\n\r\n\t// pos it and scale in animation\r\n\tpos.x *= aspect.x;\r\n\tgl_Position = vec4(pos, .6*fadeIn);\r\n\r\n\t\t// spread quad on screenspace\r\n\tgl_Position.x += pivot.x * aspect.x * size.x;\r\n\tgl_Position.y += pivot.y * aspect.y * size.y;\r\n}\r\n");

      _export("__useDefault", __useDefault);

      _export("default", __useDefault);
    }
  };
});
$__System.register("a", ["3", "11", "30", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "2f", "3a", "3b", "3c", "3d", "3e", "3f"], function (_export) {
  var THREE, uniforms, descriptors, makeAnimations, OBJLoader, PLYLoader, shaderHeader, animation_scene_json, shader_filters_filter_frag, shader_meshes_paper_frag, shader_meshes_paper_vert, shader_meshes_text_frag, shader_meshes_text_vert, _Object$assign, shader_filters_raymarching_frag, shader_filters_screen_vert, shader_meshes_bubble_frag, shader_meshes_bubble_vert, shader_meshes_line_frag, shader_meshes_line_vert, plyLoader, objLoader, fontLoader;

  return {
    setters: [function (_6) {
      THREE = _6;
    }, function (_3) {
      uniforms = _3["default"];
    }, function (_) {
      descriptors = _["default"];
    }, function (_2) {
      makeAnimations = _2["default"];
    }, function (_4) {
      OBJLoader = _4.OBJLoader;
    }, function (_5) {
      PLYLoader = _5.PLYLoader;
    }, function (_7) {
      shaderHeader = _7["default"];
    }, function (_8) {
      animation_scene_json = _8["default"];
    }, function (_9) {
      shader_filters_filter_frag = _9["default"];
    }, function (_10) {
      shader_meshes_paper_frag = _10["default"];
    }, function (_11) {
      shader_meshes_paper_vert = _11["default"];
    }, function (_12) {
      shader_meshes_text_frag = _12["default"];
    }, function (_13) {
      shader_meshes_text_vert = _13["default"];
    }, function (_f) {
      _Object$assign = _f["default"];
    }, function (_a) {
      shader_filters_raymarching_frag = _a["default"];
    }, function (_b) {
      shader_filters_screen_vert = _b["default"];
    }, function (_c) {
      shader_meshes_bubble_frag = _c["default"];
    }, function (_d) {
      shader_meshes_bubble_vert = _d["default"];
    }, function (_e) {
      shader_meshes_line_frag = _e["default"];
    }, function (_f2) {
      shader_meshes_line_vert = _f2["default"];
    }],
    execute: function () {
      /* eslint-disable */
      /* This file is generated with "npm run assets", do not edit by hand. */
      "use strict";

      plyLoader = new PLYLoader();
      objLoader = new OBJLoader();
      fontLoader = new THREE.FontLoader();

      _export("default", {
        animations: makeAnimations(JSON.parse(animation_scene_json)),
        geometries: {},
        fonts: {},
        shaderMaterials: {
          bubble: new THREE.ShaderMaterial(_Object$assign({}, descriptors.shaderMaterials.bubble, {
            vertexShader: shaderHeader + shader_meshes_bubble_vert,
            fragmentShader: shaderHeader + shader_meshes_bubble_frag,
            uniforms: uniforms
          })),
          raymarching: new THREE.ShaderMaterial(_Object$assign({}, descriptors.shaderMaterials.raymarching, {
            vertexShader: shaderHeader + shader_filters_screen_vert,
            fragmentShader: shaderHeader + shader_filters_raymarching_frag,
            uniforms: uniforms
          })),
          paper: new THREE.ShaderMaterial(_Object$assign({}, descriptors.shaderMaterials.paper, {
            vertexShader: shaderHeader + shader_meshes_paper_vert,
            fragmentShader: shaderHeader + shader_meshes_paper_frag,
            uniforms: uniforms
          })),
          line: new THREE.ShaderMaterial(_Object$assign({}, descriptors.shaderMaterials.line, {
            vertexShader: shaderHeader + shader_meshes_line_vert,
            fragmentShader: shaderHeader + shader_meshes_line_frag,
            uniforms: uniforms
          })),
          text: new THREE.ShaderMaterial(_Object$assign({}, descriptors.shaderMaterials.text, {
            vertexShader: shaderHeader + shader_meshes_text_vert,
            fragmentShader: shaderHeader + shader_meshes_text_frag,
            uniforms: uniforms
          })),
          filter: new THREE.ShaderMaterial(_Object$assign({}, descriptors.shaderMaterials.filter, {
            vertexShader: shaderHeader + shader_filters_screen_vert,
            fragmentShader: shaderHeader + shader_filters_filter_frag,
            uniforms: uniforms
          }))
        },
        load: function load(callback) {
          return callback();
        }
      });
    }
  };
});

$__System.registerDynamic("18", [], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var $Object = Object;
  module.exports = {
    create: $Object.create,
    getProto: $Object.getPrototypeOf,
    isEnum: {}.propertyIsEnumerable,
    getDesc: $Object.getOwnPropertyDescriptor,
    setDesc: $Object.defineProperty,
    setDescs: $Object.defineProperties,
    getKeys: $Object.keys,
    getNames: $Object.getOwnPropertyNames,
    getSymbols: $Object.getOwnPropertySymbols,
    each: [].forEach
  };
});
$__System.registerDynamic('44', ['18'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var $ = $__require('18');
  module.exports = function defineProperty(it, key, desc) {
    return $.setDesc(it, key, desc);
  };
});
$__System.registerDynamic("45", ["44"], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = { "default": $__require("44"), __esModule: true };
});
$__System.registerDynamic("4", ["45"], true, function ($__require, exports, module) {
  /* */
  "use strict";

  var global = this || self,
      GLOBAL = global;
  var _Object$defineProperty = $__require("45")["default"];
  exports["default"] = function () {
    function defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        _Object$defineProperty(target, descriptor.key, descriptor);
      }
    }
    return function (Constructor, protoProps, staticProps) {
      if (protoProps) defineProperties(Constructor.prototype, protoProps);
      if (staticProps) defineProperties(Constructor, staticProps);
      return Constructor;
    };
  }();
  exports.__esModule = true;
});
$__System.registerDynamic("5", [], true, function ($__require, exports, module) {
  /* */
  "use strict";

  var global = this || self,
      GLOBAL = global;
  exports["default"] = function (instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  };

  exports.__esModule = true;
});
$__System.registerDynamic("14", [], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  // 7.2.1 RequireObjectCoercible(argument)
  module.exports = function (it) {
    if (it == undefined) throw TypeError("Can't call method on  " + it);
    return it;
  };
});
$__System.registerDynamic('2b', ['14'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var defined = $__require('14');
  module.exports = function (it) {
    return Object(defined(it));
  };
});
$__System.registerDynamic('46', [], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
  var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
  if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef
});
$__System.registerDynamic('47', [], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = function (it) {
    if (typeof it != 'function') throw TypeError(it + ' is not a function!');
    return it;
  };
});
$__System.registerDynamic('1d', ['47'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var aFunction = $__require('47');
  module.exports = function (fn, that, length) {
    aFunction(fn);
    if (that === undefined) return fn;
    switch (length) {
      case 1:
        return function (a) {
          return fn.call(that, a);
        };
      case 2:
        return function (a, b) {
          return fn.call(that, a, b);
        };
      case 3:
        return function (a, b, c) {
          return fn.call(that, a, b, c);
        };
    }
    return function () {
      return fn.apply(that, arguments);
    };
  };
});
$__System.registerDynamic('1f', ['46', '21', '1d'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var global = $__require('46'),
      core = $__require('21'),
      ctx = $__require('1d'),
      PROTOTYPE = 'prototype';
  var $export = function (type, name, source) {
    var IS_FORCED = type & $export.F,
        IS_GLOBAL = type & $export.G,
        IS_STATIC = type & $export.S,
        IS_PROTO = type & $export.P,
        IS_BIND = type & $export.B,
        IS_WRAP = type & $export.W,
        exports = IS_GLOBAL ? core : core[name] || (core[name] = {}),
        target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE],
        key,
        own,
        out;
    if (IS_GLOBAL) source = name;
    for (key in source) {
      own = !IS_FORCED && target && key in target;
      if (own && key in exports) continue;
      out = own ? target[key] : source[key];
      exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] : IS_BIND && own ? ctx(out, global) : IS_WRAP && target[key] == out ? function (C) {
        var F = function (param) {
          return this instanceof C ? new C(param) : C(param);
        };
        F[PROTOTYPE] = C[PROTOTYPE];
        return F;
      }(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
      if (IS_PROTO) (exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out;
    }
  };
  $export.F = 1;
  $export.G = 2;
  $export.S = 4;
  $export.P = 8;
  $export.B = 16;
  $export.W = 32;
  module.exports = $export;
});
$__System.registerDynamic("2c", [], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = function (exec) {
    try {
      return !!exec();
    } catch (e) {
      return true;
    }
  };
});
$__System.registerDynamic('16', ['1f', '21', '2c'], true, function ($__require, exports, module) {
    var global = this || self,
        GLOBAL = global;
    /* */
    var $export = $__require('1f'),
        core = $__require('21'),
        fails = $__require('2c');
    module.exports = function (KEY, exec) {
        var fn = (core.Object || {})[KEY] || Object[KEY],
            exp = {};
        exp[KEY] = exec(fn);
        $export($export.S + $export.F * fails(function () {
            fn(1);
        }), 'Object', exp);
    };
});
$__System.registerDynamic('48', ['2b', '16'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var toObject = $__require('2b');
  $__require('16')('keys', function ($keys) {
    return function keys(it) {
      return $keys(toObject(it));
    };
  });
});
$__System.registerDynamic('21', [], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  var core = module.exports = { version: '1.2.6' };
  if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef
});
$__System.registerDynamic('49', ['48', '21'], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  $__require('48');
  module.exports = $__require('21').Object.keys;
});
$__System.registerDynamic("4a", ["49"], true, function ($__require, exports, module) {
  var global = this || self,
      GLOBAL = global;
  /* */
  module.exports = { "default": $__require("49"), __esModule: true };
});
$__System.register('10', ['3', '4', '5', '28', '4a'], function (_export) {
	var THREE, _createClass, _classCallCheck, randomRange, closestPowerOfTwo, _Object$keys, Geometry;

	return {
		setters: [function (_3) {
			THREE = _3;
		}, function (_) {
			_createClass = _['default'];
		}, function (_2) {
			_classCallCheck = _2['default'];
		}, function (_4) {
			randomRange = _4.randomRange;
			closestPowerOfTwo = _4.closestPowerOfTwo;
		}, function (_a) {
			_Object$keys = _a['default'];
		}],
		execute: function () {
			'use strict';

			Geometry = (function () {
				function Geometry() {
					_classCallCheck(this, Geometry);
				}

				_createClass(Geometry, null, [{
					key: 'createFromAttributes',
					value: function createFromAttributes(attributes) {
						var geometry = new THREE.BufferGeometry();
						var names = _Object$keys(attributes);
						names.forEach(function (name) {
							geometry.addAttribute(name, attributes[name]);
						});
						geometry.boundingBox = new THREE.Box3(new THREE.Vector3(-100, -100, -100), new THREE.Vector3(100, 100, 100));
						geometry.boundingSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0), 100);
						return geometry;
					}
				}, {
					key: 'createRandom',
					value: function createRandom(count) {
						return Geometry.createFromAttributes(Geometry.getRandomAttributes(count | 9));
					}
				}, {
					key: 'getRandomBuffer',
					value: function getRandomBuffer(count, step) {
						var array = new Float32Array(count * step);
						for (var i = 0; i < array.length; i++) {
							array[i] = randomRange(0, 1);
						}
						return new THREE.BufferAttribute(array, step);
					}
				}, {
					key: 'getRandomPoints',
					value: function getRandomPoints(count, step) {
						var points = [];
						for (var i = 0; i < count * step; i++) {
							points.push(randomRange(0, 1));
						}
						return points;
					}
				}, {
					key: 'getRandomAttributes',
					value: function getRandomAttributes(count) {
						return {
							position: Geometry.getRandomBuffer(count, 3),
							normal: Geometry.getRandomBuffer(count, 3),
							color: Geometry.getRandomBuffer(count, 3),
							uv: Geometry.getRandomBuffer(count, 2)
						};
					}
				}, {
					key: 'createTriangleFromPoints',
					value: function createTriangleFromPoints(attributes) {
						// variables
						var count = attributes.position.array.length / 3;
						var dimension = closestPowerOfTwo(Math.sqrt(count));
						var indexVertex = 0,
						    indexUV = 0,
						    indexAnchor = 0,
						    u,
						    v;

						// attributes
						var arrays = {};
						var attributeNames = _Object$keys(attributes);
						attributeNames.forEach(function (name) {
							arrays[name] = new Float32Array(count * 3 * attributes[name].itemSize);
						});
						var anchors = new Float32Array(count * 3 * 2);
						var indexMap = new Float32Array(count * 3 * 2);

						// triangles
						for (var triangleIndex = 0; triangleIndex < count; triangleIndex++) {

							// uv is used to map vertex index to bitmap data
							u = triangleIndex % dimension / dimension;
							v = Math.floor(triangleIndex / dimension) / dimension;

							// positions and normals are on the same for the 3 points
							for (var tri = 0; tri < 3; ++tri) {
								attributeNames.forEach(function (name) {
									var itemSize = attributes[name].itemSize;
									for (var i = 0; i < itemSize; i++) {
										arrays[name][triangleIndex * 9 + tri * itemSize + i] = attributes[name].array[triangleIndex * itemSize + i];
									}
								});

								indexMap[indexUV + 0] = u;
								indexMap[indexUV + 1] = v;

								indexVertex += 3;
								indexUV += 2;
							}

							// offset used to scale triangle in shader
							anchors[indexAnchor] = 0;
							anchors[indexAnchor + 1] = 1;
							anchors[indexAnchor + 2] = -1;
							anchors[indexAnchor + 3] = -1;
							anchors[indexAnchor + 4] = 1;
							anchors[indexAnchor + 5] = -1;
							indexAnchor += 6;
						}

						var geometry = new THREE.BufferGeometry();
						attributeNames.forEach(function (name) {
							geometry.addAttribute(name, new THREE.BufferAttribute(arrays[name], attributes[name].itemSize));
						});
						geometry.addAttribute('anchor', new THREE.BufferAttribute(anchors, 2));
						geometry.addAttribute('indexMap', new THREE.BufferAttribute(indexMap, 2));

						var min = -100;
						var max = 100;
						geometry.boundingBox = new THREE.Box3(new THREE.Vector3(min, min, min), new THREE.Vector3(max, max, max));
						geometry.boundingSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0), max);

						return geometry;
					}
				}, {
					key: 'createQuadFromPoints',
					value: function createQuadFromPoints(points, material, slices) {
						// variables
						var slices = slices || [1, 1];
						var count = points.length / 3;
						var dimension = closestPowerOfTwo(Math.sqrt(count));
						var faces = [slices[0] + 1, slices[1] + 1];
						var vertexCount = faces[0] * faces[1];
						var quadCount = slices[0] * slices[1];

						var meshes = [];
						var verticesMax = 65000 - 1;
						var totalVertices = count * vertexCount;
						var meshCount = 1 + Math.floor(totalVertices / verticesMax);
						var pointIndex = 0;
						for (var m = 0; m < meshCount; ++m) {

							var count;
							if (meshCount > 1) {
								if (m == meshCount - 1) {
									count = totalVertices % verticesMax;
								} else {
									count = verticesMax;
								}
							} else {
								count = totalVertices;
							}

							// attributes
							// var arrays = {};
							var positions = [];
							var anchors = [];
							var indexMap = [];
							var indices = [];
							// var attributeNames = Object.keys(attributes);
							// attributeNames.forEach(name => { arrays[name] = []; });

							for (var index = 0; index < count; ++index) {

								// uv is used to map vertex index to bitmap data
								var u = pointIndex % dimension / dimension;
								var v = Math.floor(pointIndex / dimension) / dimension;

								for (var vertex = 0; vertex < vertexCount; ++vertex) {
									// attributeNames.forEach(name => {
									var itemSize = 3;
									for (var i = 0; i < itemSize; i++) {
										positions.push(points[pointIndex * itemSize + i]);
									}
									// });
									var x = vertex % faces[0] / faces[0];
									var y = Math.floor(vertex / faces[0]) / faces[1];
									anchors.push(x * 2 - 1, y * 2 - 1);
									indexMap.push(u, v);
								}

								// FIX ME
								var vertexIndex = index * vertexCount;
								for (var quad = 0; quad < quadCount; ++quad) {

									var x = quad % faces[0];
									var y = Math.floor(quad / faces[0]);
									var ia = x + y * faces[0];
									var a = vertexIndex + ia;

									var xb = x + 1;
									var yb = y;
									var ib = xb + yb * faces[0];
									var b = vertexIndex + ib;

									var xc = x;
									var yc = y + 1;
									var ic = xc + yc * faces[0];
									var c = vertexIndex + ic;

									var xd = x + 1;
									var yd = y + 1;
									var id = xd + yd * faces[0];
									var d = vertexIndex + id;

									indices.push(a, b, c, b, c, d);
								}

								pointIndex += 1;
							}

							var geometry = new THREE.BufferGeometry();
							// attributeNames.forEach(name => {
							// 	geometry.addAttribute(name, new THREE.BufferAttribute(new Float32Array(arrays[name]), attributes[name].itemSize));
							// });
							geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 2));
							geometry.addAttribute('anchor', new THREE.BufferAttribute(new Float32Array(anchors), 2));
							geometry.addAttribute('indexMap', new THREE.BufferAttribute(new Float32Array(indexMap), 2));
							geometry.setIndex(new THREE.BufferAttribute(new Uint16Array(indices), 1));

							var min = -100;
							var max = 100;
							geometry.boundingBox = new THREE.Box3(new THREE.Vector3(min, min, min), new THREE.Vector3(max, max, max));
							geometry.boundingSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0), max);

							var mesh = new THREE.Mesh(geometry, material);
							meshes.push(mesh);
						}

						return meshes;
					}
				}]);

				return Geometry;
			})();

			_export('default', Geometry);
		}
	};
});

$__System.register('4b', ['3', '4', '5', '8', '9', '10', '28', 'b', 'a'], function (_export) {
	var THREE, _createClass, _classCallCheck, _get, _inherits, Geometry, lerp, Scene, assets, MainScene;

	return {
		setters: [function (_5) {
			THREE = _5;
		}, function (_3) {
			_createClass = _3['default'];
		}, function (_4) {
			_classCallCheck = _4['default'];
		}, function (_) {
			_get = _['default'];
		}, function (_2) {
			_inherits = _2['default'];
		}, function (_6) {
			Geometry = _6['default'];
		}, function (_7) {
			lerp = _7.lerp;
		}, function (_b) {
			Scene = _b['default'];
		}, function (_a) {
			assets = _a['default'];
		}],
		execute: function () {
			'use strict';

			MainScene = (function (_Scene) {
				_inherits(MainScene, _Scene);

				function MainScene() {
					_classCallCheck(this, MainScene);

					_get(Object.getPrototypeOf(MainScene.prototype), 'constructor', this).call(this);
					// bubble
					this.addChildren(Geometry.createQuadFromPoints(Geometry.getRandomPoints(64 * 64, 3), assets.shaderMaterials.bubble));
					// lines
					this.addChildren(Geometry.createQuadFromPoints(Geometry.getRandomPoints(5 * 5, 3), assets.shaderMaterials.line, [1, 20]));
					// paper
					this.addChildren(Geometry.createQuadFromPoints(Geometry.getRandomPoints(5 * 5, 3), assets.shaderMaterials.paper, [1, 20]));

					this.lookAt = new THREE.Vector3();
					this.positionDelta = [0, 0, 0];
					this.targetDelta = [0, 0, 0];
					this.last = 0;
				}

				_createClass(MainScene, [{
					key: 'update',
					value: function update(elapsed) {
						_get(Object.getPrototypeOf(MainScene.prototype), 'update', this).call(this, elapsed);
						var delta = Math.min(1., Math.max(.01, (elapsed - this.last) * 5.));

						var position = assets.animations.getPosition('Camera', elapsed);
						var target = assets.animations.getPosition('Target', elapsed);
						this.positionDelta[0] = lerp(this.positionDelta[0], position[0], delta);
						this.positionDelta[1] = lerp(this.positionDelta[1], position[1], delta);
						this.positionDelta[2] = lerp(this.positionDelta[2], position[2], delta);
						this.camera.position.x = -this.positionDelta[0];
						this.camera.position.y = this.positionDelta[2];
						this.camera.position.z = this.positionDelta[1];
						this.lookAt.x = -target[0];
						this.lookAt.y = target[2];
						this.lookAt.z = target[1];
						this.camera.lookAt(this.lookAt);
						this.camera.updateMatrixWorld(true);

						this.last = elapsed;
					}
				}]);

				return MainScene;
			})(Scene);

			_export('default', MainScene);
		}
	};
});

$__System.register('28', ['3'], function (_export) {
	'use strict';

	var Vector3, sqrt3;

	_export('randomRange', randomRange);

	_export('randomVector', randomVector);

	//https://github.com/mattdesl/lerp/blob/master/index.js

	_export('clamp', clamp);

	// Find the closest power of 2

	_export('lerp', lerp);

	// Used to calculate length of vector from center of box to corner of box

	_export('closestPowerOfTwo', closestPowerOfTwo);

	// Thank to Tomas Akenine-Möller
	// For sharing his Triangle Box Overlaping algorithm
	// http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/tribox3.txt

	_export('distanceBetween', distanceBetween);

	_export('planeBoxOverlap', planeBoxOverlap);

	_export('triangleArea', triangleArea);

	_export('triBoxOverlap', triBoxOverlap);

	function randomRange(min, max) {
		return min + Math.random() * (max - min);
	}

	function randomVector(min, max) {
		return new Vector3(randomRange(min, max), randomRange(min, max), randomRange(min, max));
	}

	function clamp(value, min, max) {
		return Math.max(min, Math.min(max, value));
	}

	function lerp(v0, v1, t) {
		return v0 * (1 - t) + v1 * t;
	}

	function closestPowerOfTwo(num) {
		return Math.pow(2, Math.ceil(Math.log(num) / Math.log(2)));
	}

	//

	function distanceBetween(a, b) {
		return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z));
	}

	function planeBoxOverlap(normal, vert, maxbox) {
		var vmin = new Vector3(0, 0, 0);
		var vmax = new Vector3(0, 0, 0);
		if (normal.x > 0) {
			vmin.x = -maxbox.x - vert.x;vmax.x = maxbox.x - vert.x;
		} else {
			vmin.x = maxbox.x - vert.x;vmax.x = -maxbox.x - vert.x;
		}
		if (normal.y > 0) {
			vmin.y = -maxbox.y - vert.y;vmax.y = maxbox.y - vert.y;
		} else {
			vmin.y = maxbox.y - vert.y;vmax.y = -maxbox.y - vert.y;
		}
		if (normal.z > 0) {
			vmin.z = -maxbox.z - vert.z;vmax.z = maxbox.z - vert.z;
		} else {
			vmin.z = maxbox.z - vert.z;vmax.z = -maxbox.z - vert.z;
		}
		var min = new Vector3(normal.x, normal.y, normal.z);
		var max = new Vector3(normal.x, normal.y, normal.z);
		if (min.dot(vmin) > 0) return 0;
		if (max.dot(vmax) >= 0) return 1;
		return 0;
	}

	function triangleArea(a, b, c) {
		var ab = new Vector3(a.x, a.y, a.z).sub(b);
		var ac = new Vector3(a.x, a.y, a.z).sub(c);
		return ab.cross(ac).length() / 2;
	}

	function triBoxOverlap(boxcenter, boxhalfsize, a, b, c) {
		var v0 = { x: 0, y: 0, z: 0 };
		var v1 = { x: 0, y: 0, z: 0 };
		var v2 = { x: 0, y: 0, z: 0 };
		var min, max, p0, p1, p2, rad, fex, fey, fez;
		var normal = new Vector3(0, 0, 0);
		var e0 = new Vector3(0, 0, 0);
		var e1 = new Vector3(0, 0, 0);
		var e2 = new Vector3(0, 0, 0);

		/* This is the fastest branch on Sun */
		/* move everything so that the boxcenter is in (0,0,0) */
		v0.x = a.x - boxcenter.x;v0.y = a.y - boxcenter.y;v0.z = a.z - boxcenter.z;
		v1.x = b.x - boxcenter.x;v1.y = b.y - boxcenter.y;v1.z = b.z - boxcenter.z;
		v2.x = c.x - boxcenter.x;v2.y = c.y - boxcenter.y;v2.z = c.z - boxcenter.z;
		/* compute triangle edges */
		e0.x = v1.x - v0.x;e0.y = v1.y - v0.y;e0.z = v1.z - v0.z;
		e1.x = v2.x - v1.x;e1.y = v2.y - v1.y;e1.z = v2.z - v1.z;
		e2.x = v0.x - v2.x;e2.y = v0.y - v2.y;e2.z = v0.z - v2.z;

		/* Bullet 3:  */
		/*  test the 9 tests first (this was faster) */
		fex = Math.abs(e0.x);
		fey = Math.abs(e0.y);
		fez = Math.abs(e0.z);
		//
		p0 = e0.z * v0.y - e0.y * v0.z;
		p2 = e0.z * v2.y - e0.y * v2.z;
		if (p0 < p2) {
			min = p0;max = p2;
		} else {
			min = p2;max = p0;
		}
		rad = fez * boxhalfsize.y + fey * boxhalfsize.z;
		if (min > rad || max < -rad) return 0;
		//
		p0 = -e0.z * v0.x + e0.x * v0.z;
		p2 = -e0.z * v2.x + e0.x * v2.z;
		if (p0 < p2) {
			min = p0;max = p2;
		} else {
			min = p2;max = p0;
		}
		rad = fez * boxhalfsize.x + fex * boxhalfsize.z;
		if (min > rad || max < -rad) return 0;
		//
		p1 = e0.y * v1.x - e0.x * v1.y;
		p2 = e0.y * v2.x - e0.x * v2.y;
		if (p2 < p1) {
			min = p2;max = p1;
		} else {
			min = p1;max = p2;
		}
		rad = fey * boxhalfsize.x + fex * boxhalfsize.y;
		if (min > rad || max < -rad) return 0;
		//
		fex = Math.abs(e1.x);
		fey = Math.abs(e1.y);
		fez = Math.abs(e1.z);
		//
		p0 = e1.z * v0.y - e1.y * v0.z;
		p2 = e1.z * v2.y - e1.y * v2.z;
		if (p0 < p2) {
			min = p0;max = p2;
		} else {
			min = p2;max = p0;
		}
		rad = fez * boxhalfsize.y + fey * boxhalfsize.z;
		if (min > rad || max < -rad) return 0;
		//
		p0 = -e1.z * v0.x + e1.x * v0.z;
		p2 = -e1.z * v2.x + e1.x * v2.z;
		if (p0 < p2) {
			min = p0;max = p2;
		} else {
			min = p2;max = p0;
		}
		rad = fez * boxhalfsize.x + fex * boxhalfsize.z;
		if (min > rad || max < -rad) return 0;
		//
		p0 = e1.y * v0.x - e1.x * v0.y;
		p1 = e1.y * v1.x - e1.x * v1.y;
		if (p0 < p1) {
			min = p0;max = p1;
		} else {
			min = p1;max = p0;
		}
		rad = fey * boxhalfsize.x + fex * boxhalfsize.y;
		if (min > rad || max < -rad) return 0;
		//
		fex = Math.abs(e2.x);
		fey = Math.abs(e2.y);
		fez = Math.abs(e2.z);
		//
		p0 = e2.z * v0.y - e2.y * v0.z;
		p1 = e2.z * v1.y - e2.y * v1.z;
		if (p0 < p1) {
			min = p0;max = p1;
		} else {
			min = p1;max = p0;
		}
		rad = fez * boxhalfsize.y + fey * boxhalfsize.z;
		if (min > rad || max < -rad) return 0;
		//
		p0 = -e2.z * v0.x + e2.x * v0.z;
		p1 = -e2.z * v1.x + e2.x * v1.z;
		if (p0 < p1) {
			min = p0;max = p1;
		} else {
			min = p1;max = p0;
		}
		rad = fez * boxhalfsize.x + fex * boxhalfsize.z;
		if (min > rad || max < -rad) return 0;
		//
		p1 = e2.y * v1.x - e2.x * v1.y;
		p2 = e2.y * v2.x - e2.x * v2.y;
		if (p2 < p1) {
			min = p2;max = p1;
		} else {
			min = p1;max = p2;
		}
		rad = fey * boxhalfsize.x + fex * boxhalfsize.y;
		if (min > rad || max < -rad) return 0;

		/* Bullet 1: */
		/*  first test overlap in the {x,y,z}-directions */
		/*  find min, max of the triangle each direction, and test for overlap in */
		/*  that direction -- this is equivalent to testing a minimal AABB around */
		/*  the triangle against the AABB */
		/* test in X-direction */
		min = Math.min(v0.x, Math.min(v1.x, v2.x));
		max = Math.max(v0.x, Math.max(v1.x, v2.x));
		if (min > boxhalfsize.x || max < -boxhalfsize.x) return 0;
		/* test in Y-direction */
		min = Math.min(v0.y, Math.min(v1.y, v2.y));
		max = Math.max(v0.y, Math.max(v1.y, v2.y));
		if (min > boxhalfsize.y || max < -boxhalfsize.y) return 0;
		/* test in Z-direction */
		min = Math.min(v0.z, Math.min(v1.z, v2.z));
		max = Math.max(v0.z, Math.max(v1.z, v2.z));
		if (min > boxhalfsize.z || max < -boxhalfsize.z) return 0;
		/* Bullet 2: */
		/*  test if the box intersects the plane of the triangle */
		/*  compute plane equation of triangle: normal*x+d=0 */
		normal.crossVectors(e0, e1);
		if (0 == planeBoxOverlap(normal, v0, boxhalfsize)) return 0;
		return 1; /* box and triangle overlaps */
	}

	return {
		setters: [function (_) {
			Vector3 = _.Vector3;
		}],
		execute: function () {
			sqrt3 = Math.sqrt(3);

			_export('sqrt3', sqrt3);
		}
	};
});

$__System.register('4c', [], function (_export) {
	// import * as THREE from 'three.js';
	// const clock = new THREE.Clock();

	'use strict';

	var music, isReady;

	_export('start', start);

	_export('getTime', getTime);

	// var musicTime = true;

	function start() {
		music.play();
		// music.addEventListener('ended', function() {
		// 	musicTime = false;
		// 	clock.start();
		// })
	}

	function getTime() {
		// if (musicTime) {
		return music.currentTime;
		// } else {
		// return clock.getElapsedTime();
		// }
	}

	return {
		setters: [],
		execute: function () {
			music = document.getElementById('music');
			isReady = false;

			_export('isReady', isReady);

			music.addEventListener('onloadeddata', function () {
				_export('isReady', isReady = true);
			});
			music.load();
		}
	};
});

(function() {
var define = $__System.amdDefine;
(function(global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define("4d", ["exports"], factory) : (factory((global.THREE = global.THREE || {})));
}(this, (function(exports) {
  'use strict';
  if (Number.EPSILON === undefined) {
    Number.EPSILON = Math.pow(2, -52);
  }
  if (Number.isInteger === undefined) {
    Number.isInteger = function(value) {
      return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
    };
  }
  if (Math.sign === undefined) {
    Math.sign = function(x) {
      return (x < 0) ? -1 : (x > 0) ? 1 : +x;
    };
  }
  if ('name' in Function.prototype === false) {
    Object.defineProperty(Function.prototype, 'name', {get: function() {
        return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1];
      }});
  }
  if (Object.assign === undefined) {
    (function() {
      Object.assign = function(target) {
        'use strict';
        if (target === undefined || target === null) {
          throw new TypeError('Cannot convert undefined or null to object');
        }
        var output = Object(target);
        for (var index = 1; index < arguments.length; index++) {
          var source = arguments[index];
          if (source !== undefined && source !== null) {
            for (var nextKey in source) {
              if (Object.prototype.hasOwnProperty.call(source, nextKey)) {
                output[nextKey] = source[nextKey];
              }
            }
          }
        }
        return output;
      };
    })();
  }
  function EventDispatcher() {}
  Object.assign(EventDispatcher.prototype, {
    addEventListener: function(type, listener) {
      if (this._listeners === undefined)
        this._listeners = {};
      var listeners = this._listeners;
      if (listeners[type] === undefined) {
        listeners[type] = [];
      }
      if (listeners[type].indexOf(listener) === -1) {
        listeners[type].push(listener);
      }
    },
    hasEventListener: function(type, listener) {
      if (this._listeners === undefined)
        return false;
      var listeners = this._listeners;
      return listeners[type] !== undefined && listeners[type].indexOf(listener) !== -1;
    },
    removeEventListener: function(type, listener) {
      if (this._listeners === undefined)
        return;
      var listeners = this._listeners;
      var listenerArray = listeners[type];
      if (listenerArray !== undefined) {
        var index = listenerArray.indexOf(listener);
        if (index !== -1) {
          listenerArray.splice(index, 1);
        }
      }
    },
    dispatchEvent: function(event) {
      if (this._listeners === undefined)
        return;
      var listeners = this._listeners;
      var listenerArray = listeners[event.type];
      if (listenerArray !== undefined) {
        event.target = this;
        var array = listenerArray.slice(0);
        for (var i = 0,
            l = array.length; i < l; i++) {
          array[i].call(this, event);
        }
      }
    }
  });
  var REVISION = '88';
  var MOUSE = {
    LEFT: 0,
    MIDDLE: 1,
    RIGHT: 2
  };
  var CullFaceNone = 0;
  var CullFaceBack = 1;
  var CullFaceFront = 2;
  var CullFaceFrontBack = 3;
  var FrontFaceDirectionCW = 0;
  var FrontFaceDirectionCCW = 1;
  var BasicShadowMap = 0;
  var PCFShadowMap = 1;
  var PCFSoftShadowMap = 2;
  var FrontSide = 0;
  var BackSide = 1;
  var DoubleSide = 2;
  var FlatShading = 1;
  var SmoothShading = 2;
  var NoColors = 0;
  var FaceColors = 1;
  var VertexColors = 2;
  var NoBlending = 0;
  var NormalBlending = 1;
  var AdditiveBlending = 2;
  var SubtractiveBlending = 3;
  var MultiplyBlending = 4;
  var CustomBlending = 5;
  var AddEquation = 100;
  var SubtractEquation = 101;
  var ReverseSubtractEquation = 102;
  var MinEquation = 103;
  var MaxEquation = 104;
  var ZeroFactor = 200;
  var OneFactor = 201;
  var SrcColorFactor = 202;
  var OneMinusSrcColorFactor = 203;
  var SrcAlphaFactor = 204;
  var OneMinusSrcAlphaFactor = 205;
  var DstAlphaFactor = 206;
  var OneMinusDstAlphaFactor = 207;
  var DstColorFactor = 208;
  var OneMinusDstColorFactor = 209;
  var SrcAlphaSaturateFactor = 210;
  var NeverDepth = 0;
  var AlwaysDepth = 1;
  var LessDepth = 2;
  var LessEqualDepth = 3;
  var EqualDepth = 4;
  var GreaterEqualDepth = 5;
  var GreaterDepth = 6;
  var NotEqualDepth = 7;
  var MultiplyOperation = 0;
  var MixOperation = 1;
  var AddOperation = 2;
  var NoToneMapping = 0;
  var LinearToneMapping = 1;
  var ReinhardToneMapping = 2;
  var Uncharted2ToneMapping = 3;
  var CineonToneMapping = 4;
  var UVMapping = 300;
  var CubeReflectionMapping = 301;
  var CubeRefractionMapping = 302;
  var EquirectangularReflectionMapping = 303;
  var EquirectangularRefractionMapping = 304;
  var SphericalReflectionMapping = 305;
  var CubeUVReflectionMapping = 306;
  var CubeUVRefractionMapping = 307;
  var RepeatWrapping = 1000;
  var ClampToEdgeWrapping = 1001;
  var MirroredRepeatWrapping = 1002;
  var NearestFilter = 1003;
  var NearestMipMapNearestFilter = 1004;
  var NearestMipMapLinearFilter = 1005;
  var LinearFilter = 1006;
  var LinearMipMapNearestFilter = 1007;
  var LinearMipMapLinearFilter = 1008;
  var UnsignedByteType = 1009;
  var ByteType = 1010;
  var ShortType = 1011;
  var UnsignedShortType = 1012;
  var IntType = 1013;
  var UnsignedIntType = 1014;
  var FloatType = 1015;
  var HalfFloatType = 1016;
  var UnsignedShort4444Type = 1017;
  var UnsignedShort5551Type = 1018;
  var UnsignedShort565Type = 1019;
  var UnsignedInt248Type = 1020;
  var AlphaFormat = 1021;
  var RGBFormat = 1022;
  var RGBAFormat = 1023;
  var LuminanceFormat = 1024;
  var LuminanceAlphaFormat = 1025;
  var RGBEFormat = RGBAFormat;
  var DepthFormat = 1026;
  var DepthStencilFormat = 1027;
  var RGB_S3TC_DXT1_Format = 2001;
  var RGBA_S3TC_DXT1_Format = 2002;
  var RGBA_S3TC_DXT3_Format = 2003;
  var RGBA_S3TC_DXT5_Format = 2004;
  var RGB_PVRTC_4BPPV1_Format = 2100;
  var RGB_PVRTC_2BPPV1_Format = 2101;
  var RGBA_PVRTC_4BPPV1_Format = 2102;
  var RGBA_PVRTC_2BPPV1_Format = 2103;
  var RGB_ETC1_Format = 2151;
  var LoopOnce = 2200;
  var LoopRepeat = 2201;
  var LoopPingPong = 2202;
  var InterpolateDiscrete = 2300;
  var InterpolateLinear = 2301;
  var InterpolateSmooth = 2302;
  var ZeroCurvatureEnding = 2400;
  var ZeroSlopeEnding = 2401;
  var WrapAroundEnding = 2402;
  var TrianglesDrawMode = 0;
  var TriangleStripDrawMode = 1;
  var TriangleFanDrawMode = 2;
  var LinearEncoding = 3000;
  var sRGBEncoding = 3001;
  var GammaEncoding = 3007;
  var RGBEEncoding = 3002;
  var LogLuvEncoding = 3003;
  var RGBM7Encoding = 3004;
  var RGBM16Encoding = 3005;
  var RGBDEncoding = 3006;
  var BasicDepthPacking = 3200;
  var RGBADepthPacking = 3201;
  var _Math = {
    DEG2RAD: Math.PI / 180,
    RAD2DEG: 180 / Math.PI,
    generateUUID: function() {
      var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
      var rnd = 0,
          r;
      return function generateUUID() {
        var uuid = '';
        for (var i = 0; i < 36; i++) {
          if (i === 8 || i === 13 || i === 18 || i === 23) {
            uuid += '-';
          } else if (i === 14) {
            uuid += '4';
          } else {
            if (rnd <= 0x02)
              rnd = 0x2000000 + (Math.random() * 0x1000000) | 0;
            r = rnd & 0xf;
            rnd = rnd >> 4;
            uuid += chars[(i === 19) ? (r & 0x3) | 0x8 : r];
          }
        }
        return uuid;
      };
    }(),
    clamp: function(value, min, max) {
      return Math.max(min, Math.min(max, value));
    },
    euclideanModulo: function(n, m) {
      return ((n % m) + m) % m;
    },
    mapLinear: function(x, a1, a2, b1, b2) {
      return b1 + (x - a1) * (b2 - b1) / (a2 - a1);
    },
    lerp: function(x, y, t) {
      return (1 - t) * x + t * y;
    },
    smoothstep: function(x, min, max) {
      if (x <= min)
        return 0;
      if (x >= max)
        return 1;
      x = (x - min) / (max - min);
      return x * x * (3 - 2 * x);
    },
    smootherstep: function(x, min, max) {
      if (x <= min)
        return 0;
      if (x >= max)
        return 1;
      x = (x - min) / (max - min);
      return x * x * x * (x * (x * 6 - 15) + 10);
    },
    randInt: function(low, high) {
      return low + Math.floor(Math.random() * (high - low + 1));
    },
    randFloat: function(low, high) {
      return low + Math.random() * (high - low);
    },
    randFloatSpread: function(range) {
      return range * (0.5 - Math.random());
    },
    degToRad: function(degrees) {
      return degrees * _Math.DEG2RAD;
    },
    radToDeg: function(radians) {
      return radians * _Math.RAD2DEG;
    },
    isPowerOfTwo: function(value) {
      return (value & (value - 1)) === 0 && value !== 0;
    },
    ceilPowerOfTwo: function(value) {
      return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2));
    },
    floorPowerOfTwo: function(value) {
      return Math.pow(2, Math.floor(Math.log(value) / Math.LN2));
    }
  };
  function Vector2(x, y) {
    this.x = x || 0;
    this.y = y || 0;
  }
  Object.defineProperties(Vector2.prototype, {
    "width": {
      get: function() {
        return this.x;
      },
      set: function(value) {
        this.x = value;
      }
    },
    "height": {
      get: function() {
        return this.y;
      },
      set: function(value) {
        this.y = value;
      }
    }
  });
  Object.assign(Vector2.prototype, {
    isVector2: true,
    set: function(x, y) {
      this.x = x;
      this.y = y;
      return this;
    },
    setScalar: function(scalar) {
      this.x = scalar;
      this.y = scalar;
      return this;
    },
    setX: function(x) {
      this.x = x;
      return this;
    },
    setY: function(y) {
      this.y = y;
      return this;
    },
    setComponent: function(index, value) {
      switch (index) {
        case 0:
          this.x = value;
          break;
        case 1:
          this.y = value;
          break;
        default:
          throw new Error('index is out of range: ' + index);
      }
      return this;
    },
    getComponent: function(index) {
      switch (index) {
        case 0:
          return this.x;
        case 1:
          return this.y;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    clone: function() {
      return new this.constructor(this.x, this.y);
    },
    copy: function(v) {
      this.x = v.x;
      this.y = v.y;
      return this;
    },
    add: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');
        return this.addVectors(v, w);
      }
      this.x += v.x;
      this.y += v.y;
      return this;
    },
    addScalar: function(s) {
      this.x += s;
      this.y += s;
      return this;
    },
    addVectors: function(a, b) {
      this.x = a.x + b.x;
      this.y = a.y + b.y;
      return this;
    },
    addScaledVector: function(v, s) {
      this.x += v.x * s;
      this.y += v.y * s;
      return this;
    },
    sub: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');
        return this.subVectors(v, w);
      }
      this.x -= v.x;
      this.y -= v.y;
      return this;
    },
    subScalar: function(s) {
      this.x -= s;
      this.y -= s;
      return this;
    },
    subVectors: function(a, b) {
      this.x = a.x - b.x;
      this.y = a.y - b.y;
      return this;
    },
    multiply: function(v) {
      this.x *= v.x;
      this.y *= v.y;
      return this;
    },
    multiplyScalar: function(scalar) {
      this.x *= scalar;
      this.y *= scalar;
      return this;
    },
    divide: function(v) {
      this.x /= v.x;
      this.y /= v.y;
      return this;
    },
    divideScalar: function(scalar) {
      return this.multiplyScalar(1 / scalar);
    },
    applyMatrix3: function(m) {
      var x = this.x,
          y = this.y;
      var e = m.elements;
      this.x = e[0] * x + e[3] * y + e[6];
      this.y = e[1] * x + e[4] * y + e[7];
      return this;
    },
    min: function(v) {
      this.x = Math.min(this.x, v.x);
      this.y = Math.min(this.y, v.y);
      return this;
    },
    max: function(v) {
      this.x = Math.max(this.x, v.x);
      this.y = Math.max(this.y, v.y);
      return this;
    },
    clamp: function(min, max) {
      this.x = Math.max(min.x, Math.min(max.x, this.x));
      this.y = Math.max(min.y, Math.min(max.y, this.y));
      return this;
    },
    clampScalar: function() {
      var min = new Vector2();
      var max = new Vector2();
      return function clampScalar(minVal, maxVal) {
        min.set(minVal, minVal);
        max.set(maxVal, maxVal);
        return this.clamp(min, max);
      };
    }(),
    clampLength: function(min, max) {
      var length = this.length();
      return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
    },
    floor: function() {
      this.x = Math.floor(this.x);
      this.y = Math.floor(this.y);
      return this;
    },
    ceil: function() {
      this.x = Math.ceil(this.x);
      this.y = Math.ceil(this.y);
      return this;
    },
    round: function() {
      this.x = Math.round(this.x);
      this.y = Math.round(this.y);
      return this;
    },
    roundToZero: function() {
      this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x);
      this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y);
      return this;
    },
    negate: function() {
      this.x = -this.x;
      this.y = -this.y;
      return this;
    },
    dot: function(v) {
      return this.x * v.x + this.y * v.y;
    },
    lengthSq: function() {
      return this.x * this.x + this.y * this.y;
    },
    length: function() {
      return Math.sqrt(this.x * this.x + this.y * this.y);
    },
    manhattanLength: function() {
      return Math.abs(this.x) + Math.abs(this.y);
    },
    normalize: function() {
      return this.divideScalar(this.length() || 1);
    },
    angle: function() {
      var angle = Math.atan2(this.y, this.x);
      if (angle < 0)
        angle += 2 * Math.PI;
      return angle;
    },
    distanceTo: function(v) {
      return Math.sqrt(this.distanceToSquared(v));
    },
    distanceToSquared: function(v) {
      var dx = this.x - v.x,
          dy = this.y - v.y;
      return dx * dx + dy * dy;
    },
    manhattanDistanceTo: function(v) {
      return Math.abs(this.x - v.x) + Math.abs(this.y - v.y);
    },
    setLength: function(length) {
      return this.normalize().multiplyScalar(length);
    },
    lerp: function(v, alpha) {
      this.x += (v.x - this.x) * alpha;
      this.y += (v.y - this.y) * alpha;
      return this;
    },
    lerpVectors: function(v1, v2, alpha) {
      return this.subVectors(v2, v1).multiplyScalar(alpha).add(v1);
    },
    equals: function(v) {
      return ((v.x === this.x) && (v.y === this.y));
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this.x = array[offset];
      this.y = array[offset + 1];
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this.x;
      array[offset + 1] = this.y;
      return array;
    },
    fromBufferAttribute: function(attribute, index, offset) {
      if (offset !== undefined) {
        console.warn('THREE.Vector2: offset has been removed from .fromBufferAttribute().');
      }
      this.x = attribute.getX(index);
      this.y = attribute.getY(index);
      return this;
    },
    rotateAround: function(center, angle) {
      var c = Math.cos(angle),
          s = Math.sin(angle);
      var x = this.x - center.x;
      var y = this.y - center.y;
      this.x = x * c - y * s + center.x;
      this.y = x * s + y * c + center.y;
      return this;
    }
  });
  function Matrix4() {
    this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
    if (arguments.length > 0) {
      console.error('THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.');
    }
  }
  Object.assign(Matrix4.prototype, {
    isMatrix4: true,
    set: function(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
      var te = this.elements;
      te[0] = n11;
      te[4] = n12;
      te[8] = n13;
      te[12] = n14;
      te[1] = n21;
      te[5] = n22;
      te[9] = n23;
      te[13] = n24;
      te[2] = n31;
      te[6] = n32;
      te[10] = n33;
      te[14] = n34;
      te[3] = n41;
      te[7] = n42;
      te[11] = n43;
      te[15] = n44;
      return this;
    },
    identity: function() {
      this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
      return this;
    },
    clone: function() {
      return new Matrix4().fromArray(this.elements);
    },
    copy: function(m) {
      var te = this.elements;
      var me = m.elements;
      te[0] = me[0];
      te[1] = me[1];
      te[2] = me[2];
      te[3] = me[3];
      te[4] = me[4];
      te[5] = me[5];
      te[6] = me[6];
      te[7] = me[7];
      te[8] = me[8];
      te[9] = me[9];
      te[10] = me[10];
      te[11] = me[11];
      te[12] = me[12];
      te[13] = me[13];
      te[14] = me[14];
      te[15] = me[15];
      return this;
    },
    copyPosition: function(m) {
      var te = this.elements,
          me = m.elements;
      te[12] = me[12];
      te[13] = me[13];
      te[14] = me[14];
      return this;
    },
    extractBasis: function(xAxis, yAxis, zAxis) {
      xAxis.setFromMatrixColumn(this, 0);
      yAxis.setFromMatrixColumn(this, 1);
      zAxis.setFromMatrixColumn(this, 2);
      return this;
    },
    makeBasis: function(xAxis, yAxis, zAxis) {
      this.set(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, 0, 0, 0, 1);
      return this;
    },
    extractRotation: function() {
      var v1 = new Vector3();
      return function extractRotation(m) {
        var te = this.elements;
        var me = m.elements;
        var scaleX = 1 / v1.setFromMatrixColumn(m, 0).length();
        var scaleY = 1 / v1.setFromMatrixColumn(m, 1).length();
        var scaleZ = 1 / v1.setFromMatrixColumn(m, 2).length();
        te[0] = me[0] * scaleX;
        te[1] = me[1] * scaleX;
        te[2] = me[2] * scaleX;
        te[4] = me[4] * scaleY;
        te[5] = me[5] * scaleY;
        te[6] = me[6] * scaleY;
        te[8] = me[8] * scaleZ;
        te[9] = me[9] * scaleZ;
        te[10] = me[10] * scaleZ;
        return this;
      };
    }(),
    makeRotationFromEuler: function(euler) {
      if (!(euler && euler.isEuler)) {
        console.error('THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.');
      }
      var te = this.elements;
      var x = euler.x,
          y = euler.y,
          z = euler.z;
      var a = Math.cos(x),
          b = Math.sin(x);
      var c = Math.cos(y),
          d = Math.sin(y);
      var e = Math.cos(z),
          f = Math.sin(z);
      if (euler.order === 'XYZ') {
        var ae = a * e,
            af = a * f,
            be = b * e,
            bf = b * f;
        te[0] = c * e;
        te[4] = -c * f;
        te[8] = d;
        te[1] = af + be * d;
        te[5] = ae - bf * d;
        te[9] = -b * c;
        te[2] = bf - ae * d;
        te[6] = be + af * d;
        te[10] = a * c;
      } else if (euler.order === 'YXZ') {
        var ce = c * e,
            cf = c * f,
            de = d * e,
            df = d * f;
        te[0] = ce + df * b;
        te[4] = de * b - cf;
        te[8] = a * d;
        te[1] = a * f;
        te[5] = a * e;
        te[9] = -b;
        te[2] = cf * b - de;
        te[6] = df + ce * b;
        te[10] = a * c;
      } else if (euler.order === 'ZXY') {
        var ce = c * e,
            cf = c * f,
            de = d * e,
            df = d * f;
        te[0] = ce - df * b;
        te[4] = -a * f;
        te[8] = de + cf * b;
        te[1] = cf + de * b;
        te[5] = a * e;
        te[9] = df - ce * b;
        te[2] = -a * d;
        te[6] = b;
        te[10] = a * c;
      } else if (euler.order === 'ZYX') {
        var ae = a * e,
            af = a * f,
            be = b * e,
            bf = b * f;
        te[0] = c * e;
        te[4] = be * d - af;
        te[8] = ae * d + bf;
        te[1] = c * f;
        te[5] = bf * d + ae;
        te[9] = af * d - be;
        te[2] = -d;
        te[6] = b * c;
        te[10] = a * c;
      } else if (euler.order === 'YZX') {
        var ac = a * c,
            ad = a * d,
            bc = b * c,
            bd = b * d;
        te[0] = c * e;
        te[4] = bd - ac * f;
        te[8] = bc * f + ad;
        te[1] = f;
        te[5] = a * e;
        te[9] = -b * e;
        te[2] = -d * e;
        te[6] = ad * f + bc;
        te[10] = ac - bd * f;
      } else if (euler.order === 'XZY') {
        var ac = a * c,
            ad = a * d,
            bc = b * c,
            bd = b * d;
        te[0] = c * e;
        te[4] = -f;
        te[8] = d * e;
        te[1] = ac * f + bd;
        te[5] = a * e;
        te[9] = ad * f - bc;
        te[2] = bc * f - ad;
        te[6] = b * e;
        te[10] = bd * f + ac;
      }
      te[3] = 0;
      te[7] = 0;
      te[11] = 0;
      te[12] = 0;
      te[13] = 0;
      te[14] = 0;
      te[15] = 1;
      return this;
    },
    makeRotationFromQuaternion: function(q) {
      var te = this.elements;
      var x = q._x,
          y = q._y,
          z = q._z,
          w = q._w;
      var x2 = x + x,
          y2 = y + y,
          z2 = z + z;
      var xx = x * x2,
          xy = x * y2,
          xz = x * z2;
      var yy = y * y2,
          yz = y * z2,
          zz = z * z2;
      var wx = w * x2,
          wy = w * y2,
          wz = w * z2;
      te[0] = 1 - (yy + zz);
      te[4] = xy - wz;
      te[8] = xz + wy;
      te[1] = xy + wz;
      te[5] = 1 - (xx + zz);
      te[9] = yz - wx;
      te[2] = xz - wy;
      te[6] = yz + wx;
      te[10] = 1 - (xx + yy);
      te[3] = 0;
      te[7] = 0;
      te[11] = 0;
      te[12] = 0;
      te[13] = 0;
      te[14] = 0;
      te[15] = 1;
      return this;
    },
    lookAt: function() {
      var x = new Vector3();
      var y = new Vector3();
      var z = new Vector3();
      return function lookAt(eye, target, up) {
        var te = this.elements;
        z.subVectors(eye, target);
        if (z.lengthSq() === 0) {
          z.z = 1;
        }
        z.normalize();
        x.crossVectors(up, z);
        if (x.lengthSq() === 0) {
          if (Math.abs(up.z) === 1) {
            z.x += 0.0001;
          } else {
            z.z += 0.0001;
          }
          z.normalize();
          x.crossVectors(up, z);
        }
        x.normalize();
        y.crossVectors(z, x);
        te[0] = x.x;
        te[4] = y.x;
        te[8] = z.x;
        te[1] = x.y;
        te[5] = y.y;
        te[9] = z.y;
        te[2] = x.z;
        te[6] = y.z;
        te[10] = z.z;
        return this;
      };
    }(),
    multiply: function(m, n) {
      if (n !== undefined) {
        console.warn('THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.');
        return this.multiplyMatrices(m, n);
      }
      return this.multiplyMatrices(this, m);
    },
    premultiply: function(m) {
      return this.multiplyMatrices(m, this);
    },
    multiplyMatrices: function(a, b) {
      var ae = a.elements;
      var be = b.elements;
      var te = this.elements;
      var a11 = ae[0],
          a12 = ae[4],
          a13 = ae[8],
          a14 = ae[12];
      var a21 = ae[1],
          a22 = ae[5],
          a23 = ae[9],
          a24 = ae[13];
      var a31 = ae[2],
          a32 = ae[6],
          a33 = ae[10],
          a34 = ae[14];
      var a41 = ae[3],
          a42 = ae[7],
          a43 = ae[11],
          a44 = ae[15];
      var b11 = be[0],
          b12 = be[4],
          b13 = be[8],
          b14 = be[12];
      var b21 = be[1],
          b22 = be[5],
          b23 = be[9],
          b24 = be[13];
      var b31 = be[2],
          b32 = be[6],
          b33 = be[10],
          b34 = be[14];
      var b41 = be[3],
          b42 = be[7],
          b43 = be[11],
          b44 = be[15];
      te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
      te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
      te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
      te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
      te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
      te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
      te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
      te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
      te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
      te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
      te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
      te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
      te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
      te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
      te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
      te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
      return this;
    },
    multiplyScalar: function(s) {
      var te = this.elements;
      te[0] *= s;
      te[4] *= s;
      te[8] *= s;
      te[12] *= s;
      te[1] *= s;
      te[5] *= s;
      te[9] *= s;
      te[13] *= s;
      te[2] *= s;
      te[6] *= s;
      te[10] *= s;
      te[14] *= s;
      te[3] *= s;
      te[7] *= s;
      te[11] *= s;
      te[15] *= s;
      return this;
    },
    applyToBufferAttribute: function() {
      var v1 = new Vector3();
      return function applyToBufferAttribute(attribute) {
        for (var i = 0,
            l = attribute.count; i < l; i++) {
          v1.x = attribute.getX(i);
          v1.y = attribute.getY(i);
          v1.z = attribute.getZ(i);
          v1.applyMatrix4(this);
          attribute.setXYZ(i, v1.x, v1.y, v1.z);
        }
        return attribute;
      };
    }(),
    determinant: function() {
      var te = this.elements;
      var n11 = te[0],
          n12 = te[4],
          n13 = te[8],
          n14 = te[12];
      var n21 = te[1],
          n22 = te[5],
          n23 = te[9],
          n24 = te[13];
      var n31 = te[2],
          n32 = te[6],
          n33 = te[10],
          n34 = te[14];
      var n41 = te[3],
          n42 = te[7],
          n43 = te[11],
          n44 = te[15];
      return (n41 * (+n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34) + n42 * (+n11 * n23 * n34 - n11 * n24 * n33 + n14 * n21 * n33 - n13 * n21 * n34 + n13 * n24 * n31 - n14 * n23 * n31) + n43 * (+n11 * n24 * n32 - n11 * n22 * n34 - n14 * n21 * n32 + n12 * n21 * n34 + n14 * n22 * n31 - n12 * n24 * n31) + n44 * (-n13 * n22 * n31 - n11 * n23 * n32 + n11 * n22 * n33 + n13 * n21 * n32 - n12 * n21 * n33 + n12 * n23 * n31));
    },
    transpose: function() {
      var te = this.elements;
      var tmp;
      tmp = te[1];
      te[1] = te[4];
      te[4] = tmp;
      tmp = te[2];
      te[2] = te[8];
      te[8] = tmp;
      tmp = te[6];
      te[6] = te[9];
      te[9] = tmp;
      tmp = te[3];
      te[3] = te[12];
      te[12] = tmp;
      tmp = te[7];
      te[7] = te[13];
      te[13] = tmp;
      tmp = te[11];
      te[11] = te[14];
      te[14] = tmp;
      return this;
    },
    setPosition: function(v) {
      var te = this.elements;
      te[12] = v.x;
      te[13] = v.y;
      te[14] = v.z;
      return this;
    },
    getInverse: function(m, throwOnDegenerate) {
      var te = this.elements,
          me = m.elements,
          n11 = me[0],
          n21 = me[1],
          n31 = me[2],
          n41 = me[3],
          n12 = me[4],
          n22 = me[5],
          n32 = me[6],
          n42 = me[7],
          n13 = me[8],
          n23 = me[9],
          n33 = me[10],
          n43 = me[11],
          n14 = me[12],
          n24 = me[13],
          n34 = me[14],
          n44 = me[15],
          t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
          t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
          t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
          t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
      var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
      if (det === 0) {
        var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0";
        if (throwOnDegenerate === true) {
          throw new Error(msg);
        } else {
          console.warn(msg);
        }
        return this.identity();
      }
      var detInv = 1 / det;
      te[0] = t11 * detInv;
      te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv;
      te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv;
      te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv;
      te[4] = t12 * detInv;
      te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv;
      te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv;
      te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv;
      te[8] = t13 * detInv;
      te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv;
      te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv;
      te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv;
      te[12] = t14 * detInv;
      te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv;
      te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv;
      te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv;
      return this;
    },
    scale: function(v) {
      var te = this.elements;
      var x = v.x,
          y = v.y,
          z = v.z;
      te[0] *= x;
      te[4] *= y;
      te[8] *= z;
      te[1] *= x;
      te[5] *= y;
      te[9] *= z;
      te[2] *= x;
      te[6] *= y;
      te[10] *= z;
      te[3] *= x;
      te[7] *= y;
      te[11] *= z;
      return this;
    },
    getMaxScaleOnAxis: function() {
      var te = this.elements;
      var scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2];
      var scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6];
      var scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10];
      return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq));
    },
    makeTranslation: function(x, y, z) {
      this.set(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1);
      return this;
    },
    makeRotationX: function(theta) {
      var c = Math.cos(theta),
          s = Math.sin(theta);
      this.set(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
      return this;
    },
    makeRotationY: function(theta) {
      var c = Math.cos(theta),
          s = Math.sin(theta);
      this.set(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
      return this;
    },
    makeRotationZ: function(theta) {
      var c = Math.cos(theta),
          s = Math.sin(theta);
      this.set(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
      return this;
    },
    makeRotationAxis: function(axis, angle) {
      var c = Math.cos(angle);
      var s = Math.sin(angle);
      var t = 1 - c;
      var x = axis.x,
          y = axis.y,
          z = axis.z;
      var tx = t * x,
          ty = t * y;
      this.set(tx * x + c, tx * y - s * z, tx * z + s * y, 0, tx * y + s * z, ty * y + c, ty * z - s * x, 0, tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 0, 0, 0, 1);
      return this;
    },
    makeScale: function(x, y, z) {
      this.set(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1);
      return this;
    },
    makeShear: function(x, y, z) {
      this.set(1, y, z, 0, x, 1, z, 0, x, y, 1, 0, 0, 0, 0, 1);
      return this;
    },
    compose: function(position, quaternion, scale) {
      this.makeRotationFromQuaternion(quaternion);
      this.scale(scale);
      this.setPosition(position);
      return this;
    },
    decompose: function() {
      var vector = new Vector3();
      var matrix = new Matrix4();
      return function decompose(position, quaternion, scale) {
        var te = this.elements;
        var sx = vector.set(te[0], te[1], te[2]).length();
        var sy = vector.set(te[4], te[5], te[6]).length();
        var sz = vector.set(te[8], te[9], te[10]).length();
        var det = this.determinant();
        if (det < 0)
          sx = -sx;
        position.x = te[12];
        position.y = te[13];
        position.z = te[14];
        matrix.copy(this);
        var invSX = 1 / sx;
        var invSY = 1 / sy;
        var invSZ = 1 / sz;
        matrix.elements[0] *= invSX;
        matrix.elements[1] *= invSX;
        matrix.elements[2] *= invSX;
        matrix.elements[4] *= invSY;
        matrix.elements[5] *= invSY;
        matrix.elements[6] *= invSY;
        matrix.elements[8] *= invSZ;
        matrix.elements[9] *= invSZ;
        matrix.elements[10] *= invSZ;
        quaternion.setFromRotationMatrix(matrix);
        scale.x = sx;
        scale.y = sy;
        scale.z = sz;
        return this;
      };
    }(),
    makePerspective: function(left, right, top, bottom, near, far) {
      if (far === undefined) {
        console.warn('THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.');
      }
      var te = this.elements;
      var x = 2 * near / (right - left);
      var y = 2 * near / (top - bottom);
      var a = (right + left) / (right - left);
      var b = (top + bottom) / (top - bottom);
      var c = -(far + near) / (far - near);
      var d = -2 * far * near / (far - near);
      te[0] = x;
      te[4] = 0;
      te[8] = a;
      te[12] = 0;
      te[1] = 0;
      te[5] = y;
      te[9] = b;
      te[13] = 0;
      te[2] = 0;
      te[6] = 0;
      te[10] = c;
      te[14] = d;
      te[3] = 0;
      te[7] = 0;
      te[11] = -1;
      te[15] = 0;
      return this;
    },
    makeOrthographic: function(left, right, top, bottom, near, far) {
      var te = this.elements;
      var w = 1.0 / (right - left);
      var h = 1.0 / (top - bottom);
      var p = 1.0 / (far - near);
      var x = (right + left) * w;
      var y = (top + bottom) * h;
      var z = (far + near) * p;
      te[0] = 2 * w;
      te[4] = 0;
      te[8] = 0;
      te[12] = -x;
      te[1] = 0;
      te[5] = 2 * h;
      te[9] = 0;
      te[13] = -y;
      te[2] = 0;
      te[6] = 0;
      te[10] = -2 * p;
      te[14] = -z;
      te[3] = 0;
      te[7] = 0;
      te[11] = 0;
      te[15] = 1;
      return this;
    },
    equals: function(matrix) {
      var te = this.elements;
      var me = matrix.elements;
      for (var i = 0; i < 16; i++) {
        if (te[i] !== me[i])
          return false;
      }
      return true;
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      for (var i = 0; i < 16; i++) {
        this.elements[i] = array[i + offset];
      }
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      var te = this.elements;
      array[offset] = te[0];
      array[offset + 1] = te[1];
      array[offset + 2] = te[2];
      array[offset + 3] = te[3];
      array[offset + 4] = te[4];
      array[offset + 5] = te[5];
      array[offset + 6] = te[6];
      array[offset + 7] = te[7];
      array[offset + 8] = te[8];
      array[offset + 9] = te[9];
      array[offset + 10] = te[10];
      array[offset + 11] = te[11];
      array[offset + 12] = te[12];
      array[offset + 13] = te[13];
      array[offset + 14] = te[14];
      array[offset + 15] = te[15];
      return array;
    }
  });
  function Quaternion(x, y, z, w) {
    this._x = x || 0;
    this._y = y || 0;
    this._z = z || 0;
    this._w = (w !== undefined) ? w : 1;
  }
  Object.assign(Quaternion, {
    slerp: function(qa, qb, qm, t) {
      return qm.copy(qa).slerp(qb, t);
    },
    slerpFlat: function(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) {
      var x0 = src0[srcOffset0 + 0],
          y0 = src0[srcOffset0 + 1],
          z0 = src0[srcOffset0 + 2],
          w0 = src0[srcOffset0 + 3],
          x1 = src1[srcOffset1 + 0],
          y1 = src1[srcOffset1 + 1],
          z1 = src1[srcOffset1 + 2],
          w1 = src1[srcOffset1 + 3];
      if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) {
        var s = 1 - t,
            cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
            dir = (cos >= 0 ? 1 : -1),
            sqrSin = 1 - cos * cos;
        if (sqrSin > Number.EPSILON) {
          var sin = Math.sqrt(sqrSin),
              len = Math.atan2(sin, cos * dir);
          s = Math.sin(s * len) / sin;
          t = Math.sin(t * len) / sin;
        }
        var tDir = t * dir;
        x0 = x0 * s + x1 * tDir;
        y0 = y0 * s + y1 * tDir;
        z0 = z0 * s + z1 * tDir;
        w0 = w0 * s + w1 * tDir;
        if (s === 1 - t) {
          var f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0);
          x0 *= f;
          y0 *= f;
          z0 *= f;
          w0 *= f;
        }
      }
      dst[dstOffset] = x0;
      dst[dstOffset + 1] = y0;
      dst[dstOffset + 2] = z0;
      dst[dstOffset + 3] = w0;
    }
  });
  Object.defineProperties(Quaternion.prototype, {
    x: {
      get: function() {
        return this._x;
      },
      set: function(value) {
        this._x = value;
        this.onChangeCallback();
      }
    },
    y: {
      get: function() {
        return this._y;
      },
      set: function(value) {
        this._y = value;
        this.onChangeCallback();
      }
    },
    z: {
      get: function() {
        return this._z;
      },
      set: function(value) {
        this._z = value;
        this.onChangeCallback();
      }
    },
    w: {
      get: function() {
        return this._w;
      },
      set: function(value) {
        this._w = value;
        this.onChangeCallback();
      }
    }
  });
  Object.assign(Quaternion.prototype, {
    set: function(x, y, z, w) {
      this._x = x;
      this._y = y;
      this._z = z;
      this._w = w;
      this.onChangeCallback();
      return this;
    },
    clone: function() {
      return new this.constructor(this._x, this._y, this._z, this._w);
    },
    copy: function(quaternion) {
      this._x = quaternion.x;
      this._y = quaternion.y;
      this._z = quaternion.z;
      this._w = quaternion.w;
      this.onChangeCallback();
      return this;
    },
    setFromEuler: function(euler, update) {
      if (!(euler && euler.isEuler)) {
        throw new Error('THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.');
      }
      var x = euler._x,
          y = euler._y,
          z = euler._z,
          order = euler.order;
      var cos = Math.cos;
      var sin = Math.sin;
      var c1 = cos(x / 2);
      var c2 = cos(y / 2);
      var c3 = cos(z / 2);
      var s1 = sin(x / 2);
      var s2 = sin(y / 2);
      var s3 = sin(z / 2);
      if (order === 'XYZ') {
        this._x = s1 * c2 * c3 + c1 * s2 * s3;
        this._y = c1 * s2 * c3 - s1 * c2 * s3;
        this._z = c1 * c2 * s3 + s1 * s2 * c3;
        this._w = c1 * c2 * c3 - s1 * s2 * s3;
      } else if (order === 'YXZ') {
        this._x = s1 * c2 * c3 + c1 * s2 * s3;
        this._y = c1 * s2 * c3 - s1 * c2 * s3;
        this._z = c1 * c2 * s3 - s1 * s2 * c3;
        this._w = c1 * c2 * c3 + s1 * s2 * s3;
      } else if (order === 'ZXY') {
        this._x = s1 * c2 * c3 - c1 * s2 * s3;
        this._y = c1 * s2 * c3 + s1 * c2 * s3;
        this._z = c1 * c2 * s3 + s1 * s2 * c3;
        this._w = c1 * c2 * c3 - s1 * s2 * s3;
      } else if (order === 'ZYX') {
        this._x = s1 * c2 * c3 - c1 * s2 * s3;
        this._y = c1 * s2 * c3 + s1 * c2 * s3;
        this._z = c1 * c2 * s3 - s1 * s2 * c3;
        this._w = c1 * c2 * c3 + s1 * s2 * s3;
      } else if (order === 'YZX') {
        this._x = s1 * c2 * c3 + c1 * s2 * s3;
        this._y = c1 * s2 * c3 + s1 * c2 * s3;
        this._z = c1 * c2 * s3 - s1 * s2 * c3;
        this._w = c1 * c2 * c3 - s1 * s2 * s3;
      } else if (order === 'XZY') {
        this._x = s1 * c2 * c3 - c1 * s2 * s3;
        this._y = c1 * s2 * c3 - s1 * c2 * s3;
        this._z = c1 * c2 * s3 + s1 * s2 * c3;
        this._w = c1 * c2 * c3 + s1 * s2 * s3;
      }
      if (update !== false)
        this.onChangeCallback();
      return this;
    },
    setFromAxisAngle: function(axis, angle) {
      var halfAngle = angle / 2,
          s = Math.sin(halfAngle);
      this._x = axis.x * s;
      this._y = axis.y * s;
      this._z = axis.z * s;
      this._w = Math.cos(halfAngle);
      this.onChangeCallback();
      return this;
    },
    setFromRotationMatrix: function(m) {
      var te = m.elements,
          m11 = te[0],
          m12 = te[4],
          m13 = te[8],
          m21 = te[1],
          m22 = te[5],
          m23 = te[9],
          m31 = te[2],
          m32 = te[6],
          m33 = te[10],
          trace = m11 + m22 + m33,
          s;
      if (trace > 0) {
        s = 0.5 / Math.sqrt(trace + 1.0);
        this._w = 0.25 / s;
        this._x = (m32 - m23) * s;
        this._y = (m13 - m31) * s;
        this._z = (m21 - m12) * s;
      } else if (m11 > m22 && m11 > m33) {
        s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
        this._w = (m32 - m23) / s;
        this._x = 0.25 * s;
        this._y = (m12 + m21) / s;
        this._z = (m13 + m31) / s;
      } else if (m22 > m33) {
        s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
        this._w = (m13 - m31) / s;
        this._x = (m12 + m21) / s;
        this._y = 0.25 * s;
        this._z = (m23 + m32) / s;
      } else {
        s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
        this._w = (m21 - m12) / s;
        this._x = (m13 + m31) / s;
        this._y = (m23 + m32) / s;
        this._z = 0.25 * s;
      }
      this.onChangeCallback();
      return this;
    },
    setFromUnitVectors: function() {
      var v1 = new Vector3();
      var r;
      var EPS = 0.000001;
      return function setFromUnitVectors(vFrom, vTo) {
        if (v1 === undefined)
          v1 = new Vector3();
        r = vFrom.dot(vTo) + 1;
        if (r < EPS) {
          r = 0;
          if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
            v1.set(-vFrom.y, vFrom.x, 0);
          } else {
            v1.set(0, -vFrom.z, vFrom.y);
          }
        } else {
          v1.crossVectors(vFrom, vTo);
        }
        this._x = v1.x;
        this._y = v1.y;
        this._z = v1.z;
        this._w = r;
        return this.normalize();
      };
    }(),
    inverse: function() {
      return this.conjugate().normalize();
    },
    conjugate: function() {
      this._x *= -1;
      this._y *= -1;
      this._z *= -1;
      this.onChangeCallback();
      return this;
    },
    dot: function(v) {
      return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
    },
    lengthSq: function() {
      return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
    },
    length: function() {
      return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w);
    },
    normalize: function() {
      var l = this.length();
      if (l === 0) {
        this._x = 0;
        this._y = 0;
        this._z = 0;
        this._w = 1;
      } else {
        l = 1 / l;
        this._x = this._x * l;
        this._y = this._y * l;
        this._z = this._z * l;
        this._w = this._w * l;
      }
      this.onChangeCallback();
      return this;
    },
    multiply: function(q, p) {
      if (p !== undefined) {
        console.warn('THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.');
        return this.multiplyQuaternions(q, p);
      }
      return this.multiplyQuaternions(this, q);
    },
    premultiply: function(q) {
      return this.multiplyQuaternions(q, this);
    },
    multiplyQuaternions: function(a, b) {
      var qax = a._x,
          qay = a._y,
          qaz = a._z,
          qaw = a._w;
      var qbx = b._x,
          qby = b._y,
          qbz = b._z,
          qbw = b._w;
      this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
      this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
      this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
      this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
      this.onChangeCallback();
      return this;
    },
    slerp: function(qb, t) {
      if (t === 0)
        return this;
      if (t === 1)
        return this.copy(qb);
      var x = this._x,
          y = this._y,
          z = this._z,
          w = this._w;
      var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
      if (cosHalfTheta < 0) {
        this._w = -qb._w;
        this._x = -qb._x;
        this._y = -qb._y;
        this._z = -qb._z;
        cosHalfTheta = -cosHalfTheta;
      } else {
        this.copy(qb);
      }
      if (cosHalfTheta >= 1.0) {
        this._w = w;
        this._x = x;
        this._y = y;
        this._z = z;
        return this;
      }
      var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
      if (Math.abs(sinHalfTheta) < 0.001) {
        this._w = 0.5 * (w + this._w);
        this._x = 0.5 * (x + this._x);
        this._y = 0.5 * (y + this._y);
        this._z = 0.5 * (z + this._z);
        return this;
      }
      var halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta);
      var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta,
          ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
      this._w = (w * ratioA + this._w * ratioB);
      this._x = (x * ratioA + this._x * ratioB);
      this._y = (y * ratioA + this._y * ratioB);
      this._z = (z * ratioA + this._z * ratioB);
      this.onChangeCallback();
      return this;
    },
    equals: function(quaternion) {
      return (quaternion._x === this._x) && (quaternion._y === this._y) && (quaternion._z === this._z) && (quaternion._w === this._w);
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this._x = array[offset];
      this._y = array[offset + 1];
      this._z = array[offset + 2];
      this._w = array[offset + 3];
      this.onChangeCallback();
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this._x;
      array[offset + 1] = this._y;
      array[offset + 2] = this._z;
      array[offset + 3] = this._w;
      return array;
    },
    onChange: function(callback) {
      this.onChangeCallback = callback;
      return this;
    },
    onChangeCallback: function() {}
  });
  function Vector3(x, y, z) {
    this.x = x || 0;
    this.y = y || 0;
    this.z = z || 0;
  }
  Object.assign(Vector3.prototype, {
    isVector3: true,
    set: function(x, y, z) {
      this.x = x;
      this.y = y;
      this.z = z;
      return this;
    },
    setScalar: function(scalar) {
      this.x = scalar;
      this.y = scalar;
      this.z = scalar;
      return this;
    },
    setX: function(x) {
      this.x = x;
      return this;
    },
    setY: function(y) {
      this.y = y;
      return this;
    },
    setZ: function(z) {
      this.z = z;
      return this;
    },
    setComponent: function(index, value) {
      switch (index) {
        case 0:
          this.x = value;
          break;
        case 1:
          this.y = value;
          break;
        case 2:
          this.z = value;
          break;
        default:
          throw new Error('index is out of range: ' + index);
      }
      return this;
    },
    getComponent: function(index) {
      switch (index) {
        case 0:
          return this.x;
        case 1:
          return this.y;
        case 2:
          return this.z;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    clone: function() {
      return new this.constructor(this.x, this.y, this.z);
    },
    copy: function(v) {
      this.x = v.x;
      this.y = v.y;
      this.z = v.z;
      return this;
    },
    add: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');
        return this.addVectors(v, w);
      }
      this.x += v.x;
      this.y += v.y;
      this.z += v.z;
      return this;
    },
    addScalar: function(s) {
      this.x += s;
      this.y += s;
      this.z += s;
      return this;
    },
    addVectors: function(a, b) {
      this.x = a.x + b.x;
      this.y = a.y + b.y;
      this.z = a.z + b.z;
      return this;
    },
    addScaledVector: function(v, s) {
      this.x += v.x * s;
      this.y += v.y * s;
      this.z += v.z * s;
      return this;
    },
    sub: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');
        return this.subVectors(v, w);
      }
      this.x -= v.x;
      this.y -= v.y;
      this.z -= v.z;
      return this;
    },
    subScalar: function(s) {
      this.x -= s;
      this.y -= s;
      this.z -= s;
      return this;
    },
    subVectors: function(a, b) {
      this.x = a.x - b.x;
      this.y = a.y - b.y;
      this.z = a.z - b.z;
      return this;
    },
    multiply: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.');
        return this.multiplyVectors(v, w);
      }
      this.x *= v.x;
      this.y *= v.y;
      this.z *= v.z;
      return this;
    },
    multiplyScalar: function(scalar) {
      this.x *= scalar;
      this.y *= scalar;
      this.z *= scalar;
      return this;
    },
    multiplyVectors: function(a, b) {
      this.x = a.x * b.x;
      this.y = a.y * b.y;
      this.z = a.z * b.z;
      return this;
    },
    applyEuler: function() {
      var quaternion = new Quaternion();
      return function applyEuler(euler) {
        if (!(euler && euler.isEuler)) {
          console.error('THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.');
        }
        return this.applyQuaternion(quaternion.setFromEuler(euler));
      };
    }(),
    applyAxisAngle: function() {
      var quaternion = new Quaternion();
      return function applyAxisAngle(axis, angle) {
        return this.applyQuaternion(quaternion.setFromAxisAngle(axis, angle));
      };
    }(),
    applyMatrix3: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var e = m.elements;
      this.x = e[0] * x + e[3] * y + e[6] * z;
      this.y = e[1] * x + e[4] * y + e[7] * z;
      this.z = e[2] * x + e[5] * y + e[8] * z;
      return this;
    },
    applyMatrix4: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var e = m.elements;
      var w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
      this.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * w;
      this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w;
      this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w;
      return this;
    },
    applyQuaternion: function(q) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var qx = q.x,
          qy = q.y,
          qz = q.z,
          qw = q.w;
      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;
      this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
      this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
      this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
      return this;
    },
    project: function() {
      var matrix = new Matrix4();
      return function project(camera) {
        matrix.multiplyMatrices(camera.projectionMatrix, matrix.getInverse(camera.matrixWorld));
        return this.applyMatrix4(matrix);
      };
    }(),
    unproject: function() {
      var matrix = new Matrix4();
      return function unproject(camera) {
        matrix.multiplyMatrices(camera.matrixWorld, matrix.getInverse(camera.projectionMatrix));
        return this.applyMatrix4(matrix);
      };
    }(),
    transformDirection: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var e = m.elements;
      this.x = e[0] * x + e[4] * y + e[8] * z;
      this.y = e[1] * x + e[5] * y + e[9] * z;
      this.z = e[2] * x + e[6] * y + e[10] * z;
      return this.normalize();
    },
    divide: function(v) {
      this.x /= v.x;
      this.y /= v.y;
      this.z /= v.z;
      return this;
    },
    divideScalar: function(scalar) {
      return this.multiplyScalar(1 / scalar);
    },
    min: function(v) {
      this.x = Math.min(this.x, v.x);
      this.y = Math.min(this.y, v.y);
      this.z = Math.min(this.z, v.z);
      return this;
    },
    max: function(v) {
      this.x = Math.max(this.x, v.x);
      this.y = Math.max(this.y, v.y);
      this.z = Math.max(this.z, v.z);
      return this;
    },
    clamp: function(min, max) {
      this.x = Math.max(min.x, Math.min(max.x, this.x));
      this.y = Math.max(min.y, Math.min(max.y, this.y));
      this.z = Math.max(min.z, Math.min(max.z, this.z));
      return this;
    },
    clampScalar: function() {
      var min = new Vector3();
      var max = new Vector3();
      return function clampScalar(minVal, maxVal) {
        min.set(minVal, minVal, minVal);
        max.set(maxVal, maxVal, maxVal);
        return this.clamp(min, max);
      };
    }(),
    clampLength: function(min, max) {
      var length = this.length();
      return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
    },
    floor: function() {
      this.x = Math.floor(this.x);
      this.y = Math.floor(this.y);
      this.z = Math.floor(this.z);
      return this;
    },
    ceil: function() {
      this.x = Math.ceil(this.x);
      this.y = Math.ceil(this.y);
      this.z = Math.ceil(this.z);
      return this;
    },
    round: function() {
      this.x = Math.round(this.x);
      this.y = Math.round(this.y);
      this.z = Math.round(this.z);
      return this;
    },
    roundToZero: function() {
      this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x);
      this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y);
      this.z = (this.z < 0) ? Math.ceil(this.z) : Math.floor(this.z);
      return this;
    },
    negate: function() {
      this.x = -this.x;
      this.y = -this.y;
      this.z = -this.z;
      return this;
    },
    dot: function(v) {
      return this.x * v.x + this.y * v.y + this.z * v.z;
    },
    lengthSq: function() {
      return this.x * this.x + this.y * this.y + this.z * this.z;
    },
    length: function() {
      return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
    },
    manhattanLength: function() {
      return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z);
    },
    normalize: function() {
      return this.divideScalar(this.length() || 1);
    },
    setLength: function(length) {
      return this.normalize().multiplyScalar(length);
    },
    lerp: function(v, alpha) {
      this.x += (v.x - this.x) * alpha;
      this.y += (v.y - this.y) * alpha;
      this.z += (v.z - this.z) * alpha;
      return this;
    },
    lerpVectors: function(v1, v2, alpha) {
      return this.subVectors(v2, v1).multiplyScalar(alpha).add(v1);
    },
    cross: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.');
        return this.crossVectors(v, w);
      }
      return this.crossVectors(this, v);
    },
    crossVectors: function(a, b) {
      var ax = a.x,
          ay = a.y,
          az = a.z;
      var bx = b.x,
          by = b.y,
          bz = b.z;
      this.x = ay * bz - az * by;
      this.y = az * bx - ax * bz;
      this.z = ax * by - ay * bx;
      return this;
    },
    projectOnVector: function(vector) {
      var scalar = vector.dot(this) / vector.lengthSq();
      return this.copy(vector).multiplyScalar(scalar);
    },
    projectOnPlane: function() {
      var v1 = new Vector3();
      return function projectOnPlane(planeNormal) {
        v1.copy(this).projectOnVector(planeNormal);
        return this.sub(v1);
      };
    }(),
    reflect: function() {
      var v1 = new Vector3();
      return function reflect(normal) {
        return this.sub(v1.copy(normal).multiplyScalar(2 * this.dot(normal)));
      };
    }(),
    angleTo: function(v) {
      var theta = this.dot(v) / (Math.sqrt(this.lengthSq() * v.lengthSq()));
      return Math.acos(_Math.clamp(theta, -1, 1));
    },
    distanceTo: function(v) {
      return Math.sqrt(this.distanceToSquared(v));
    },
    distanceToSquared: function(v) {
      var dx = this.x - v.x,
          dy = this.y - v.y,
          dz = this.z - v.z;
      return dx * dx + dy * dy + dz * dz;
    },
    manhattanDistanceTo: function(v) {
      return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z);
    },
    setFromSpherical: function(s) {
      var sinPhiRadius = Math.sin(s.phi) * s.radius;
      this.x = sinPhiRadius * Math.sin(s.theta);
      this.y = Math.cos(s.phi) * s.radius;
      this.z = sinPhiRadius * Math.cos(s.theta);
      return this;
    },
    setFromCylindrical: function(c) {
      this.x = c.radius * Math.sin(c.theta);
      this.y = c.y;
      this.z = c.radius * Math.cos(c.theta);
      return this;
    },
    setFromMatrixPosition: function(m) {
      var e = m.elements;
      this.x = e[12];
      this.y = e[13];
      this.z = e[14];
      return this;
    },
    setFromMatrixScale: function(m) {
      var sx = this.setFromMatrixColumn(m, 0).length();
      var sy = this.setFromMatrixColumn(m, 1).length();
      var sz = this.setFromMatrixColumn(m, 2).length();
      this.x = sx;
      this.y = sy;
      this.z = sz;
      return this;
    },
    setFromMatrixColumn: function(m, index) {
      return this.fromArray(m.elements, index * 4);
    },
    equals: function(v) {
      return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this.x = array[offset];
      this.y = array[offset + 1];
      this.z = array[offset + 2];
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this.x;
      array[offset + 1] = this.y;
      array[offset + 2] = this.z;
      return array;
    },
    fromBufferAttribute: function(attribute, index, offset) {
      if (offset !== undefined) {
        console.warn('THREE.Vector3: offset has been removed from .fromBufferAttribute().');
      }
      this.x = attribute.getX(index);
      this.y = attribute.getY(index);
      this.z = attribute.getZ(index);
      return this;
    }
  });
  function Matrix3() {
    this.elements = [1, 0, 0, 0, 1, 0, 0, 0, 1];
    if (arguments.length > 0) {
      console.error('THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.');
    }
  }
  Object.assign(Matrix3.prototype, {
    isMatrix3: true,
    set: function(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
      var te = this.elements;
      te[0] = n11;
      te[1] = n21;
      te[2] = n31;
      te[3] = n12;
      te[4] = n22;
      te[5] = n32;
      te[6] = n13;
      te[7] = n23;
      te[8] = n33;
      return this;
    },
    identity: function() {
      this.set(1, 0, 0, 0, 1, 0, 0, 0, 1);
      return this;
    },
    clone: function() {
      return new this.constructor().fromArray(this.elements);
    },
    copy: function(m) {
      var te = this.elements;
      var me = m.elements;
      te[0] = me[0];
      te[1] = me[1];
      te[2] = me[2];
      te[3] = me[3];
      te[4] = me[4];
      te[5] = me[5];
      te[6] = me[6];
      te[7] = me[7];
      te[8] = me[8];
      return this;
    },
    setFromMatrix4: function(m) {
      var me = m.elements;
      this.set(me[0], me[4], me[8], me[1], me[5], me[9], me[2], me[6], me[10]);
      return this;
    },
    applyToBufferAttribute: function() {
      var v1 = new Vector3();
      return function applyToBufferAttribute(attribute) {
        for (var i = 0,
            l = attribute.count; i < l; i++) {
          v1.x = attribute.getX(i);
          v1.y = attribute.getY(i);
          v1.z = attribute.getZ(i);
          v1.applyMatrix3(this);
          attribute.setXYZ(i, v1.x, v1.y, v1.z);
        }
        return attribute;
      };
    }(),
    multiply: function(m) {
      return this.multiplyMatrices(this, m);
    },
    premultiply: function(m) {
      return this.multiplyMatrices(m, this);
    },
    multiplyMatrices: function(a, b) {
      var ae = a.elements;
      var be = b.elements;
      var te = this.elements;
      var a11 = ae[0],
          a12 = ae[3],
          a13 = ae[6];
      var a21 = ae[1],
          a22 = ae[4],
          a23 = ae[7];
      var a31 = ae[2],
          a32 = ae[5],
          a33 = ae[8];
      var b11 = be[0],
          b12 = be[3],
          b13 = be[6];
      var b21 = be[1],
          b22 = be[4],
          b23 = be[7];
      var b31 = be[2],
          b32 = be[5],
          b33 = be[8];
      te[0] = a11 * b11 + a12 * b21 + a13 * b31;
      te[3] = a11 * b12 + a12 * b22 + a13 * b32;
      te[6] = a11 * b13 + a12 * b23 + a13 * b33;
      te[1] = a21 * b11 + a22 * b21 + a23 * b31;
      te[4] = a21 * b12 + a22 * b22 + a23 * b32;
      te[7] = a21 * b13 + a22 * b23 + a23 * b33;
      te[2] = a31 * b11 + a32 * b21 + a33 * b31;
      te[5] = a31 * b12 + a32 * b22 + a33 * b32;
      te[8] = a31 * b13 + a32 * b23 + a33 * b33;
      return this;
    },
    multiplyScalar: function(s) {
      var te = this.elements;
      te[0] *= s;
      te[3] *= s;
      te[6] *= s;
      te[1] *= s;
      te[4] *= s;
      te[7] *= s;
      te[2] *= s;
      te[5] *= s;
      te[8] *= s;
      return this;
    },
    determinant: function() {
      var te = this.elements;
      var a = te[0],
          b = te[1],
          c = te[2],
          d = te[3],
          e = te[4],
          f = te[5],
          g = te[6],
          h = te[7],
          i = te[8];
      return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
    },
    getInverse: function(matrix, throwOnDegenerate) {
      if (matrix && matrix.isMatrix4) {
        console.error("THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument.");
      }
      var me = matrix.elements,
          te = this.elements,
          n11 = me[0],
          n21 = me[1],
          n31 = me[2],
          n12 = me[3],
          n22 = me[4],
          n32 = me[5],
          n13 = me[6],
          n23 = me[7],
          n33 = me[8],
          t11 = n33 * n22 - n32 * n23,
          t12 = n32 * n13 - n33 * n12,
          t13 = n23 * n12 - n22 * n13,
          det = n11 * t11 + n21 * t12 + n31 * t13;
      if (det === 0) {
        var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0";
        if (throwOnDegenerate === true) {
          throw new Error(msg);
        } else {
          console.warn(msg);
        }
        return this.identity();
      }
      var detInv = 1 / det;
      te[0] = t11 * detInv;
      te[1] = (n31 * n23 - n33 * n21) * detInv;
      te[2] = (n32 * n21 - n31 * n22) * detInv;
      te[3] = t12 * detInv;
      te[4] = (n33 * n11 - n31 * n13) * detInv;
      te[5] = (n31 * n12 - n32 * n11) * detInv;
      te[6] = t13 * detInv;
      te[7] = (n21 * n13 - n23 * n11) * detInv;
      te[8] = (n22 * n11 - n21 * n12) * detInv;
      return this;
    },
    transpose: function() {
      var tmp,
          m = this.elements;
      tmp = m[1];
      m[1] = m[3];
      m[3] = tmp;
      tmp = m[2];
      m[2] = m[6];
      m[6] = tmp;
      tmp = m[5];
      m[5] = m[7];
      m[7] = tmp;
      return this;
    },
    getNormalMatrix: function(matrix4) {
      return this.setFromMatrix4(matrix4).getInverse(this).transpose();
    },
    transposeIntoArray: function(r) {
      var m = this.elements;
      r[0] = m[0];
      r[1] = m[3];
      r[2] = m[6];
      r[3] = m[1];
      r[4] = m[4];
      r[5] = m[7];
      r[6] = m[2];
      r[7] = m[5];
      r[8] = m[8];
      return this;
    },
    setUvTransform: function(tx, ty, sx, sy, rotation, cx, cy) {
      var c = Math.cos(rotation);
      var s = Math.sin(rotation);
      this.set(sx * c, sx * s, -sx * (c * cx + s * cy) + cx + tx, -sy * s, sy * c, -sy * (-s * cx + c * cy) + cy + ty, 0, 0, 1);
    },
    scale: function(sx, sy) {
      var te = this.elements;
      te[0] *= sx;
      te[3] *= sx;
      te[6] *= sx;
      te[1] *= sy;
      te[4] *= sy;
      te[7] *= sy;
      return this;
    },
    rotate: function(theta) {
      var c = Math.cos(theta);
      var s = Math.sin(theta);
      var te = this.elements;
      var a11 = te[0],
          a12 = te[3],
          a13 = te[6];
      var a21 = te[1],
          a22 = te[4],
          a23 = te[7];
      te[0] = c * a11 + s * a21;
      te[3] = c * a12 + s * a22;
      te[6] = c * a13 + s * a23;
      te[1] = -s * a11 + c * a21;
      te[4] = -s * a12 + c * a22;
      te[7] = -s * a13 + c * a23;
      return this;
    },
    translate: function(tx, ty) {
      var te = this.elements;
      te[0] += tx * te[2];
      te[3] += tx * te[5];
      te[6] += tx * te[8];
      te[1] += ty * te[2];
      te[4] += ty * te[5];
      te[7] += ty * te[8];
      return this;
    },
    equals: function(matrix) {
      var te = this.elements;
      var me = matrix.elements;
      for (var i = 0; i < 9; i++) {
        if (te[i] !== me[i])
          return false;
      }
      return true;
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      for (var i = 0; i < 9; i++) {
        this.elements[i] = array[i + offset];
      }
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      var te = this.elements;
      array[offset] = te[0];
      array[offset + 1] = te[1];
      array[offset + 2] = te[2];
      array[offset + 3] = te[3];
      array[offset + 4] = te[4];
      array[offset + 5] = te[5];
      array[offset + 6] = te[6];
      array[offset + 7] = te[7];
      array[offset + 8] = te[8];
      return array;
    }
  });
  var textureId = 0;
  function Texture(image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding) {
    Object.defineProperty(this, 'id', {value: textureId++});
    this.uuid = _Math.generateUUID();
    this.name = '';
    this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
    this.mipmaps = [];
    this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
    this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
    this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
    this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
    this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
    this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
    this.format = format !== undefined ? format : RGBAFormat;
    this.type = type !== undefined ? type : UnsignedByteType;
    this.offset = new Vector2(0, 0);
    this.repeat = new Vector2(1, 1);
    this.center = new Vector2(0, 0);
    this.rotation = 0;
    this.matrixAutoUpdate = true;
    this.matrix = new Matrix3();
    this.generateMipmaps = true;
    this.premultiplyAlpha = false;
    this.flipY = true;
    this.unpackAlignment = 4;
    this.encoding = encoding !== undefined ? encoding : LinearEncoding;
    this.version = 0;
    this.onUpdate = null;
  }
  Texture.DEFAULT_IMAGE = undefined;
  Texture.DEFAULT_MAPPING = UVMapping;
  Object.defineProperty(Texture.prototype, "needsUpdate", {set: function(value) {
      if (value === true)
        this.version++;
    }});
  Object.assign(Texture.prototype, EventDispatcher.prototype, {
    constructor: Texture,
    isTexture: true,
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.name = source.name;
      this.image = source.image;
      this.mipmaps = source.mipmaps.slice(0);
      this.mapping = source.mapping;
      this.wrapS = source.wrapS;
      this.wrapT = source.wrapT;
      this.magFilter = source.magFilter;
      this.minFilter = source.minFilter;
      this.anisotropy = source.anisotropy;
      this.format = source.format;
      this.type = source.type;
      this.offset.copy(source.offset);
      this.repeat.copy(source.repeat);
      this.center.copy(source.center);
      this.rotation = source.rotation;
      this.matrixAutoUpdate = source.matrixAutoUpdate;
      this.matrix.copy(source.matrix);
      this.generateMipmaps = source.generateMipmaps;
      this.premultiplyAlpha = source.premultiplyAlpha;
      this.flipY = source.flipY;
      this.unpackAlignment = source.unpackAlignment;
      this.encoding = source.encoding;
      return this;
    },
    toJSON: function(meta) {
      var isRootObject = (meta === undefined || typeof meta === 'string');
      if (!isRootObject && meta.textures[this.uuid] !== undefined) {
        return meta.textures[this.uuid];
      }
      function getDataURL(image) {
        var canvas;
        if (image instanceof HTMLCanvasElement) {
          canvas = image;
        } else {
          canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
          canvas.width = image.width;
          canvas.height = image.height;
          var context = canvas.getContext('2d');
          if (image instanceof ImageData) {
            context.putImageData(image, 0, 0);
          } else {
            context.drawImage(image, 0, 0, image.width, image.height);
          }
        }
        if (canvas.width > 2048 || canvas.height > 2048) {
          return canvas.toDataURL('image/jpeg', 0.6);
        } else {
          return canvas.toDataURL('image/png');
        }
      }
      var output = {
        metadata: {
          version: 4.5,
          type: 'Texture',
          generator: 'Texture.toJSON'
        },
        uuid: this.uuid,
        name: this.name,
        mapping: this.mapping,
        repeat: [this.repeat.x, this.repeat.y],
        offset: [this.offset.x, this.offset.y],
        center: [this.center.x, this.center.y],
        rotation: this.rotation,
        wrap: [this.wrapS, this.wrapT],
        minFilter: this.minFilter,
        magFilter: this.magFilter,
        anisotropy: this.anisotropy,
        flipY: this.flipY
      };
      if (this.image !== undefined) {
        var image = this.image;
        if (image.uuid === undefined) {
          image.uuid = _Math.generateUUID();
        }
        if (!isRootObject && meta.images[image.uuid] === undefined) {
          meta.images[image.uuid] = {
            uuid: image.uuid,
            url: getDataURL(image)
          };
        }
        output.image = image.uuid;
      }
      if (!isRootObject) {
        meta.textures[this.uuid] = output;
      }
      return output;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    },
    transformUv: function(uv) {
      if (this.mapping !== UVMapping)
        return;
      uv.applyMatrix3(this.matrix);
      if (uv.x < 0 || uv.x > 1) {
        switch (this.wrapS) {
          case RepeatWrapping:
            uv.x = uv.x - Math.floor(uv.x);
            break;
          case ClampToEdgeWrapping:
            uv.x = uv.x < 0 ? 0 : 1;
            break;
          case MirroredRepeatWrapping:
            if (Math.abs(Math.floor(uv.x) % 2) === 1) {
              uv.x = Math.ceil(uv.x) - uv.x;
            } else {
              uv.x = uv.x - Math.floor(uv.x);
            }
            break;
        }
      }
      if (uv.y < 0 || uv.y > 1) {
        switch (this.wrapT) {
          case RepeatWrapping:
            uv.y = uv.y - Math.floor(uv.y);
            break;
          case ClampToEdgeWrapping:
            uv.y = uv.y < 0 ? 0 : 1;
            break;
          case MirroredRepeatWrapping:
            if (Math.abs(Math.floor(uv.y) % 2) === 1) {
              uv.y = Math.ceil(uv.y) - uv.y;
            } else {
              uv.y = uv.y - Math.floor(uv.y);
            }
            break;
        }
      }
      if (this.flipY) {
        uv.y = 1 - uv.y;
      }
    }
  });
  function Vector4(x, y, z, w) {
    this.x = x || 0;
    this.y = y || 0;
    this.z = z || 0;
    this.w = (w !== undefined) ? w : 1;
  }
  Object.assign(Vector4.prototype, {
    isVector4: true,
    set: function(x, y, z, w) {
      this.x = x;
      this.y = y;
      this.z = z;
      this.w = w;
      return this;
    },
    setScalar: function(scalar) {
      this.x = scalar;
      this.y = scalar;
      this.z = scalar;
      this.w = scalar;
      return this;
    },
    setX: function(x) {
      this.x = x;
      return this;
    },
    setY: function(y) {
      this.y = y;
      return this;
    },
    setZ: function(z) {
      this.z = z;
      return this;
    },
    setW: function(w) {
      this.w = w;
      return this;
    },
    setComponent: function(index, value) {
      switch (index) {
        case 0:
          this.x = value;
          break;
        case 1:
          this.y = value;
          break;
        case 2:
          this.z = value;
          break;
        case 3:
          this.w = value;
          break;
        default:
          throw new Error('index is out of range: ' + index);
      }
      return this;
    },
    getComponent: function(index) {
      switch (index) {
        case 0:
          return this.x;
        case 1:
          return this.y;
        case 2:
          return this.z;
        case 3:
          return this.w;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    clone: function() {
      return new this.constructor(this.x, this.y, this.z, this.w);
    },
    copy: function(v) {
      this.x = v.x;
      this.y = v.y;
      this.z = v.z;
      this.w = (v.w !== undefined) ? v.w : 1;
      return this;
    },
    add: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');
        return this.addVectors(v, w);
      }
      this.x += v.x;
      this.y += v.y;
      this.z += v.z;
      this.w += v.w;
      return this;
    },
    addScalar: function(s) {
      this.x += s;
      this.y += s;
      this.z += s;
      this.w += s;
      return this;
    },
    addVectors: function(a, b) {
      this.x = a.x + b.x;
      this.y = a.y + b.y;
      this.z = a.z + b.z;
      this.w = a.w + b.w;
      return this;
    },
    addScaledVector: function(v, s) {
      this.x += v.x * s;
      this.y += v.y * s;
      this.z += v.z * s;
      this.w += v.w * s;
      return this;
    },
    sub: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');
        return this.subVectors(v, w);
      }
      this.x -= v.x;
      this.y -= v.y;
      this.z -= v.z;
      this.w -= v.w;
      return this;
    },
    subScalar: function(s) {
      this.x -= s;
      this.y -= s;
      this.z -= s;
      this.w -= s;
      return this;
    },
    subVectors: function(a, b) {
      this.x = a.x - b.x;
      this.y = a.y - b.y;
      this.z = a.z - b.z;
      this.w = a.w - b.w;
      return this;
    },
    multiplyScalar: function(scalar) {
      this.x *= scalar;
      this.y *= scalar;
      this.z *= scalar;
      this.w *= scalar;
      return this;
    },
    applyMatrix4: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z,
          w = this.w;
      var e = m.elements;
      this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w;
      this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w;
      this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w;
      this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w;
      return this;
    },
    divideScalar: function(scalar) {
      return this.multiplyScalar(1 / scalar);
    },
    setAxisAngleFromQuaternion: function(q) {
      this.w = 2 * Math.acos(q.w);
      var s = Math.sqrt(1 - q.w * q.w);
      if (s < 0.0001) {
        this.x = 1;
        this.y = 0;
        this.z = 0;
      } else {
        this.x = q.x / s;
        this.y = q.y / s;
        this.z = q.z / s;
      }
      return this;
    },
    setAxisAngleFromRotationMatrix: function(m) {
      var angle,
          x,
          y,
          z,
          epsilon = 0.01,
          epsilon2 = 0.1,
          te = m.elements,
          m11 = te[0],
          m12 = te[4],
          m13 = te[8],
          m21 = te[1],
          m22 = te[5],
          m23 = te[9],
          m31 = te[2],
          m32 = te[6],
          m33 = te[10];
      if ((Math.abs(m12 - m21) < epsilon) && (Math.abs(m13 - m31) < epsilon) && (Math.abs(m23 - m32) < epsilon)) {
        if ((Math.abs(m12 + m21) < epsilon2) && (Math.abs(m13 + m31) < epsilon2) && (Math.abs(m23 + m32) < epsilon2) && (Math.abs(m11 + m22 + m33 - 3) < epsilon2)) {
          this.set(1, 0, 0, 0);
          return this;
        }
        angle = Math.PI;
        var xx = (m11 + 1) / 2;
        var yy = (m22 + 1) / 2;
        var zz = (m33 + 1) / 2;
        var xy = (m12 + m21) / 4;
        var xz = (m13 + m31) / 4;
        var yz = (m23 + m32) / 4;
        if ((xx > yy) && (xx > zz)) {
          if (xx < epsilon) {
            x = 0;
            y = 0.707106781;
            z = 0.707106781;
          } else {
            x = Math.sqrt(xx);
            y = xy / x;
            z = xz / x;
          }
        } else if (yy > zz) {
          if (yy < epsilon) {
            x = 0.707106781;
            y = 0;
            z = 0.707106781;
          } else {
            y = Math.sqrt(yy);
            x = xy / y;
            z = yz / y;
          }
        } else {
          if (zz < epsilon) {
            x = 0.707106781;
            y = 0.707106781;
            z = 0;
          } else {
            z = Math.sqrt(zz);
            x = xz / z;
            y = yz / z;
          }
        }
        this.set(x, y, z, angle);
        return this;
      }
      var s = Math.sqrt((m32 - m23) * (m32 - m23) + (m13 - m31) * (m13 - m31) + (m21 - m12) * (m21 - m12));
      if (Math.abs(s) < 0.001)
        s = 1;
      this.x = (m32 - m23) / s;
      this.y = (m13 - m31) / s;
      this.z = (m21 - m12) / s;
      this.w = Math.acos((m11 + m22 + m33 - 1) / 2);
      return this;
    },
    min: function(v) {
      this.x = Math.min(this.x, v.x);
      this.y = Math.min(this.y, v.y);
      this.z = Math.min(this.z, v.z);
      this.w = Math.min(this.w, v.w);
      return this;
    },
    max: function(v) {
      this.x = Math.max(this.x, v.x);
      this.y = Math.max(this.y, v.y);
      this.z = Math.max(this.z, v.z);
      this.w = Math.max(this.w, v.w);
      return this;
    },
    clamp: function(min, max) {
      this.x = Math.max(min.x, Math.min(max.x, this.x));
      this.y = Math.max(min.y, Math.min(max.y, this.y));
      this.z = Math.max(min.z, Math.min(max.z, this.z));
      this.w = Math.max(min.w, Math.min(max.w, this.w));
      return this;
    },
    clampScalar: function() {
      var min,
          max;
      return function clampScalar(minVal, maxVal) {
        if (min === undefined) {
          min = new Vector4();
          max = new Vector4();
        }
        min.set(minVal, minVal, minVal, minVal);
        max.set(maxVal, maxVal, maxVal, maxVal);
        return this.clamp(min, max);
      };
    }(),
    clampLength: function(min, max) {
      var length = this.length();
      return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
    },
    floor: function() {
      this.x = Math.floor(this.x);
      this.y = Math.floor(this.y);
      this.z = Math.floor(this.z);
      this.w = Math.floor(this.w);
      return this;
    },
    ceil: function() {
      this.x = Math.ceil(this.x);
      this.y = Math.ceil(this.y);
      this.z = Math.ceil(this.z);
      this.w = Math.ceil(this.w);
      return this;
    },
    round: function() {
      this.x = Math.round(this.x);
      this.y = Math.round(this.y);
      this.z = Math.round(this.z);
      this.w = Math.round(this.w);
      return this;
    },
    roundToZero: function() {
      this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x);
      this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y);
      this.z = (this.z < 0) ? Math.ceil(this.z) : Math.floor(this.z);
      this.w = (this.w < 0) ? Math.ceil(this.w) : Math.floor(this.w);
      return this;
    },
    negate: function() {
      this.x = -this.x;
      this.y = -this.y;
      this.z = -this.z;
      this.w = -this.w;
      return this;
    },
    dot: function(v) {
      return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
    },
    lengthSq: function() {
      return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
    },
    length: function() {
      return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
    },
    manhattanLength: function() {
      return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w);
    },
    normalize: function() {
      return this.divideScalar(this.length() || 1);
    },
    setLength: function(length) {
      return this.normalize().multiplyScalar(length);
    },
    lerp: function(v, alpha) {
      this.x += (v.x - this.x) * alpha;
      this.y += (v.y - this.y) * alpha;
      this.z += (v.z - this.z) * alpha;
      this.w += (v.w - this.w) * alpha;
      return this;
    },
    lerpVectors: function(v1, v2, alpha) {
      return this.subVectors(v2, v1).multiplyScalar(alpha).add(v1);
    },
    equals: function(v) {
      return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z) && (v.w === this.w));
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this.x = array[offset];
      this.y = array[offset + 1];
      this.z = array[offset + 2];
      this.w = array[offset + 3];
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this.x;
      array[offset + 1] = this.y;
      array[offset + 2] = this.z;
      array[offset + 3] = this.w;
      return array;
    },
    fromBufferAttribute: function(attribute, index, offset) {
      if (offset !== undefined) {
        console.warn('THREE.Vector4: offset has been removed from .fromBufferAttribute().');
      }
      this.x = attribute.getX(index);
      this.y = attribute.getY(index);
      this.z = attribute.getZ(index);
      this.w = attribute.getW(index);
      return this;
    }
  });
  function WebGLRenderTarget(width, height, options) {
    this.uuid = _Math.generateUUID();
    this.width = width;
    this.height = height;
    this.scissor = new Vector4(0, 0, width, height);
    this.scissorTest = false;
    this.viewport = new Vector4(0, 0, width, height);
    options = options || {};
    if (options.minFilter === undefined)
      options.minFilter = LinearFilter;
    this.texture = new Texture(undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding);
    this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
    this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
    this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
  }
  Object.assign(WebGLRenderTarget.prototype, EventDispatcher.prototype, {
    isWebGLRenderTarget: true,
    setSize: function(width, height) {
      if (this.width !== width || this.height !== height) {
        this.width = width;
        this.height = height;
        this.dispose();
      }
      this.viewport.set(0, 0, width, height);
      this.scissor.set(0, 0, width, height);
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.width = source.width;
      this.height = source.height;
      this.viewport.copy(source.viewport);
      this.texture = source.texture.clone();
      this.depthBuffer = source.depthBuffer;
      this.stencilBuffer = source.stencilBuffer;
      this.depthTexture = source.depthTexture;
      return this;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  });
  function WebGLRenderTargetCube(width, height, options) {
    WebGLRenderTarget.call(this, width, height, options);
    this.activeCubeFace = 0;
    this.activeMipMapLevel = 0;
  }
  WebGLRenderTargetCube.prototype = Object.create(WebGLRenderTarget.prototype);
  WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;
  WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;
  function DataTexture(data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding) {
    Texture.call(this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
    this.image = {
      data: data,
      width: width,
      height: height
    };
    this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
    this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
    this.generateMipmaps = false;
    this.flipY = false;
    this.unpackAlignment = 1;
  }
  DataTexture.prototype = Object.create(Texture.prototype);
  DataTexture.prototype.constructor = DataTexture;
  DataTexture.prototype.isDataTexture = true;
  function CubeTexture(images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding) {
    images = images !== undefined ? images : [];
    mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
    Texture.call(this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
    this.flipY = false;
  }
  CubeTexture.prototype = Object.create(Texture.prototype);
  CubeTexture.prototype.constructor = CubeTexture;
  CubeTexture.prototype.isCubeTexture = true;
  Object.defineProperty(CubeTexture.prototype, 'images', {
    get: function() {
      return this.image;
    },
    set: function(value) {
      this.image = value;
    }
  });
  var emptyTexture = new Texture();
  var emptyCubeTexture = new CubeTexture();
  function UniformContainer() {
    this.seq = [];
    this.map = {};
  }
  var arrayCacheF32 = [];
  var arrayCacheI32 = [];
  var mat4array = new Float32Array(16);
  var mat3array = new Float32Array(9);
  function flatten(array, nBlocks, blockSize) {
    var firstElem = array[0];
    if (firstElem <= 0 || firstElem > 0)
      return array;
    var n = nBlocks * blockSize,
        r = arrayCacheF32[n];
    if (r === undefined) {
      r = new Float32Array(n);
      arrayCacheF32[n] = r;
    }
    if (nBlocks !== 0) {
      firstElem.toArray(r, 0);
      for (var i = 1,
          offset = 0; i !== nBlocks; ++i) {
        offset += blockSize;
        array[i].toArray(r, offset);
      }
    }
    return r;
  }
  function allocTexUnits(renderer, n) {
    var r = arrayCacheI32[n];
    if (r === undefined) {
      r = new Int32Array(n);
      arrayCacheI32[n] = r;
    }
    for (var i = 0; i !== n; ++i)
      r[i] = renderer.allocTextureUnit();
    return r;
  }
  function setValue1f(gl, v) {
    gl.uniform1f(this.addr, v);
  }
  function setValue1i(gl, v) {
    gl.uniform1i(this.addr, v);
  }
  function setValue2fv(gl, v) {
    if (v.x === undefined) {
      gl.uniform2fv(this.addr, v);
    } else {
      gl.uniform2f(this.addr, v.x, v.y);
    }
  }
  function setValue3fv(gl, v) {
    if (v.x !== undefined) {
      gl.uniform3f(this.addr, v.x, v.y, v.z);
    } else if (v.r !== undefined) {
      gl.uniform3f(this.addr, v.r, v.g, v.b);
    } else {
      gl.uniform3fv(this.addr, v);
    }
  }
  function setValue4fv(gl, v) {
    if (v.x === undefined) {
      gl.uniform4fv(this.addr, v);
    } else {
      gl.uniform4f(this.addr, v.x, v.y, v.z, v.w);
    }
  }
  function setValue2fm(gl, v) {
    gl.uniformMatrix2fv(this.addr, false, v.elements || v);
  }
  function setValue3fm(gl, v) {
    if (v.elements === undefined) {
      gl.uniformMatrix3fv(this.addr, false, v);
    } else {
      mat3array.set(v.elements);
      gl.uniformMatrix3fv(this.addr, false, mat3array);
    }
  }
  function setValue4fm(gl, v) {
    if (v.elements === undefined) {
      gl.uniformMatrix4fv(this.addr, false, v);
    } else {
      mat4array.set(v.elements);
      gl.uniformMatrix4fv(this.addr, false, mat4array);
    }
  }
  function setValueT1(gl, v, renderer) {
    var unit = renderer.allocTextureUnit();
    gl.uniform1i(this.addr, unit);
    renderer.setTexture2D(v || emptyTexture, unit);
  }
  function setValueT6(gl, v, renderer) {
    var unit = renderer.allocTextureUnit();
    gl.uniform1i(this.addr, unit);
    renderer.setTextureCube(v || emptyCubeTexture, unit);
  }
  function setValue2iv(gl, v) {
    gl.uniform2iv(this.addr, v);
  }
  function setValue3iv(gl, v) {
    gl.uniform3iv(this.addr, v);
  }
  function setValue4iv(gl, v) {
    gl.uniform4iv(this.addr, v);
  }
  function getSingularSetter(type) {
    switch (type) {
      case 0x1406:
        return setValue1f;
      case 0x8b50:
        return setValue2fv;
      case 0x8b51:
        return setValue3fv;
      case 0x8b52:
        return setValue4fv;
      case 0x8b5a:
        return setValue2fm;
      case 0x8b5b:
        return setValue3fm;
      case 0x8b5c:
        return setValue4fm;
      case 0x8b5e:
      case 0x8d66:
        return setValueT1;
      case 0x8b60:
        return setValueT6;
      case 0x1404:
      case 0x8b56:
        return setValue1i;
      case 0x8b53:
      case 0x8b57:
        return setValue2iv;
      case 0x8b54:
      case 0x8b58:
        return setValue3iv;
      case 0x8b55:
      case 0x8b59:
        return setValue4iv;
    }
  }
  function setValue1fv(gl, v) {
    gl.uniform1fv(this.addr, v);
  }
  function setValue1iv(gl, v) {
    gl.uniform1iv(this.addr, v);
  }
  function setValueV2a(gl, v) {
    gl.uniform2fv(this.addr, flatten(v, this.size, 2));
  }
  function setValueV3a(gl, v) {
    gl.uniform3fv(this.addr, flatten(v, this.size, 3));
  }
  function setValueV4a(gl, v) {
    gl.uniform4fv(this.addr, flatten(v, this.size, 4));
  }
  function setValueM2a(gl, v) {
    gl.uniformMatrix2fv(this.addr, false, flatten(v, this.size, 4));
  }
  function setValueM3a(gl, v) {
    gl.uniformMatrix3fv(this.addr, false, flatten(v, this.size, 9));
  }
  function setValueM4a(gl, v) {
    gl.uniformMatrix4fv(this.addr, false, flatten(v, this.size, 16));
  }
  function setValueT1a(gl, v, renderer) {
    var n = v.length,
        units = allocTexUnits(renderer, n);
    gl.uniform1iv(this.addr, units);
    for (var i = 0; i !== n; ++i) {
      renderer.setTexture2D(v[i] || emptyTexture, units[i]);
    }
  }
  function setValueT6a(gl, v, renderer) {
    var n = v.length,
        units = allocTexUnits(renderer, n);
    gl.uniform1iv(this.addr, units);
    for (var i = 0; i !== n; ++i) {
      renderer.setTextureCube(v[i] || emptyCubeTexture, units[i]);
    }
  }
  function getPureArraySetter(type) {
    switch (type) {
      case 0x1406:
        return setValue1fv;
      case 0x8b50:
        return setValueV2a;
      case 0x8b51:
        return setValueV3a;
      case 0x8b52:
        return setValueV4a;
      case 0x8b5a:
        return setValueM2a;
      case 0x8b5b:
        return setValueM3a;
      case 0x8b5c:
        return setValueM4a;
      case 0x8b5e:
        return setValueT1a;
      case 0x8b60:
        return setValueT6a;
      case 0x1404:
      case 0x8b56:
        return setValue1iv;
      case 0x8b53:
      case 0x8b57:
        return setValue2iv;
      case 0x8b54:
      case 0x8b58:
        return setValue3iv;
      case 0x8b55:
      case 0x8b59:
        return setValue4iv;
    }
  }
  function SingleUniform(id, activeInfo, addr) {
    this.id = id;
    this.addr = addr;
    this.setValue = getSingularSetter(activeInfo.type);
  }
  function PureArrayUniform(id, activeInfo, addr) {
    this.id = id;
    this.addr = addr;
    this.size = activeInfo.size;
    this.setValue = getPureArraySetter(activeInfo.type);
  }
  function StructuredUniform(id) {
    this.id = id;
    UniformContainer.call(this);
  }
  StructuredUniform.prototype.setValue = function(gl, value) {
    var seq = this.seq;
    for (var i = 0,
        n = seq.length; i !== n; ++i) {
      var u = seq[i];
      u.setValue(gl, value[u.id]);
    }
  };
  var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
  function addUniform(container, uniformObject) {
    container.seq.push(uniformObject);
    container.map[uniformObject.id] = uniformObject;
  }
  function parseUniform(activeInfo, addr, container) {
    var path = activeInfo.name,
        pathLength = path.length;
    RePathPart.lastIndex = 0;
    for (; ; ) {
      var match = RePathPart.exec(path),
          matchEnd = RePathPart.lastIndex,
          id = match[1],
          idIsIndex = match[2] === ']',
          subscript = match[3];
      if (idIsIndex)
        id = id | 0;
      if (subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength) {
        addUniform(container, subscript === undefined ? new SingleUniform(id, activeInfo, addr) : new PureArrayUniform(id, activeInfo, addr));
        break;
      } else {
        var map = container.map,
            next = map[id];
        if (next === undefined) {
          next = new StructuredUniform(id);
          addUniform(container, next);
        }
        container = next;
      }
    }
  }
  function WebGLUniforms(gl, program, renderer) {
    UniformContainer.call(this);
    this.renderer = renderer;
    var n = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
    for (var i = 0; i < n; ++i) {
      var info = gl.getActiveUniform(program, i),
          path = info.name,
          addr = gl.getUniformLocation(program, path);
      parseUniform(info, addr, this);
    }
  }
  WebGLUniforms.prototype.setValue = function(gl, name, value) {
    var u = this.map[name];
    if (u !== undefined)
      u.setValue(gl, value, this.renderer);
  };
  WebGLUniforms.prototype.setOptional = function(gl, object, name) {
    var v = object[name];
    if (v !== undefined)
      this.setValue(gl, name, v);
  };
  WebGLUniforms.upload = function(gl, seq, values, renderer) {
    for (var i = 0,
        n = seq.length; i !== n; ++i) {
      var u = seq[i],
          v = values[u.id];
      if (v.needsUpdate !== false) {
        u.setValue(gl, v.value, renderer);
      }
    }
  };
  WebGLUniforms.seqWithValue = function(seq, values) {
    var r = [];
    for (var i = 0,
        n = seq.length; i !== n; ++i) {
      var u = seq[i];
      if (u.id in values)
        r.push(u);
    }
    return r;
  };
  var ColorKeywords = {
    'aliceblue': 0xF0F8FF,
    'antiquewhite': 0xFAEBD7,
    'aqua': 0x00FFFF,
    'aquamarine': 0x7FFFD4,
    'azure': 0xF0FFFF,
    'beige': 0xF5F5DC,
    'bisque': 0xFFE4C4,
    'black': 0x000000,
    'blanchedalmond': 0xFFEBCD,
    'blue': 0x0000FF,
    'blueviolet': 0x8A2BE2,
    'brown': 0xA52A2A,
    'burlywood': 0xDEB887,
    'cadetblue': 0x5F9EA0,
    'chartreuse': 0x7FFF00,
    'chocolate': 0xD2691E,
    'coral': 0xFF7F50,
    'cornflowerblue': 0x6495ED,
    'cornsilk': 0xFFF8DC,
    'crimson': 0xDC143C,
    'cyan': 0x00FFFF,
    'darkblue': 0x00008B,
    'darkcyan': 0x008B8B,
    'darkgoldenrod': 0xB8860B,
    'darkgray': 0xA9A9A9,
    'darkgreen': 0x006400,
    'darkgrey': 0xA9A9A9,
    'darkkhaki': 0xBDB76B,
    'darkmagenta': 0x8B008B,
    'darkolivegreen': 0x556B2F,
    'darkorange': 0xFF8C00,
    'darkorchid': 0x9932CC,
    'darkred': 0x8B0000,
    'darksalmon': 0xE9967A,
    'darkseagreen': 0x8FBC8F,
    'darkslateblue': 0x483D8B,
    'darkslategray': 0x2F4F4F,
    'darkslategrey': 0x2F4F4F,
    'darkturquoise': 0x00CED1,
    'darkviolet': 0x9400D3,
    'deeppink': 0xFF1493,
    'deepskyblue': 0x00BFFF,
    'dimgray': 0x696969,
    'dimgrey': 0x696969,
    'dodgerblue': 0x1E90FF,
    'firebrick': 0xB22222,
    'floralwhite': 0xFFFAF0,
    'forestgreen': 0x228B22,
    'fuchsia': 0xFF00FF,
    'gainsboro': 0xDCDCDC,
    'ghostwhite': 0xF8F8FF,
    'gold': 0xFFD700,
    'goldenrod': 0xDAA520,
    'gray': 0x808080,
    'green': 0x008000,
    'greenyellow': 0xADFF2F,
    'grey': 0x808080,
    'honeydew': 0xF0FFF0,
    'hotpink': 0xFF69B4,
    'indianred': 0xCD5C5C,
    'indigo': 0x4B0082,
    'ivory': 0xFFFFF0,
    'khaki': 0xF0E68C,
    'lavender': 0xE6E6FA,
    'lavenderblush': 0xFFF0F5,
    'lawngreen': 0x7CFC00,
    'lemonchiffon': 0xFFFACD,
    'lightblue': 0xADD8E6,
    'lightcoral': 0xF08080,
    'lightcyan': 0xE0FFFF,
    'lightgoldenrodyellow': 0xFAFAD2,
    'lightgray': 0xD3D3D3,
    'lightgreen': 0x90EE90,
    'lightgrey': 0xD3D3D3,
    'lightpink': 0xFFB6C1,
    'lightsalmon': 0xFFA07A,
    'lightseagreen': 0x20B2AA,
    'lightskyblue': 0x87CEFA,
    'lightslategray': 0x778899,
    'lightslategrey': 0x778899,
    'lightsteelblue': 0xB0C4DE,
    'lightyellow': 0xFFFFE0,
    'lime': 0x00FF00,
    'limegreen': 0x32CD32,
    'linen': 0xFAF0E6,
    'magenta': 0xFF00FF,
    'maroon': 0x800000,
    'mediumaquamarine': 0x66CDAA,
    'mediumblue': 0x0000CD,
    'mediumorchid': 0xBA55D3,
    'mediumpurple': 0x9370DB,
    'mediumseagreen': 0x3CB371,
    'mediumslateblue': 0x7B68EE,
    'mediumspringgreen': 0x00FA9A,
    'mediumturquoise': 0x48D1CC,
    'mediumvioletred': 0xC71585,
    'midnightblue': 0x191970,
    'mintcream': 0xF5FFFA,
    'mistyrose': 0xFFE4E1,
    'moccasin': 0xFFE4B5,
    'navajowhite': 0xFFDEAD,
    'navy': 0x000080,
    'oldlace': 0xFDF5E6,
    'olive': 0x808000,
    'olivedrab': 0x6B8E23,
    'orange': 0xFFA500,
    'orangered': 0xFF4500,
    'orchid': 0xDA70D6,
    'palegoldenrod': 0xEEE8AA,
    'palegreen': 0x98FB98,
    'paleturquoise': 0xAFEEEE,
    'palevioletred': 0xDB7093,
    'papayawhip': 0xFFEFD5,
    'peachpuff': 0xFFDAB9,
    'peru': 0xCD853F,
    'pink': 0xFFC0CB,
    'plum': 0xDDA0DD,
    'powderblue': 0xB0E0E6,
    'purple': 0x800080,
    'rebeccapurple': 0x663399,
    'red': 0xFF0000,
    'rosybrown': 0xBC8F8F,
    'royalblue': 0x4169E1,
    'saddlebrown': 0x8B4513,
    'salmon': 0xFA8072,
    'sandybrown': 0xF4A460,
    'seagreen': 0x2E8B57,
    'seashell': 0xFFF5EE,
    'sienna': 0xA0522D,
    'silver': 0xC0C0C0,
    'skyblue': 0x87CEEB,
    'slateblue': 0x6A5ACD,
    'slategray': 0x708090,
    'slategrey': 0x708090,
    'snow': 0xFFFAFA,
    'springgreen': 0x00FF7F,
    'steelblue': 0x4682B4,
    'tan': 0xD2B48C,
    'teal': 0x008080,
    'thistle': 0xD8BFD8,
    'tomato': 0xFF6347,
    'turquoise': 0x40E0D0,
    'violet': 0xEE82EE,
    'wheat': 0xF5DEB3,
    'white': 0xFFFFFF,
    'whitesmoke': 0xF5F5F5,
    'yellow': 0xFFFF00,
    'yellowgreen': 0x9ACD32
  };
  function Color(r, g, b) {
    if (g === undefined && b === undefined) {
      return this.set(r);
    }
    return this.setRGB(r, g, b);
  }
  Object.assign(Color.prototype, {
    isColor: true,
    r: 1,
    g: 1,
    b: 1,
    set: function(value) {
      if (value && value.isColor) {
        this.copy(value);
      } else if (typeof value === 'number') {
        this.setHex(value);
      } else if (typeof value === 'string') {
        this.setStyle(value);
      }
      return this;
    },
    setScalar: function(scalar) {
      this.r = scalar;
      this.g = scalar;
      this.b = scalar;
      return this;
    },
    setHex: function(hex) {
      hex = Math.floor(hex);
      this.r = (hex >> 16 & 255) / 255;
      this.g = (hex >> 8 & 255) / 255;
      this.b = (hex & 255) / 255;
      return this;
    },
    setRGB: function(r, g, b) {
      this.r = r;
      this.g = g;
      this.b = b;
      return this;
    },
    setHSL: function() {
      function hue2rgb(p, q, t) {
        if (t < 0)
          t += 1;
        if (t > 1)
          t -= 1;
        if (t < 1 / 6)
          return p + (q - p) * 6 * t;
        if (t < 1 / 2)
          return q;
        if (t < 2 / 3)
          return p + (q - p) * 6 * (2 / 3 - t);
        return p;
      }
      return function setHSL(h, s, l) {
        h = _Math.euclideanModulo(h, 1);
        s = _Math.clamp(s, 0, 1);
        l = _Math.clamp(l, 0, 1);
        if (s === 0) {
          this.r = this.g = this.b = l;
        } else {
          var p = l <= 0.5 ? l * (1 + s) : l + s - (l * s);
          var q = (2 * l) - p;
          this.r = hue2rgb(q, p, h + 1 / 3);
          this.g = hue2rgb(q, p, h);
          this.b = hue2rgb(q, p, h - 1 / 3);
        }
        return this;
      };
    }(),
    setStyle: function(style) {
      function handleAlpha(string) {
        if (string === undefined)
          return;
        if (parseFloat(string) < 1) {
          console.warn('THREE.Color: Alpha component of ' + style + ' will be ignored.');
        }
      }
      var m;
      if (m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(style)) {
        var color;
        var name = m[1];
        var components = m[2];
        switch (name) {
          case 'rgb':
          case 'rgba':
            if (color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
              this.r = Math.min(255, parseInt(color[1], 10)) / 255;
              this.g = Math.min(255, parseInt(color[2], 10)) / 255;
              this.b = Math.min(255, parseInt(color[3], 10)) / 255;
              handleAlpha(color[5]);
              return this;
            }
            if (color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
              this.r = Math.min(100, parseInt(color[1], 10)) / 100;
              this.g = Math.min(100, parseInt(color[2], 10)) / 100;
              this.b = Math.min(100, parseInt(color[3], 10)) / 100;
              handleAlpha(color[5]);
              return this;
            }
            break;
          case 'hsl':
          case 'hsla':
            if (color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
              var h = parseFloat(color[1]) / 360;
              var s = parseInt(color[2], 10) / 100;
              var l = parseInt(color[3], 10) / 100;
              handleAlpha(color[5]);
              return this.setHSL(h, s, l);
            }
            break;
        }
      } else if (m = /^\#([A-Fa-f0-9]+)$/.exec(style)) {
        var hex = m[1];
        var size = hex.length;
        if (size === 3) {
          this.r = parseInt(hex.charAt(0) + hex.charAt(0), 16) / 255;
          this.g = parseInt(hex.charAt(1) + hex.charAt(1), 16) / 255;
          this.b = parseInt(hex.charAt(2) + hex.charAt(2), 16) / 255;
          return this;
        } else if (size === 6) {
          this.r = parseInt(hex.charAt(0) + hex.charAt(1), 16) / 255;
          this.g = parseInt(hex.charAt(2) + hex.charAt(3), 16) / 255;
          this.b = parseInt(hex.charAt(4) + hex.charAt(5), 16) / 255;
          return this;
        }
      }
      if (style && style.length > 0) {
        var hex = ColorKeywords[style];
        if (hex !== undefined) {
          this.setHex(hex);
        } else {
          console.warn('THREE.Color: Unknown color ' + style);
        }
      }
      return this;
    },
    clone: function() {
      return new this.constructor(this.r, this.g, this.b);
    },
    copy: function(color) {
      this.r = color.r;
      this.g = color.g;
      this.b = color.b;
      return this;
    },
    copyGammaToLinear: function(color, gammaFactor) {
      if (gammaFactor === undefined)
        gammaFactor = 2.0;
      this.r = Math.pow(color.r, gammaFactor);
      this.g = Math.pow(color.g, gammaFactor);
      this.b = Math.pow(color.b, gammaFactor);
      return this;
    },
    copyLinearToGamma: function(color, gammaFactor) {
      if (gammaFactor === undefined)
        gammaFactor = 2.0;
      var safeInverse = (gammaFactor > 0) ? (1.0 / gammaFactor) : 1.0;
      this.r = Math.pow(color.r, safeInverse);
      this.g = Math.pow(color.g, safeInverse);
      this.b = Math.pow(color.b, safeInverse);
      return this;
    },
    convertGammaToLinear: function() {
      var r = this.r,
          g = this.g,
          b = this.b;
      this.r = r * r;
      this.g = g * g;
      this.b = b * b;
      return this;
    },
    convertLinearToGamma: function() {
      this.r = Math.sqrt(this.r);
      this.g = Math.sqrt(this.g);
      this.b = Math.sqrt(this.b);
      return this;
    },
    getHex: function() {
      return (this.r * 255) << 16 ^ (this.g * 255) << 8 ^ (this.b * 255) << 0;
    },
    getHexString: function() {
      return ('000000' + this.getHex().toString(16)).slice(-6);
    },
    getHSL: function(optionalTarget) {
      var hsl = optionalTarget || {
        h: 0,
        s: 0,
        l: 0
      };
      var r = this.r,
          g = this.g,
          b = this.b;
      var max = Math.max(r, g, b);
      var min = Math.min(r, g, b);
      var hue,
          saturation;
      var lightness = (min + max) / 2.0;
      if (min === max) {
        hue = 0;
        saturation = 0;
      } else {
        var delta = max - min;
        saturation = lightness <= 0.5 ? delta / (max + min) : delta / (2 - max - min);
        switch (max) {
          case r:
            hue = (g - b) / delta + (g < b ? 6 : 0);
            break;
          case g:
            hue = (b - r) / delta + 2;
            break;
          case b:
            hue = (r - g) / delta + 4;
            break;
        }
        hue /= 6;
      }
      hsl.h = hue;
      hsl.s = saturation;
      hsl.l = lightness;
      return hsl;
    },
    getStyle: function() {
      return 'rgb(' + ((this.r * 255) | 0) + ',' + ((this.g * 255) | 0) + ',' + ((this.b * 255) | 0) + ')';
    },
    offsetHSL: function(h, s, l) {
      var hsl = this.getHSL();
      hsl.h += h;
      hsl.s += s;
      hsl.l += l;
      this.setHSL(hsl.h, hsl.s, hsl.l);
      return this;
    },
    add: function(color) {
      this.r += color.r;
      this.g += color.g;
      this.b += color.b;
      return this;
    },
    addColors: function(color1, color2) {
      this.r = color1.r + color2.r;
      this.g = color1.g + color2.g;
      this.b = color1.b + color2.b;
      return this;
    },
    addScalar: function(s) {
      this.r += s;
      this.g += s;
      this.b += s;
      return this;
    },
    sub: function(color) {
      this.r = Math.max(0, this.r - color.r);
      this.g = Math.max(0, this.g - color.g);
      this.b = Math.max(0, this.b - color.b);
      return this;
    },
    multiply: function(color) {
      this.r *= color.r;
      this.g *= color.g;
      this.b *= color.b;
      return this;
    },
    multiplyScalar: function(s) {
      this.r *= s;
      this.g *= s;
      this.b *= s;
      return this;
    },
    lerp: function(color, alpha) {
      this.r += (color.r - this.r) * alpha;
      this.g += (color.g - this.g) * alpha;
      this.b += (color.b - this.b) * alpha;
      return this;
    },
    equals: function(c) {
      return (c.r === this.r) && (c.g === this.g) && (c.b === this.b);
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this.r = array[offset];
      this.g = array[offset + 1];
      this.b = array[offset + 2];
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this.r;
      array[offset + 1] = this.g;
      array[offset + 2] = this.b;
      return array;
    },
    toJSON: function() {
      return this.getHex();
    }
  });
  var UniformsLib = {
    common: {
      diffuse: {value: new Color(0xeeeeee)},
      opacity: {value: 1.0},
      map: {value: null},
      uvTransform: {value: new Matrix3()},
      alphaMap: {value: null}
    },
    specularmap: {specularMap: {value: null}},
    envmap: {
      envMap: {value: null},
      flipEnvMap: {value: -1},
      reflectivity: {value: 1.0},
      refractionRatio: {value: 0.98}
    },
    aomap: {
      aoMap: {value: null},
      aoMapIntensity: {value: 1}
    },
    lightmap: {
      lightMap: {value: null},
      lightMapIntensity: {value: 1}
    },
    emissivemap: {emissiveMap: {value: null}},
    bumpmap: {
      bumpMap: {value: null},
      bumpScale: {value: 1}
    },
    normalmap: {
      normalMap: {value: null},
      normalScale: {value: new Vector2(1, 1)}
    },
    displacementmap: {
      displacementMap: {value: null},
      displacementScale: {value: 1},
      displacementBias: {value: 0}
    },
    roughnessmap: {roughnessMap: {value: null}},
    metalnessmap: {metalnessMap: {value: null}},
    gradientmap: {gradientMap: {value: null}},
    fog: {
      fogDensity: {value: 0.00025},
      fogNear: {value: 1},
      fogFar: {value: 2000},
      fogColor: {value: new Color(0xffffff)}
    },
    lights: {
      ambientLightColor: {value: []},
      directionalLights: {
        value: [],
        properties: {
          direction: {},
          color: {},
          shadow: {},
          shadowBias: {},
          shadowRadius: {},
          shadowMapSize: {}
        }
      },
      directionalShadowMap: {value: []},
      directionalShadowMatrix: {value: []},
      spotLights: {
        value: [],
        properties: {
          color: {},
          position: {},
          direction: {},
          distance: {},
          coneCos: {},
          penumbraCos: {},
          decay: {},
          shadow: {},
          shadowBias: {},
          shadowRadius: {},
          shadowMapSize: {}
        }
      },
      spotShadowMap: {value: []},
      spotShadowMatrix: {value: []},
      pointLights: {
        value: [],
        properties: {
          color: {},
          position: {},
          decay: {},
          distance: {},
          shadow: {},
          shadowBias: {},
          shadowRadius: {},
          shadowMapSize: {},
          shadowCameraNear: {},
          shadowCameraFar: {}
        }
      },
      pointShadowMap: {value: []},
      pointShadowMatrix: {value: []},
      hemisphereLights: {
        value: [],
        properties: {
          direction: {},
          skyColor: {},
          groundColor: {}
        }
      },
      rectAreaLights: {
        value: [],
        properties: {
          color: {},
          position: {},
          width: {},
          height: {}
        }
      }
    },
    points: {
      diffuse: {value: new Color(0xeeeeee)},
      opacity: {value: 1.0},
      size: {value: 1.0},
      scale: {value: 1.0},
      map: {value: null},
      uvTransform: {value: new Matrix3()}
    }
  };
  var UniformsUtils = {
    merge: function(uniforms) {
      var merged = {};
      for (var u = 0; u < uniforms.length; u++) {
        var tmp = this.clone(uniforms[u]);
        for (var p in tmp) {
          merged[p] = tmp[p];
        }
      }
      return merged;
    },
    clone: function(uniforms_src) {
      var uniforms_dst = {};
      for (var u in uniforms_src) {
        uniforms_dst[u] = {};
        for (var p in uniforms_src[u]) {
          var parameter_src = uniforms_src[u][p];
          if (parameter_src && (parameter_src.isColor || parameter_src.isMatrix3 || parameter_src.isMatrix4 || parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 || parameter_src.isTexture)) {
            uniforms_dst[u][p] = parameter_src.clone();
          } else if (Array.isArray(parameter_src)) {
            uniforms_dst[u][p] = parameter_src.slice();
          } else {
            uniforms_dst[u][p] = parameter_src;
          }
        }
      }
      return uniforms_dst;
    }
  };
  var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
  var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n";
  var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
  var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n";
  var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
  var begin_vertex = "\nvec3 transformed = vec3( position );\n";
  var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n";
  var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";
  var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n";
  var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n";
  var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n";
  var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n";
  var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n";
  var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
  var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n";
  var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
  var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif";
  var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";
  var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1  (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale =  bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n";
  var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n";
  var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n";
  var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
  var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
  var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n";
  var encodings_fragment = "  gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
  var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M      = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM            = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D      = max( maxRange / maxRGB, 1.0 );\n\tD            = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value )  {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n";
  var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n";
  var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n";
  var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n";
  var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n";
  var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif";
  var fog_pars_vertex = "#ifdef USE_FOG\n  varying float fogDepth;\n#endif\n";
  var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n";
  var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n";
  var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n";
  var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
  var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
  var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n";
  var lights_pars = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltcMat;\tuniform sampler2D ltcMag;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n";
  var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
  var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n";
  var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n";
  var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3(   1,   0, t.y ),\n\t\t\tvec3(   0, t.z,   0 ),\n\t\t\tvec3( t.w,   0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";
  var lights_template = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n";
  var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
  var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n";
  var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif";
  var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n";
  var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n";
  var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n";
  var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n";
  var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n";
  var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n";
  var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
  var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n";
  var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
  var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n";
  var normal_fragment = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n";
  var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n";
  var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256.,  256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";
  var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
  var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n";
  var dithering_fragment = "#if defined( DITHERING )\n  gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n";
  var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n";
  var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n";
  var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
  var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n";
  var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n";
  var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n";
  var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n";
  var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
  var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n";
  var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n";
  var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n";
  var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif";
  var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
  var tonemapping_fragment = "#if defined( TONE_MAPPING )\n  gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
  var tonemapping_pars_fragment = "#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n";
  var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif";
  var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n";
  var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
  var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
  var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif";
  var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif";
  var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n";
  var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n";
  var cube_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}\n";
  var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n";
  var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n}\n";
  var distanceRGBA_frag = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n";
  var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}\n";
  var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n";
  var equirect_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}\n";
  var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
  var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}\n";
  var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
  var meshbasic_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_ENVMAP\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}\n";
  var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
  var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
  var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_template>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
  var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
  var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <lights_pars>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_template>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
  var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
  var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n";
  var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n";
  var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
  var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
  var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <fog_fragment>\n}\n";
  var shadow_vert = "#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
  var ShaderChunk = {
    alphamap_fragment: alphamap_fragment,
    alphamap_pars_fragment: alphamap_pars_fragment,
    alphatest_fragment: alphatest_fragment,
    aomap_fragment: aomap_fragment,
    aomap_pars_fragment: aomap_pars_fragment,
    begin_vertex: begin_vertex,
    beginnormal_vertex: beginnormal_vertex,
    bsdfs: bsdfs,
    bumpmap_pars_fragment: bumpmap_pars_fragment,
    clipping_planes_fragment: clipping_planes_fragment,
    clipping_planes_pars_fragment: clipping_planes_pars_fragment,
    clipping_planes_pars_vertex: clipping_planes_pars_vertex,
    clipping_planes_vertex: clipping_planes_vertex,
    color_fragment: color_fragment,
    color_pars_fragment: color_pars_fragment,
    color_pars_vertex: color_pars_vertex,
    color_vertex: color_vertex,
    common: common,
    cube_uv_reflection_fragment: cube_uv_reflection_fragment,
    defaultnormal_vertex: defaultnormal_vertex,
    displacementmap_pars_vertex: displacementmap_pars_vertex,
    displacementmap_vertex: displacementmap_vertex,
    emissivemap_fragment: emissivemap_fragment,
    emissivemap_pars_fragment: emissivemap_pars_fragment,
    encodings_fragment: encodings_fragment,
    encodings_pars_fragment: encodings_pars_fragment,
    envmap_fragment: envmap_fragment,
    envmap_pars_fragment: envmap_pars_fragment,
    envmap_pars_vertex: envmap_pars_vertex,
    envmap_vertex: envmap_vertex,
    fog_vertex: fog_vertex,
    fog_pars_vertex: fog_pars_vertex,
    fog_fragment: fog_fragment,
    fog_pars_fragment: fog_pars_fragment,
    gradientmap_pars_fragment: gradientmap_pars_fragment,
    lightmap_fragment: lightmap_fragment,
    lightmap_pars_fragment: lightmap_pars_fragment,
    lights_lambert_vertex: lights_lambert_vertex,
    lights_pars: lights_pars,
    lights_phong_fragment: lights_phong_fragment,
    lights_phong_pars_fragment: lights_phong_pars_fragment,
    lights_physical_fragment: lights_physical_fragment,
    lights_physical_pars_fragment: lights_physical_pars_fragment,
    lights_template: lights_template,
    logdepthbuf_fragment: logdepthbuf_fragment,
    logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
    logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
    logdepthbuf_vertex: logdepthbuf_vertex,
    map_fragment: map_fragment,
    map_pars_fragment: map_pars_fragment,
    map_particle_fragment: map_particle_fragment,
    map_particle_pars_fragment: map_particle_pars_fragment,
    metalnessmap_fragment: metalnessmap_fragment,
    metalnessmap_pars_fragment: metalnessmap_pars_fragment,
    morphnormal_vertex: morphnormal_vertex,
    morphtarget_pars_vertex: morphtarget_pars_vertex,
    morphtarget_vertex: morphtarget_vertex,
    normal_fragment: normal_fragment,
    normalmap_pars_fragment: normalmap_pars_fragment,
    packing: packing,
    premultiplied_alpha_fragment: premultiplied_alpha_fragment,
    project_vertex: project_vertex,
    dithering_fragment: dithering_fragment,
    dithering_pars_fragment: dithering_pars_fragment,
    roughnessmap_fragment: roughnessmap_fragment,
    roughnessmap_pars_fragment: roughnessmap_pars_fragment,
    shadowmap_pars_fragment: shadowmap_pars_fragment,
    shadowmap_pars_vertex: shadowmap_pars_vertex,
    shadowmap_vertex: shadowmap_vertex,
    shadowmask_pars_fragment: shadowmask_pars_fragment,
    skinbase_vertex: skinbase_vertex,
    skinning_pars_vertex: skinning_pars_vertex,
    skinning_vertex: skinning_vertex,
    skinnormal_vertex: skinnormal_vertex,
    specularmap_fragment: specularmap_fragment,
    specularmap_pars_fragment: specularmap_pars_fragment,
    tonemapping_fragment: tonemapping_fragment,
    tonemapping_pars_fragment: tonemapping_pars_fragment,
    uv_pars_fragment: uv_pars_fragment,
    uv_pars_vertex: uv_pars_vertex,
    uv_vertex: uv_vertex,
    uv2_pars_fragment: uv2_pars_fragment,
    uv2_pars_vertex: uv2_pars_vertex,
    uv2_vertex: uv2_vertex,
    worldpos_vertex: worldpos_vertex,
    cube_frag: cube_frag,
    cube_vert: cube_vert,
    depth_frag: depth_frag,
    depth_vert: depth_vert,
    distanceRGBA_frag: distanceRGBA_frag,
    distanceRGBA_vert: distanceRGBA_vert,
    equirect_frag: equirect_frag,
    equirect_vert: equirect_vert,
    linedashed_frag: linedashed_frag,
    linedashed_vert: linedashed_vert,
    meshbasic_frag: meshbasic_frag,
    meshbasic_vert: meshbasic_vert,
    meshlambert_frag: meshlambert_frag,
    meshlambert_vert: meshlambert_vert,
    meshphong_frag: meshphong_frag,
    meshphong_vert: meshphong_vert,
    meshphysical_frag: meshphysical_frag,
    meshphysical_vert: meshphysical_vert,
    normal_frag: normal_frag,
    normal_vert: normal_vert,
    points_frag: points_frag,
    points_vert: points_vert,
    shadow_frag: shadow_frag,
    shadow_vert: shadow_vert
  };
  var ShaderLib = {
    basic: {
      uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.specularmap, UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.fog]),
      vertexShader: ShaderChunk.meshbasic_vert,
      fragmentShader: ShaderChunk.meshbasic_frag
    },
    lambert: {
      uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.specularmap, UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, UniformsLib.fog, UniformsLib.lights, {emissive: {value: new Color(0x000000)}}]),
      vertexShader: ShaderChunk.meshlambert_vert,
      fragmentShader: ShaderChunk.meshlambert_frag
    },
    phong: {
      uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.specularmap, UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, UniformsLib.bumpmap, UniformsLib.normalmap, UniformsLib.displacementmap, UniformsLib.gradientmap, UniformsLib.fog, UniformsLib.lights, {
        emissive: {value: new Color(0x000000)},
        specular: {value: new Color(0x111111)},
        shininess: {value: 30}
      }]),
      vertexShader: ShaderChunk.meshphong_vert,
      fragmentShader: ShaderChunk.meshphong_frag
    },
    standard: {
      uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.emissivemap, UniformsLib.bumpmap, UniformsLib.normalmap, UniformsLib.displacementmap, UniformsLib.roughnessmap, UniformsLib.metalnessmap, UniformsLib.fog, UniformsLib.lights, {
        emissive: {value: new Color(0x000000)},
        roughness: {value: 0.5},
        metalness: {value: 0.5},
        envMapIntensity: {value: 1}
      }]),
      vertexShader: ShaderChunk.meshphysical_vert,
      fragmentShader: ShaderChunk.meshphysical_frag
    },
    points: {
      uniforms: UniformsUtils.merge([UniformsLib.points, UniformsLib.fog]),
      vertexShader: ShaderChunk.points_vert,
      fragmentShader: ShaderChunk.points_frag
    },
    dashed: {
      uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.fog, {
        scale: {value: 1},
        dashSize: {value: 1},
        totalSize: {value: 2}
      }]),
      vertexShader: ShaderChunk.linedashed_vert,
      fragmentShader: ShaderChunk.linedashed_frag
    },
    depth: {
      uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.displacementmap]),
      vertexShader: ShaderChunk.depth_vert,
      fragmentShader: ShaderChunk.depth_frag
    },
    normal: {
      uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.bumpmap, UniformsLib.normalmap, UniformsLib.displacementmap, {opacity: {value: 1.0}}]),
      vertexShader: ShaderChunk.normal_vert,
      fragmentShader: ShaderChunk.normal_frag
    },
    cube: {
      uniforms: {
        tCube: {value: null},
        tFlip: {value: -1},
        opacity: {value: 1.0}
      },
      vertexShader: ShaderChunk.cube_vert,
      fragmentShader: ShaderChunk.cube_frag
    },
    equirect: {
      uniforms: {tEquirect: {value: null}},
      vertexShader: ShaderChunk.equirect_vert,
      fragmentShader: ShaderChunk.equirect_frag
    },
    distanceRGBA: {
      uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.displacementmap, {
        referencePosition: {value: new Vector3()},
        nearDistance: {value: 1},
        farDistance: {value: 1000}
      }]),
      vertexShader: ShaderChunk.distanceRGBA_vert,
      fragmentShader: ShaderChunk.distanceRGBA_frag
    },
    shadow: {
      uniforms: UniformsUtils.merge([UniformsLib.lights, UniformsLib.fog, {
        color: {value: new Color(0x00000)},
        opacity: {value: 1.0}
      }]),
      vertexShader: ShaderChunk.shadow_vert,
      fragmentShader: ShaderChunk.shadow_frag
    }
  };
  ShaderLib.physical = {
    uniforms: UniformsUtils.merge([ShaderLib.standard.uniforms, {
      clearCoat: {value: 0},
      clearCoatRoughness: {value: 0}
    }]),
    vertexShader: ShaderChunk.meshphysical_vert,
    fragmentShader: ShaderChunk.meshphysical_frag
  };
  function Box2(min, max) {
    this.min = (min !== undefined) ? min : new Vector2(+Infinity, +Infinity);
    this.max = (max !== undefined) ? max : new Vector2(-Infinity, -Infinity);
  }
  Object.assign(Box2.prototype, {
    set: function(min, max) {
      this.min.copy(min);
      this.max.copy(max);
      return this;
    },
    setFromPoints: function(points) {
      this.makeEmpty();
      for (var i = 0,
          il = points.length; i < il; i++) {
        this.expandByPoint(points[i]);
      }
      return this;
    },
    setFromCenterAndSize: function() {
      var v1 = new Vector2();
      return function setFromCenterAndSize(center, size) {
        var halfSize = v1.copy(size).multiplyScalar(0.5);
        this.min.copy(center).sub(halfSize);
        this.max.copy(center).add(halfSize);
        return this;
      };
    }(),
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(box) {
      this.min.copy(box.min);
      this.max.copy(box.max);
      return this;
    },
    makeEmpty: function() {
      this.min.x = this.min.y = +Infinity;
      this.max.x = this.max.y = -Infinity;
      return this;
    },
    isEmpty: function() {
      return (this.max.x < this.min.x) || (this.max.y < this.min.y);
    },
    getCenter: function(optionalTarget) {
      var result = optionalTarget || new Vector2();
      return this.isEmpty() ? result.set(0, 0) : result.addVectors(this.min, this.max).multiplyScalar(0.5);
    },
    getSize: function(optionalTarget) {
      var result = optionalTarget || new Vector2();
      return this.isEmpty() ? result.set(0, 0) : result.subVectors(this.max, this.min);
    },
    expandByPoint: function(point) {
      this.min.min(point);
      this.max.max(point);
      return this;
    },
    expandByVector: function(vector) {
      this.min.sub(vector);
      this.max.add(vector);
      return this;
    },
    expandByScalar: function(scalar) {
      this.min.addScalar(-scalar);
      this.max.addScalar(scalar);
      return this;
    },
    containsPoint: function(point) {
      return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y ? false : true;
    },
    containsBox: function(box) {
      return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y;
    },
    getParameter: function(point, optionalTarget) {
      var result = optionalTarget || new Vector2();
      return result.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y));
    },
    intersectsBox: function(box) {
      return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
    },
    clampPoint: function(point, optionalTarget) {
      var result = optionalTarget || new Vector2();
      return result.copy(point).clamp(this.min, this.max);
    },
    distanceToPoint: function() {
      var v1 = new Vector2();
      return function distanceToPoint(point) {
        var clampedPoint = v1.copy(point).clamp(this.min, this.max);
        return clampedPoint.sub(point).length();
      };
    }(),
    intersect: function(box) {
      this.min.max(box.min);
      this.max.min(box.max);
      return this;
    },
    union: function(box) {
      this.min.min(box.min);
      this.max.max(box.max);
      return this;
    },
    translate: function(offset) {
      this.min.add(offset);
      this.max.add(offset);
      return this;
    },
    equals: function(box) {
      return box.min.equals(this.min) && box.max.equals(this.max);
    }
  });
  function WebGLFlareRenderer(renderer, gl, state, textures, capabilities) {
    var vertexBuffer,
        elementBuffer;
    var shader,
        program,
        attributes,
        uniforms;
    var tempTexture,
        occlusionTexture;
    function init() {
      var vertices = new Float32Array([-1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1]);
      var faces = new Uint16Array([0, 1, 2, 0, 2, 3]);
      vertexBuffer = gl.createBuffer();
      elementBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW);
      tempTexture = gl.createTexture();
      occlusionTexture = gl.createTexture();
      state.bindTexture(gl.TEXTURE_2D, tempTexture);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      state.bindTexture(gl.TEXTURE_2D, occlusionTexture);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      shader = {
        vertexShader: ['uniform lowp int renderType;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'uniform float rotation;', 'uniform sampler2D occlusionMap;', 'attribute vec2 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'varying float vVisibility;', 'void main() {', '	vUV = uv;', '	vec2 pos = position;', '	if ( renderType == 2 ) {', '		vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', '		visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', '		visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', '		visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', '		visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', '		visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', '		visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', '		visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', '		visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', '		vVisibility =        visibility.r / 9.0;', '		vVisibility *= 1.0 - visibility.g / 9.0;', '		vVisibility *=       visibility.b / 9.0;', '		vVisibility *= 1.0 - visibility.a / 9.0;', '		pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;', '		pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;', '	}', '	gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', '}'].join('\n'),
        fragmentShader: ['uniform lowp int renderType;', 'uniform sampler2D map;', 'uniform float opacity;', 'uniform vec3 color;', 'varying vec2 vUV;', 'varying float vVisibility;', 'void main() {', '	if ( renderType == 0 ) {', '		gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );', '	} else if ( renderType == 1 ) {', '		gl_FragColor = texture2D( map, vUV );', '	} else {', '		vec4 texture = texture2D( map, vUV );', '		texture.a *= opacity * vVisibility;', '		gl_FragColor = texture;', '		gl_FragColor.rgb *= color;', '	}', '}'].join('\n')
      };
      program = createProgram(shader);
      attributes = {
        vertex: gl.getAttribLocation(program, 'position'),
        uv: gl.getAttribLocation(program, 'uv')
      };
      uniforms = {
        renderType: gl.getUniformLocation(program, 'renderType'),
        map: gl.getUniformLocation(program, 'map'),
        occlusionMap: gl.getUniformLocation(program, 'occlusionMap'),
        opacity: gl.getUniformLocation(program, 'opacity'),
        color: gl.getUniformLocation(program, 'color'),
        scale: gl.getUniformLocation(program, 'scale'),
        rotation: gl.getUniformLocation(program, 'rotation'),
        screenPosition: gl.getUniformLocation(program, 'screenPosition')
      };
    }
    this.render = function(flares, scene, camera, viewport) {
      if (flares.length === 0)
        return;
      var tempPosition = new Vector3();
      var invAspect = viewport.w / viewport.z,
          halfViewportWidth = viewport.z * 0.5,
          halfViewportHeight = viewport.w * 0.5;
      var size = 16 / viewport.w,
          scale = new Vector2(size * invAspect, size);
      var screenPosition = new Vector3(1, 1, 0),
          screenPositionPixels = new Vector2(1, 1);
      var validArea = new Box2();
      validArea.min.set(viewport.x, viewport.y);
      validArea.max.set(viewport.x + (viewport.z - 16), viewport.y + (viewport.w - 16));
      if (program === undefined) {
        init();
      }
      state.useProgram(program);
      state.initAttributes();
      state.enableAttribute(attributes.vertex);
      state.enableAttribute(attributes.uv);
      state.disableUnusedAttributes();
      gl.uniform1i(uniforms.occlusionMap, 0);
      gl.uniform1i(uniforms.map, 1);
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.vertexAttribPointer(attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0);
      gl.vertexAttribPointer(attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
      state.disable(gl.CULL_FACE);
      state.buffers.depth.setMask(false);
      for (var i = 0,
          l = flares.length; i < l; i++) {
        size = 16 / viewport.w;
        scale.set(size * invAspect, size);
        var flare = flares[i];
        tempPosition.set(flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14]);
        tempPosition.applyMatrix4(camera.matrixWorldInverse);
        tempPosition.applyMatrix4(camera.projectionMatrix);
        screenPosition.copy(tempPosition);
        screenPositionPixels.x = viewport.x + (screenPosition.x * halfViewportWidth) + halfViewportWidth - 8;
        screenPositionPixels.y = viewport.y + (screenPosition.y * halfViewportHeight) + halfViewportHeight - 8;
        if (validArea.containsPoint(screenPositionPixels) === true) {
          state.activeTexture(gl.TEXTURE0);
          state.bindTexture(gl.TEXTURE_2D, null);
          state.activeTexture(gl.TEXTURE1);
          state.bindTexture(gl.TEXTURE_2D, tempTexture);
          gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0);
          gl.uniform1i(uniforms.renderType, 0);
          gl.uniform2f(uniforms.scale, scale.x, scale.y);
          gl.uniform3f(uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z);
          state.disable(gl.BLEND);
          state.enable(gl.DEPTH_TEST);
          gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
          state.activeTexture(gl.TEXTURE0);
          state.bindTexture(gl.TEXTURE_2D, occlusionTexture);
          gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0);
          gl.uniform1i(uniforms.renderType, 1);
          state.disable(gl.DEPTH_TEST);
          state.activeTexture(gl.TEXTURE1);
          state.bindTexture(gl.TEXTURE_2D, tempTexture);
          gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
          flare.positionScreen.copy(screenPosition);
          if (flare.customUpdateCallback) {
            flare.customUpdateCallback(flare);
          } else {
            flare.updateLensFlares();
          }
          gl.uniform1i(uniforms.renderType, 2);
          state.enable(gl.BLEND);
          for (var j = 0,
              jl = flare.lensFlares.length; j < jl; j++) {
            var sprite = flare.lensFlares[j];
            if (sprite.opacity > 0.001 && sprite.scale > 0.001) {
              screenPosition.x = sprite.x;
              screenPosition.y = sprite.y;
              screenPosition.z = sprite.z;
              size = sprite.size * sprite.scale / viewport.w;
              scale.x = size * invAspect;
              scale.y = size;
              gl.uniform3f(uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z);
              gl.uniform2f(uniforms.scale, scale.x, scale.y);
              gl.uniform1f(uniforms.rotation, sprite.rotation);
              gl.uniform1f(uniforms.opacity, sprite.opacity);
              gl.uniform3f(uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b);
              state.setBlending(sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst);
              textures.setTexture2D(sprite.texture, 1);
              gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
            }
          }
        }
      }
      state.enable(gl.CULL_FACE);
      state.enable(gl.DEPTH_TEST);
      state.buffers.depth.setMask(true);
      state.reset();
    };
    function createProgram(shader) {
      var program = gl.createProgram();
      var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
      var vertexShader = gl.createShader(gl.VERTEX_SHADER);
      var prefix = 'precision ' + capabilities.precision + ' float;\n';
      gl.shaderSource(fragmentShader, prefix + shader.fragmentShader);
      gl.shaderSource(vertexShader, prefix + shader.vertexShader);
      gl.compileShader(fragmentShader);
      gl.compileShader(vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.attachShader(program, vertexShader);
      gl.linkProgram(program);
      return program;
    }
  }
  function CanvasTexture(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
    Texture.call(this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
    this.needsUpdate = true;
  }
  CanvasTexture.prototype = Object.create(Texture.prototype);
  CanvasTexture.prototype.constructor = CanvasTexture;
  function WebGLSpriteRenderer(renderer, gl, state, textures, capabilities) {
    var vertexBuffer,
        elementBuffer;
    var program,
        attributes,
        uniforms;
    var texture;
    var spritePosition = new Vector3();
    var spriteRotation = new Quaternion();
    var spriteScale = new Vector3();
    function init() {
      var vertices = new Float32Array([-0.5, -0.5, 0, 0, 0.5, -0.5, 1, 0, 0.5, 0.5, 1, 1, -0.5, 0.5, 0, 1]);
      var faces = new Uint16Array([0, 1, 2, 0, 2, 3]);
      vertexBuffer = gl.createBuffer();
      elementBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW);
      program = createProgram();
      attributes = {
        position: gl.getAttribLocation(program, 'position'),
        uv: gl.getAttribLocation(program, 'uv')
      };
      uniforms = {
        uvOffset: gl.getUniformLocation(program, 'uvOffset'),
        uvScale: gl.getUniformLocation(program, 'uvScale'),
        rotation: gl.getUniformLocation(program, 'rotation'),
        scale: gl.getUniformLocation(program, 'scale'),
        color: gl.getUniformLocation(program, 'color'),
        map: gl.getUniformLocation(program, 'map'),
        opacity: gl.getUniformLocation(program, 'opacity'),
        modelViewMatrix: gl.getUniformLocation(program, 'modelViewMatrix'),
        projectionMatrix: gl.getUniformLocation(program, 'projectionMatrix'),
        fogType: gl.getUniformLocation(program, 'fogType'),
        fogDensity: gl.getUniformLocation(program, 'fogDensity'),
        fogNear: gl.getUniformLocation(program, 'fogNear'),
        fogFar: gl.getUniformLocation(program, 'fogFar'),
        fogColor: gl.getUniformLocation(program, 'fogColor'),
        fogDepth: gl.getUniformLocation(program, 'fogDepth'),
        alphaTest: gl.getUniformLocation(program, 'alphaTest')
      };
      var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
      canvas.width = 8;
      canvas.height = 8;
      var context = canvas.getContext('2d');
      context.fillStyle = 'white';
      context.fillRect(0, 0, 8, 8);
      texture = new CanvasTexture(canvas);
    }
    this.render = function(sprites, scene, camera) {
      if (sprites.length === 0)
        return;
      if (program === undefined) {
        init();
      }
      state.useProgram(program);
      state.initAttributes();
      state.enableAttribute(attributes.position);
      state.enableAttribute(attributes.uv);
      state.disableUnusedAttributes();
      state.disable(gl.CULL_FACE);
      state.enable(gl.BLEND);
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.vertexAttribPointer(attributes.position, 2, gl.FLOAT, false, 2 * 8, 0);
      gl.vertexAttribPointer(attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
      gl.uniformMatrix4fv(uniforms.projectionMatrix, false, camera.projectionMatrix.elements);
      state.activeTexture(gl.TEXTURE0);
      gl.uniform1i(uniforms.map, 0);
      var oldFogType = 0;
      var sceneFogType = 0;
      var fog = scene.fog;
      if (fog) {
        gl.uniform3f(uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b);
        if (fog.isFog) {
          gl.uniform1f(uniforms.fogNear, fog.near);
          gl.uniform1f(uniforms.fogFar, fog.far);
          gl.uniform1i(uniforms.fogType, 1);
          oldFogType = 1;
          sceneFogType = 1;
        } else if (fog.isFogExp2) {
          gl.uniform1f(uniforms.fogDensity, fog.density);
          gl.uniform1i(uniforms.fogType, 2);
          oldFogType = 2;
          sceneFogType = 2;
        }
      } else {
        gl.uniform1i(uniforms.fogType, 0);
        oldFogType = 0;
        sceneFogType = 0;
      }
      for (var i = 0,
          l = sprites.length; i < l; i++) {
        var sprite = sprites[i];
        sprite.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, sprite.matrixWorld);
        sprite.z = -sprite.modelViewMatrix.elements[14];
      }
      sprites.sort(painterSortStable);
      var scale = [];
      for (var i = 0,
          l = sprites.length; i < l; i++) {
        var sprite = sprites[i];
        var material = sprite.material;
        if (material.visible === false)
          continue;
        sprite.onBeforeRender(renderer, scene, camera, undefined, material, undefined);
        gl.uniform1f(uniforms.alphaTest, material.alphaTest);
        gl.uniformMatrix4fv(uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements);
        sprite.matrixWorld.decompose(spritePosition, spriteRotation, spriteScale);
        scale[0] = spriteScale.x;
        scale[1] = spriteScale.y;
        var fogType = 0;
        if (scene.fog && material.fog) {
          fogType = sceneFogType;
        }
        if (oldFogType !== fogType) {
          gl.uniform1i(uniforms.fogType, fogType);
          oldFogType = fogType;
        }
        if (material.map !== null) {
          gl.uniform2f(uniforms.uvOffset, material.map.offset.x, material.map.offset.y);
          gl.uniform2f(uniforms.uvScale, material.map.repeat.x, material.map.repeat.y);
        } else {
          gl.uniform2f(uniforms.uvOffset, 0, 0);
          gl.uniform2f(uniforms.uvScale, 1, 1);
        }
        gl.uniform1f(uniforms.opacity, material.opacity);
        gl.uniform3f(uniforms.color, material.color.r, material.color.g, material.color.b);
        gl.uniform1f(uniforms.rotation, material.rotation);
        gl.uniform2fv(uniforms.scale, scale);
        state.setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha);
        state.buffers.depth.setTest(material.depthTest);
        state.buffers.depth.setMask(material.depthWrite);
        state.buffers.color.setMask(material.colorWrite);
        textures.setTexture2D(material.map || texture, 0);
        gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
        sprite.onAfterRender(renderer, scene, camera, undefined, material, undefined);
      }
      state.enable(gl.CULL_FACE);
      state.reset();
    };
    function createProgram() {
      var program = gl.createProgram();
      var vertexShader = gl.createShader(gl.VERTEX_SHADER);
      var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
      gl.shaderSource(vertexShader, ['precision ' + capabilities.precision + ' float;', '#define SHADER_NAME ' + 'SpriteMaterial', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform float rotation;', 'uniform vec2 scale;', 'uniform vec2 uvOffset;', 'uniform vec2 uvScale;', 'attribute vec2 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'varying float fogDepth;', 'void main() {', '	vUV = uvOffset + uv * uvScale;', '	vec2 alignedPosition = position * scale;', '	vec2 rotatedPosition;', '	rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', '	rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', '	vec4 mvPosition;', '	mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', '	mvPosition.xy += rotatedPosition;', '	gl_Position = projectionMatrix * mvPosition;', '	fogDepth = - mvPosition.z;', '}'].join('\n'));
      gl.shaderSource(fragmentShader, ['precision ' + capabilities.precision + ' float;', '#define SHADER_NAME ' + 'SpriteMaterial', 'uniform vec3 color;', 'uniform sampler2D map;', 'uniform float opacity;', 'uniform int fogType;', 'uniform vec3 fogColor;', 'uniform float fogDensity;', 'uniform float fogNear;', 'uniform float fogFar;', 'uniform float alphaTest;', 'varying vec2 vUV;', 'varying float fogDepth;', 'void main() {', '	vec4 texture = texture2D( map, vUV );', '	gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', '	if ( gl_FragColor.a < alphaTest ) discard;', '	if ( fogType > 0 ) {', '		float fogFactor = 0.0;', '		if ( fogType == 1 ) {', '			fogFactor = smoothstep( fogNear, fogFar, fogDepth );', '		} else {', '			const float LOG2 = 1.442695;', '			fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );', '			fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', '		}', '		gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );', '	}', '}'].join('\n'));
      gl.compileShader(vertexShader);
      gl.compileShader(fragmentShader);
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      return program;
    }
    function painterSortStable(a, b) {
      if (a.renderOrder !== b.renderOrder) {
        return a.renderOrder - b.renderOrder;
      } else if (a.z !== b.z) {
        return b.z - a.z;
      } else {
        return b.id - a.id;
      }
    }
  }
  var materialId = 0;
  function Material() {
    Object.defineProperty(this, 'id', {value: materialId++});
    this.uuid = _Math.generateUUID();
    this.name = '';
    this.type = 'Material';
    this.fog = true;
    this.lights = true;
    this.blending = NormalBlending;
    this.side = FrontSide;
    this.flatShading = false;
    this.vertexColors = NoColors;
    this.opacity = 1;
    this.transparent = false;
    this.blendSrc = SrcAlphaFactor;
    this.blendDst = OneMinusSrcAlphaFactor;
    this.blendEquation = AddEquation;
    this.blendSrcAlpha = null;
    this.blendDstAlpha = null;
    this.blendEquationAlpha = null;
    this.depthFunc = LessEqualDepth;
    this.depthTest = true;
    this.depthWrite = true;
    this.clippingPlanes = null;
    this.clipIntersection = false;
    this.clipShadows = false;
    this.colorWrite = true;
    this.precision = null;
    this.polygonOffset = false;
    this.polygonOffsetFactor = 0;
    this.polygonOffsetUnits = 0;
    this.dithering = false;
    this.alphaTest = 0;
    this.premultipliedAlpha = false;
    this.overdraw = 0;
    this.visible = true;
    this.userData = {};
    this.needsUpdate = true;
  }
  Object.assign(Material.prototype, EventDispatcher.prototype, {
    isMaterial: true,
    onBeforeCompile: function() {},
    setValues: function(values) {
      if (values === undefined)
        return;
      for (var key in values) {
        var newValue = values[key];
        if (newValue === undefined) {
          console.warn("THREE.Material: '" + key + "' parameter is undefined.");
          continue;
        }
        if (key === 'shading') {
          console.warn('THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.');
          this.flatShading = (newValue === FlatShading) ? true : false;
          continue;
        }
        var currentValue = this[key];
        if (currentValue === undefined) {
          console.warn("THREE." + this.type + ": '" + key + "' is not a property of this material.");
          continue;
        }
        if (currentValue && currentValue.isColor) {
          currentValue.set(newValue);
        } else if ((currentValue && currentValue.isVector3) && (newValue && newValue.isVector3)) {
          currentValue.copy(newValue);
        } else if (key === 'overdraw') {
          this[key] = Number(newValue);
        } else {
          this[key] = newValue;
        }
      }
    },
    toJSON: function(meta) {
      var isRoot = (meta === undefined || typeof meta === 'string');
      if (isRoot) {
        meta = {
          textures: {},
          images: {}
        };
      }
      var data = {metadata: {
          version: 4.5,
          type: 'Material',
          generator: 'Material.toJSON'
        }};
      data.uuid = this.uuid;
      data.type = this.type;
      if (this.name !== '')
        data.name = this.name;
      if (this.color && this.color.isColor)
        data.color = this.color.getHex();
      if (this.roughness !== undefined)
        data.roughness = this.roughness;
      if (this.metalness !== undefined)
        data.metalness = this.metalness;
      if (this.emissive && this.emissive.isColor)
        data.emissive = this.emissive.getHex();
      if (this.emissiveIntensity !== 1)
        data.emissiveIntensity = this.emissiveIntensity;
      if (this.specular && this.specular.isColor)
        data.specular = this.specular.getHex();
      if (this.shininess !== undefined)
        data.shininess = this.shininess;
      if (this.clearCoat !== undefined)
        data.clearCoat = this.clearCoat;
      if (this.clearCoatRoughness !== undefined)
        data.clearCoatRoughness = this.clearCoatRoughness;
      if (this.map && this.map.isTexture)
        data.map = this.map.toJSON(meta).uuid;
      if (this.alphaMap && this.alphaMap.isTexture)
        data.alphaMap = this.alphaMap.toJSON(meta).uuid;
      if (this.lightMap && this.lightMap.isTexture)
        data.lightMap = this.lightMap.toJSON(meta).uuid;
      if (this.bumpMap && this.bumpMap.isTexture) {
        data.bumpMap = this.bumpMap.toJSON(meta).uuid;
        data.bumpScale = this.bumpScale;
      }
      if (this.normalMap && this.normalMap.isTexture) {
        data.normalMap = this.normalMap.toJSON(meta).uuid;
        data.normalScale = this.normalScale.toArray();
      }
      if (this.displacementMap && this.displacementMap.isTexture) {
        data.displacementMap = this.displacementMap.toJSON(meta).uuid;
        data.displacementScale = this.displacementScale;
        data.displacementBias = this.displacementBias;
      }
      if (this.roughnessMap && this.roughnessMap.isTexture)
        data.roughnessMap = this.roughnessMap.toJSON(meta).uuid;
      if (this.metalnessMap && this.metalnessMap.isTexture)
        data.metalnessMap = this.metalnessMap.toJSON(meta).uuid;
      if (this.emissiveMap && this.emissiveMap.isTexture)
        data.emissiveMap = this.emissiveMap.toJSON(meta).uuid;
      if (this.specularMap && this.specularMap.isTexture)
        data.specularMap = this.specularMap.toJSON(meta).uuid;
      if (this.envMap && this.envMap.isTexture) {
        data.envMap = this.envMap.toJSON(meta).uuid;
        data.reflectivity = this.reflectivity;
      }
      if (this.gradientMap && this.gradientMap.isTexture) {
        data.gradientMap = this.gradientMap.toJSON(meta).uuid;
      }
      if (this.size !== undefined)
        data.size = this.size;
      if (this.sizeAttenuation !== undefined)
        data.sizeAttenuation = this.sizeAttenuation;
      if (this.blending !== NormalBlending)
        data.blending = this.blending;
      if (this.flatShading === true)
        data.flatShading = this.flatShading;
      if (this.side !== FrontSide)
        data.side = this.side;
      if (this.vertexColors !== NoColors)
        data.vertexColors = this.vertexColors;
      if (this.opacity < 1)
        data.opacity = this.opacity;
      if (this.transparent === true)
        data.transparent = this.transparent;
      data.depthFunc = this.depthFunc;
      data.depthTest = this.depthTest;
      data.depthWrite = this.depthWrite;
      if (this.rotation !== 0)
        data.rotation = this.rotation;
      if (this.linewidth !== 1)
        data.linewidth = this.linewidth;
      if (this.dashSize !== undefined)
        data.dashSize = this.dashSize;
      if (this.gapSize !== undefined)
        data.gapSize = this.gapSize;
      if (this.scale !== undefined)
        data.scale = this.scale;
      if (this.dithering === true)
        data.dithering = true;
      if (this.alphaTest > 0)
        data.alphaTest = this.alphaTest;
      if (this.premultipliedAlpha === true)
        data.premultipliedAlpha = this.premultipliedAlpha;
      if (this.wireframe === true)
        data.wireframe = this.wireframe;
      if (this.wireframeLinewidth > 1)
        data.wireframeLinewidth = this.wireframeLinewidth;
      if (this.wireframeLinecap !== 'round')
        data.wireframeLinecap = this.wireframeLinecap;
      if (this.wireframeLinejoin !== 'round')
        data.wireframeLinejoin = this.wireframeLinejoin;
      if (this.morphTargets === true)
        data.morphTargets = true;
      if (this.skinning === true)
        data.skinning = true;
      if (this.visible === false)
        data.visible = false;
      if (JSON.stringify(this.userData) !== '{}')
        data.userData = this.userData;
      function extractFromCache(cache) {
        var values = [];
        for (var key in cache) {
          var data = cache[key];
          delete data.metadata;
          values.push(data);
        }
        return values;
      }
      if (isRoot) {
        var textures = extractFromCache(meta.textures);
        var images = extractFromCache(meta.images);
        if (textures.length > 0)
          data.textures = textures;
        if (images.length > 0)
          data.images = images;
      }
      return data;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.name = source.name;
      this.fog = source.fog;
      this.lights = source.lights;
      this.blending = source.blending;
      this.side = source.side;
      this.flatShading = source.flatShading;
      this.vertexColors = source.vertexColors;
      this.opacity = source.opacity;
      this.transparent = source.transparent;
      this.blendSrc = source.blendSrc;
      this.blendDst = source.blendDst;
      this.blendEquation = source.blendEquation;
      this.blendSrcAlpha = source.blendSrcAlpha;
      this.blendDstAlpha = source.blendDstAlpha;
      this.blendEquationAlpha = source.blendEquationAlpha;
      this.depthFunc = source.depthFunc;
      this.depthTest = source.depthTest;
      this.depthWrite = source.depthWrite;
      this.colorWrite = source.colorWrite;
      this.precision = source.precision;
      this.polygonOffset = source.polygonOffset;
      this.polygonOffsetFactor = source.polygonOffsetFactor;
      this.polygonOffsetUnits = source.polygonOffsetUnits;
      this.dithering = source.dithering;
      this.alphaTest = source.alphaTest;
      this.premultipliedAlpha = source.premultipliedAlpha;
      this.overdraw = source.overdraw;
      this.visible = source.visible;
      this.userData = JSON.parse(JSON.stringify(source.userData));
      this.clipShadows = source.clipShadows;
      this.clipIntersection = source.clipIntersection;
      var srcPlanes = source.clippingPlanes,
          dstPlanes = null;
      if (srcPlanes !== null) {
        var n = srcPlanes.length;
        dstPlanes = new Array(n);
        for (var i = 0; i !== n; ++i)
          dstPlanes[i] = srcPlanes[i].clone();
      }
      this.clippingPlanes = dstPlanes;
      return this;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  });
  function MeshDepthMaterial(parameters) {
    Material.call(this);
    this.type = 'MeshDepthMaterial';
    this.depthPacking = BasicDepthPacking;
    this.skinning = false;
    this.morphTargets = false;
    this.map = null;
    this.alphaMap = null;
    this.displacementMap = null;
    this.displacementScale = 1;
    this.displacementBias = 0;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.fog = false;
    this.lights = false;
    this.setValues(parameters);
  }
  MeshDepthMaterial.prototype = Object.create(Material.prototype);
  MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
  MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
  MeshDepthMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.depthPacking = source.depthPacking;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.map = source.map;
    this.alphaMap = source.alphaMap;
    this.displacementMap = source.displacementMap;
    this.displacementScale = source.displacementScale;
    this.displacementBias = source.displacementBias;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    return this;
  };
  function MeshDistanceMaterial(parameters) {
    Material.call(this);
    this.type = 'MeshDistanceMaterial';
    this.referencePosition = new Vector3();
    this.nearDistance = 1;
    this.farDistance = 1000;
    this.skinning = false;
    this.morphTargets = false;
    this.map = null;
    this.alphaMap = null;
    this.displacementMap = null;
    this.displacementScale = 1;
    this.displacementBias = 0;
    this.fog = false;
    this.lights = false;
    this.setValues(parameters);
  }
  MeshDistanceMaterial.prototype = Object.create(Material.prototype);
  MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
  MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
  MeshDistanceMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.referencePosition.copy(source.referencePosition);
    this.nearDistance = source.nearDistance;
    this.farDistance = source.farDistance;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.map = source.map;
    this.alphaMap = source.alphaMap;
    this.displacementMap = source.displacementMap;
    this.displacementScale = source.displacementScale;
    this.displacementBias = source.displacementBias;
    return this;
  };
  function Box3(min, max) {
    this.min = (min !== undefined) ? min : new Vector3(+Infinity, +Infinity, +Infinity);
    this.max = (max !== undefined) ? max : new Vector3(-Infinity, -Infinity, -Infinity);
  }
  Object.assign(Box3.prototype, {
    isBox3: true,
    set: function(min, max) {
      this.min.copy(min);
      this.max.copy(max);
      return this;
    },
    setFromArray: function(array) {
      var minX = +Infinity;
      var minY = +Infinity;
      var minZ = +Infinity;
      var maxX = -Infinity;
      var maxY = -Infinity;
      var maxZ = -Infinity;
      for (var i = 0,
          l = array.length; i < l; i += 3) {
        var x = array[i];
        var y = array[i + 1];
        var z = array[i + 2];
        if (x < minX)
          minX = x;
        if (y < minY)
          minY = y;
        if (z < minZ)
          minZ = z;
        if (x > maxX)
          maxX = x;
        if (y > maxY)
          maxY = y;
        if (z > maxZ)
          maxZ = z;
      }
      this.min.set(minX, minY, minZ);
      this.max.set(maxX, maxY, maxZ);
      return this;
    },
    setFromBufferAttribute: function(attribute) {
      var minX = +Infinity;
      var minY = +Infinity;
      var minZ = +Infinity;
      var maxX = -Infinity;
      var maxY = -Infinity;
      var maxZ = -Infinity;
      for (var i = 0,
          l = attribute.count; i < l; i++) {
        var x = attribute.getX(i);
        var y = attribute.getY(i);
        var z = attribute.getZ(i);
        if (x < minX)
          minX = x;
        if (y < minY)
          minY = y;
        if (z < minZ)
          minZ = z;
        if (x > maxX)
          maxX = x;
        if (y > maxY)
          maxY = y;
        if (z > maxZ)
          maxZ = z;
      }
      this.min.set(minX, minY, minZ);
      this.max.set(maxX, maxY, maxZ);
      return this;
    },
    setFromPoints: function(points) {
      this.makeEmpty();
      for (var i = 0,
          il = points.length; i < il; i++) {
        this.expandByPoint(points[i]);
      }
      return this;
    },
    setFromCenterAndSize: function() {
      var v1 = new Vector3();
      return function setFromCenterAndSize(center, size) {
        var halfSize = v1.copy(size).multiplyScalar(0.5);
        this.min.copy(center).sub(halfSize);
        this.max.copy(center).add(halfSize);
        return this;
      };
    }(),
    setFromObject: function(object) {
      this.makeEmpty();
      return this.expandByObject(object);
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(box) {
      this.min.copy(box.min);
      this.max.copy(box.max);
      return this;
    },
    makeEmpty: function() {
      this.min.x = this.min.y = this.min.z = +Infinity;
      this.max.x = this.max.y = this.max.z = -Infinity;
      return this;
    },
    isEmpty: function() {
      return (this.max.x < this.min.x) || (this.max.y < this.min.y) || (this.max.z < this.min.z);
    },
    getCenter: function(optionalTarget) {
      var result = optionalTarget || new Vector3();
      return this.isEmpty() ? result.set(0, 0, 0) : result.addVectors(this.min, this.max).multiplyScalar(0.5);
    },
    getSize: function(optionalTarget) {
      var result = optionalTarget || new Vector3();
      return this.isEmpty() ? result.set(0, 0, 0) : result.subVectors(this.max, this.min);
    },
    expandByPoint: function(point) {
      this.min.min(point);
      this.max.max(point);
      return this;
    },
    expandByVector: function(vector) {
      this.min.sub(vector);
      this.max.add(vector);
      return this;
    },
    expandByScalar: function(scalar) {
      this.min.addScalar(-scalar);
      this.max.addScalar(scalar);
      return this;
    },
    expandByObject: function() {
      var scope,
          i,
          l;
      var v1 = new Vector3();
      function traverse(node) {
        var geometry = node.geometry;
        if (geometry !== undefined) {
          if (geometry.isGeometry) {
            var vertices = geometry.vertices;
            for (i = 0, l = vertices.length; i < l; i++) {
              v1.copy(vertices[i]);
              v1.applyMatrix4(node.matrixWorld);
              scope.expandByPoint(v1);
            }
          } else if (geometry.isBufferGeometry) {
            var attribute = geometry.attributes.position;
            if (attribute !== undefined) {
              for (i = 0, l = attribute.count; i < l; i++) {
                v1.fromBufferAttribute(attribute, i).applyMatrix4(node.matrixWorld);
                scope.expandByPoint(v1);
              }
            }
          }
        }
      }
      return function expandByObject(object) {
        scope = this;
        object.updateMatrixWorld(true);
        object.traverse(traverse);
        return this;
      };
    }(),
    containsPoint: function(point) {
      return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y || point.z < this.min.z || point.z > this.max.z ? false : true;
    },
    containsBox: function(box) {
      return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y && this.min.z <= box.min.z && box.max.z <= this.max.z;
    },
    getParameter: function(point, optionalTarget) {
      var result = optionalTarget || new Vector3();
      return result.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y), (point.z - this.min.z) / (this.max.z - this.min.z));
    },
    intersectsBox: function(box) {
      return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y || box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
    },
    intersectsSphere: (function() {
      var closestPoint = new Vector3();
      return function intersectsSphere(sphere) {
        this.clampPoint(sphere.center, closestPoint);
        return closestPoint.distanceToSquared(sphere.center) <= (sphere.radius * sphere.radius);
      };
    })(),
    intersectsPlane: function(plane) {
      var min,
          max;
      if (plane.normal.x > 0) {
        min = plane.normal.x * this.min.x;
        max = plane.normal.x * this.max.x;
      } else {
        min = plane.normal.x * this.max.x;
        max = plane.normal.x * this.min.x;
      }
      if (plane.normal.y > 0) {
        min += plane.normal.y * this.min.y;
        max += plane.normal.y * this.max.y;
      } else {
        min += plane.normal.y * this.max.y;
        max += plane.normal.y * this.min.y;
      }
      if (plane.normal.z > 0) {
        min += plane.normal.z * this.min.z;
        max += plane.normal.z * this.max.z;
      } else {
        min += plane.normal.z * this.max.z;
        max += plane.normal.z * this.min.z;
      }
      return (min <= plane.constant && max >= plane.constant);
    },
    clampPoint: function(point, optionalTarget) {
      var result = optionalTarget || new Vector3();
      return result.copy(point).clamp(this.min, this.max);
    },
    distanceToPoint: function() {
      var v1 = new Vector3();
      return function distanceToPoint(point) {
        var clampedPoint = v1.copy(point).clamp(this.min, this.max);
        return clampedPoint.sub(point).length();
      };
    }(),
    getBoundingSphere: function() {
      var v1 = new Vector3();
      return function getBoundingSphere(optionalTarget) {
        var result = optionalTarget || new Sphere();
        this.getCenter(result.center);
        result.radius = this.getSize(v1).length() * 0.5;
        return result;
      };
    }(),
    intersect: function(box) {
      this.min.max(box.min);
      this.max.min(box.max);
      if (this.isEmpty())
        this.makeEmpty();
      return this;
    },
    union: function(box) {
      this.min.min(box.min);
      this.max.max(box.max);
      return this;
    },
    applyMatrix4: function() {
      var points = [new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3(), new Vector3()];
      return function applyMatrix4(matrix) {
        if (this.isEmpty())
          return this;
        points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix);
        points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix);
        points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix);
        points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix);
        points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix);
        points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix);
        points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix);
        points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix);
        this.setFromPoints(points);
        return this;
      };
    }(),
    translate: function(offset) {
      this.min.add(offset);
      this.max.add(offset);
      return this;
    },
    equals: function(box) {
      return box.min.equals(this.min) && box.max.equals(this.max);
    }
  });
  function Sphere(center, radius) {
    this.center = (center !== undefined) ? center : new Vector3();
    this.radius = (radius !== undefined) ? radius : 0;
  }
  Object.assign(Sphere.prototype, {
    set: function(center, radius) {
      this.center.copy(center);
      this.radius = radius;
      return this;
    },
    setFromPoints: function() {
      var box = new Box3();
      return function setFromPoints(points, optionalCenter) {
        var center = this.center;
        if (optionalCenter !== undefined) {
          center.copy(optionalCenter);
        } else {
          box.setFromPoints(points).getCenter(center);
        }
        var maxRadiusSq = 0;
        for (var i = 0,
            il = points.length; i < il; i++) {
          maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i]));
        }
        this.radius = Math.sqrt(maxRadiusSq);
        return this;
      };
    }(),
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(sphere) {
      this.center.copy(sphere.center);
      this.radius = sphere.radius;
      return this;
    },
    empty: function() {
      return (this.radius <= 0);
    },
    containsPoint: function(point) {
      return (point.distanceToSquared(this.center) <= (this.radius * this.radius));
    },
    distanceToPoint: function(point) {
      return (point.distanceTo(this.center) - this.radius);
    },
    intersectsSphere: function(sphere) {
      var radiusSum = this.radius + sphere.radius;
      return sphere.center.distanceToSquared(this.center) <= (radiusSum * radiusSum);
    },
    intersectsBox: function(box) {
      return box.intersectsSphere(this);
    },
    intersectsPlane: function(plane) {
      return Math.abs(plane.distanceToPoint(this.center)) <= this.radius;
    },
    clampPoint: function(point, optionalTarget) {
      var deltaLengthSq = this.center.distanceToSquared(point);
      var result = optionalTarget || new Vector3();
      result.copy(point);
      if (deltaLengthSq > (this.radius * this.radius)) {
        result.sub(this.center).normalize();
        result.multiplyScalar(this.radius).add(this.center);
      }
      return result;
    },
    getBoundingBox: function(optionalTarget) {
      var box = optionalTarget || new Box3();
      box.set(this.center, this.center);
      box.expandByScalar(this.radius);
      return box;
    },
    applyMatrix4: function(matrix) {
      this.center.applyMatrix4(matrix);
      this.radius = this.radius * matrix.getMaxScaleOnAxis();
      return this;
    },
    translate: function(offset) {
      this.center.add(offset);
      return this;
    },
    equals: function(sphere) {
      return sphere.center.equals(this.center) && (sphere.radius === this.radius);
    }
  });
  function Plane(normal, constant) {
    this.normal = (normal !== undefined) ? normal : new Vector3(1, 0, 0);
    this.constant = (constant !== undefined) ? constant : 0;
  }
  Object.assign(Plane.prototype, {
    set: function(normal, constant) {
      this.normal.copy(normal);
      this.constant = constant;
      return this;
    },
    setComponents: function(x, y, z, w) {
      this.normal.set(x, y, z);
      this.constant = w;
      return this;
    },
    setFromNormalAndCoplanarPoint: function(normal, point) {
      this.normal.copy(normal);
      this.constant = -point.dot(this.normal);
      return this;
    },
    setFromCoplanarPoints: function() {
      var v1 = new Vector3();
      var v2 = new Vector3();
      return function setFromCoplanarPoints(a, b, c) {
        var normal = v1.subVectors(c, b).cross(v2.subVectors(a, b)).normalize();
        this.setFromNormalAndCoplanarPoint(normal, a);
        return this;
      };
    }(),
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(plane) {
      this.normal.copy(plane.normal);
      this.constant = plane.constant;
      return this;
    },
    normalize: function() {
      var inverseNormalLength = 1.0 / this.normal.length();
      this.normal.multiplyScalar(inverseNormalLength);
      this.constant *= inverseNormalLength;
      return this;
    },
    negate: function() {
      this.constant *= -1;
      this.normal.negate();
      return this;
    },
    distanceToPoint: function(point) {
      return this.normal.dot(point) + this.constant;
    },
    distanceToSphere: function(sphere) {
      return this.distanceToPoint(sphere.center) - sphere.radius;
    },
    projectPoint: function(point, optionalTarget) {
      var result = optionalTarget || new Vector3();
      return result.copy(this.normal).multiplyScalar(-this.distanceToPoint(point)).add(point);
    },
    intersectLine: function() {
      var v1 = new Vector3();
      return function intersectLine(line, optionalTarget) {
        var result = optionalTarget || new Vector3();
        var direction = line.delta(v1);
        var denominator = this.normal.dot(direction);
        if (denominator === 0) {
          if (this.distanceToPoint(line.start) === 0) {
            return result.copy(line.start);
          }
          return undefined;
        }
        var t = -(line.start.dot(this.normal) + this.constant) / denominator;
        if (t < 0 || t > 1) {
          return undefined;
        }
        return result.copy(direction).multiplyScalar(t).add(line.start);
      };
    }(),
    intersectsLine: function(line) {
      var startSign = this.distanceToPoint(line.start);
      var endSign = this.distanceToPoint(line.end);
      return (startSign < 0 && endSign > 0) || (endSign < 0 && startSign > 0);
    },
    intersectsBox: function(box) {
      return box.intersectsPlane(this);
    },
    intersectsSphere: function(sphere) {
      return sphere.intersectsPlane(this);
    },
    coplanarPoint: function(optionalTarget) {
      var result = optionalTarget || new Vector3();
      return result.copy(this.normal).multiplyScalar(-this.constant);
    },
    applyMatrix4: function() {
      var v1 = new Vector3();
      var m1 = new Matrix3();
      return function applyMatrix4(matrix, optionalNormalMatrix) {
        var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix(matrix);
        var referencePoint = this.coplanarPoint(v1).applyMatrix4(matrix);
        var normal = this.normal.applyMatrix3(normalMatrix).normalize();
        this.constant = -referencePoint.dot(normal);
        return this;
      };
    }(),
    translate: function(offset) {
      this.constant -= offset.dot(this.normal);
      return this;
    },
    equals: function(plane) {
      return plane.normal.equals(this.normal) && (plane.constant === this.constant);
    }
  });
  function Frustum(p0, p1, p2, p3, p4, p5) {
    this.planes = [(p0 !== undefined) ? p0 : new Plane(), (p1 !== undefined) ? p1 : new Plane(), (p2 !== undefined) ? p2 : new Plane(), (p3 !== undefined) ? p3 : new Plane(), (p4 !== undefined) ? p4 : new Plane(), (p5 !== undefined) ? p5 : new Plane()];
  }
  Object.assign(Frustum.prototype, {
    set: function(p0, p1, p2, p3, p4, p5) {
      var planes = this.planes;
      planes[0].copy(p0);
      planes[1].copy(p1);
      planes[2].copy(p2);
      planes[3].copy(p3);
      planes[4].copy(p4);
      planes[5].copy(p5);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(frustum) {
      var planes = this.planes;
      for (var i = 0; i < 6; i++) {
        planes[i].copy(frustum.planes[i]);
      }
      return this;
    },
    setFromMatrix: function(m) {
      var planes = this.planes;
      var me = m.elements;
      var me0 = me[0],
          me1 = me[1],
          me2 = me[2],
          me3 = me[3];
      var me4 = me[4],
          me5 = me[5],
          me6 = me[6],
          me7 = me[7];
      var me8 = me[8],
          me9 = me[9],
          me10 = me[10],
          me11 = me[11];
      var me12 = me[12],
          me13 = me[13],
          me14 = me[14],
          me15 = me[15];
      planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12).normalize();
      planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me15 + me12).normalize();
      planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me15 + me13).normalize();
      planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me15 - me13).normalize();
      planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me15 - me14).normalize();
      planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me15 + me14).normalize();
      return this;
    },
    intersectsObject: function() {
      var sphere = new Sphere();
      return function intersectsObject(object) {
        var geometry = object.geometry;
        if (geometry.boundingSphere === null)
          geometry.computeBoundingSphere();
        sphere.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld);
        return this.intersectsSphere(sphere);
      };
    }(),
    intersectsSprite: function() {
      var sphere = new Sphere();
      return function intersectsSprite(sprite) {
        sphere.center.set(0, 0, 0);
        sphere.radius = 0.7071067811865476;
        sphere.applyMatrix4(sprite.matrixWorld);
        return this.intersectsSphere(sphere);
      };
    }(),
    intersectsSphere: function(sphere) {
      var planes = this.planes;
      var center = sphere.center;
      var negRadius = -sphere.radius;
      for (var i = 0; i < 6; i++) {
        var distance = planes[i].distanceToPoint(center);
        if (distance < negRadius) {
          return false;
        }
      }
      return true;
    },
    intersectsBox: function() {
      var p1 = new Vector3(),
          p2 = new Vector3();
      return function intersectsBox(box) {
        var planes = this.planes;
        for (var i = 0; i < 6; i++) {
          var plane = planes[i];
          p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
          p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
          p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
          p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
          p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
          p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
          var d1 = plane.distanceToPoint(p1);
          var d2 = plane.distanceToPoint(p2);
          if (d1 < 0 && d2 < 0) {
            return false;
          }
        }
        return true;
      };
    }(),
    containsPoint: function(point) {
      var planes = this.planes;
      for (var i = 0; i < 6; i++) {
        if (planes[i].distanceToPoint(point) < 0) {
          return false;
        }
      }
      return true;
    }
  });
  function WebGLShadowMap(_renderer, _objects, maxTextureSize) {
    var _frustum = new Frustum(),
        _projScreenMatrix = new Matrix4(),
        _shadowMapSize = new Vector2(),
        _maxShadowMapSize = new Vector2(maxTextureSize, maxTextureSize),
        _lookTarget = new Vector3(),
        _lightPositionWorld = new Vector3(),
        _MorphingFlag = 1,
        _SkinningFlag = 2,
        _NumberOfMaterialVariants = (_MorphingFlag | _SkinningFlag) + 1,
        _depthMaterials = new Array(_NumberOfMaterialVariants),
        _distanceMaterials = new Array(_NumberOfMaterialVariants),
        _materialCache = {};
    var cubeDirections = [new Vector3(1, 0, 0), new Vector3(-1, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 0, -1), new Vector3(0, 1, 0), new Vector3(0, -1, 0)];
    var cubeUps = [new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, -1)];
    var cube2DViewPorts = [new Vector4(), new Vector4(), new Vector4(), new Vector4(), new Vector4(), new Vector4()];
    for (var i = 0; i !== _NumberOfMaterialVariants; ++i) {
      var useMorphing = (i & _MorphingFlag) !== 0;
      var useSkinning = (i & _SkinningFlag) !== 0;
      var depthMaterial = new MeshDepthMaterial({
        depthPacking: RGBADepthPacking,
        morphTargets: useMorphing,
        skinning: useSkinning
      });
      _depthMaterials[i] = depthMaterial;
      var distanceMaterial = new MeshDistanceMaterial({
        morphTargets: useMorphing,
        skinning: useSkinning
      });
      _distanceMaterials[i] = distanceMaterial;
    }
    var scope = this;
    this.enabled = false;
    this.autoUpdate = true;
    this.needsUpdate = false;
    this.type = PCFShadowMap;
    this.renderReverseSided = true;
    this.renderSingleSided = true;
    this.render = function(lights, scene, camera) {
      if (scope.enabled === false)
        return;
      if (scope.autoUpdate === false && scope.needsUpdate === false)
        return;
      if (lights.length === 0)
        return;
      var _gl = _renderer.context;
      var _state = _renderer.state;
      _state.disable(_gl.BLEND);
      _state.buffers.color.setClear(1, 1, 1, 1);
      _state.buffers.depth.setTest(true);
      _state.setScissorTest(false);
      var faceCount;
      for (var i = 0,
          il = lights.length; i < il; i++) {
        var light = lights[i];
        var shadow = light.shadow;
        var isPointLight = light && light.isPointLight;
        if (shadow === undefined) {
          console.warn('THREE.WebGLShadowMap:', light, 'has no shadow.');
          continue;
        }
        var shadowCamera = shadow.camera;
        _shadowMapSize.copy(shadow.mapSize);
        _shadowMapSize.min(_maxShadowMapSize);
        if (isPointLight) {
          var vpWidth = _shadowMapSize.x;
          var vpHeight = _shadowMapSize.y;
          cube2DViewPorts[0].set(vpWidth * 2, vpHeight, vpWidth, vpHeight);
          cube2DViewPorts[1].set(0, vpHeight, vpWidth, vpHeight);
          cube2DViewPorts[2].set(vpWidth * 3, vpHeight, vpWidth, vpHeight);
          cube2DViewPorts[3].set(vpWidth, vpHeight, vpWidth, vpHeight);
          cube2DViewPorts[4].set(vpWidth * 3, 0, vpWidth, vpHeight);
          cube2DViewPorts[5].set(vpWidth, 0, vpWidth, vpHeight);
          _shadowMapSize.x *= 4.0;
          _shadowMapSize.y *= 2.0;
        }
        if (shadow.map === null) {
          var pars = {
            minFilter: NearestFilter,
            magFilter: NearestFilter,
            format: RGBAFormat
          };
          shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
          shadow.map.texture.name = light.name + ".shadowMap";
          shadowCamera.updateProjectionMatrix();
        }
        if (shadow.isSpotLightShadow) {
          shadow.update(light);
        }
        var shadowMap = shadow.map;
        var shadowMatrix = shadow.matrix;
        _lightPositionWorld.setFromMatrixPosition(light.matrixWorld);
        shadowCamera.position.copy(_lightPositionWorld);
        if (isPointLight) {
          faceCount = 6;
          shadowMatrix.makeTranslation(-_lightPositionWorld.x, -_lightPositionWorld.y, -_lightPositionWorld.z);
        } else {
          faceCount = 1;
          _lookTarget.setFromMatrixPosition(light.target.matrixWorld);
          shadowCamera.lookAt(_lookTarget);
          shadowCamera.updateMatrixWorld();
          shadowMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);
          shadowMatrix.multiply(shadowCamera.projectionMatrix);
          shadowMatrix.multiply(shadowCamera.matrixWorldInverse);
        }
        _renderer.setRenderTarget(shadowMap);
        _renderer.clear();
        for (var face = 0; face < faceCount; face++) {
          if (isPointLight) {
            _lookTarget.copy(shadowCamera.position);
            _lookTarget.add(cubeDirections[face]);
            shadowCamera.up.copy(cubeUps[face]);
            shadowCamera.lookAt(_lookTarget);
            shadowCamera.updateMatrixWorld();
            var vpDimensions = cube2DViewPorts[face];
            _state.viewport(vpDimensions);
          }
          _projScreenMatrix.multiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse);
          _frustum.setFromMatrix(_projScreenMatrix);
          renderObject(scene, camera, shadowCamera, isPointLight);
        }
      }
      scope.needsUpdate = false;
    };
    function getDepthMaterial(object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar) {
      var geometry = object.geometry;
      var result = null;
      var materialVariants = _depthMaterials;
      var customMaterial = object.customDepthMaterial;
      if (isPointLight) {
        materialVariants = _distanceMaterials;
        customMaterial = object.customDistanceMaterial;
      }
      if (!customMaterial) {
        var useMorphing = false;
        if (material.morphTargets) {
          if (geometry && geometry.isBufferGeometry) {
            useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
          } else if (geometry && geometry.isGeometry) {
            useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;
          }
        }
        if (object.isSkinnedMesh && material.skinning === false) {
          console.warn('THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object);
        }
        var useSkinning = object.isSkinnedMesh && material.skinning;
        var variantIndex = 0;
        if (useMorphing)
          variantIndex |= _MorphingFlag;
        if (useSkinning)
          variantIndex |= _SkinningFlag;
        result = materialVariants[variantIndex];
      } else {
        result = customMaterial;
      }
      if (_renderer.localClippingEnabled && material.clipShadows === true && material.clippingPlanes.length !== 0) {
        var keyA = result.uuid,
            keyB = material.uuid;
        var materialsForVariant = _materialCache[keyA];
        if (materialsForVariant === undefined) {
          materialsForVariant = {};
          _materialCache[keyA] = materialsForVariant;
        }
        var cachedMaterial = materialsForVariant[keyB];
        if (cachedMaterial === undefined) {
          cachedMaterial = result.clone();
          materialsForVariant[keyB] = cachedMaterial;
        }
        result = cachedMaterial;
      }
      result.visible = material.visible;
      result.wireframe = material.wireframe;
      var side = material.side;
      if (scope.renderSingleSided && side == DoubleSide) {
        side = FrontSide;
      }
      if (scope.renderReverseSided) {
        if (side === FrontSide)
          side = BackSide;
        else if (side === BackSide)
          side = FrontSide;
      }
      result.side = side;
      result.clipShadows = material.clipShadows;
      result.clippingPlanes = material.clippingPlanes;
      result.clipIntersection = material.clipIntersection;
      result.wireframeLinewidth = material.wireframeLinewidth;
      result.linewidth = material.linewidth;
      if (isPointLight && result.isMeshDistanceMaterial) {
        result.referencePosition.copy(lightPositionWorld);
        result.nearDistance = shadowCameraNear;
        result.farDistance = shadowCameraFar;
      }
      return result;
    }
    function renderObject(object, camera, shadowCamera, isPointLight) {
      if (object.visible === false)
        return;
      var visible = object.layers.test(camera.layers);
      if (visible && (object.isMesh || object.isLine || object.isPoints)) {
        if (object.castShadow && (!object.frustumCulled || _frustum.intersectsObject(object))) {
          object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld);
          var geometry = _objects.update(object);
          var material = object.material;
          if (Array.isArray(material)) {
            var groups = geometry.groups;
            for (var k = 0,
                kl = groups.length; k < kl; k++) {
              var group = groups[k];
              var groupMaterial = material[group.materialIndex];
              if (groupMaterial && groupMaterial.visible) {
                var depthMaterial = getDepthMaterial(object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far);
                _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group);
              }
            }
          } else if (material.visible) {
            var depthMaterial = getDepthMaterial(object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far);
            _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null);
          }
        }
      }
      var children = object.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        renderObject(children[i], camera, shadowCamera, isPointLight);
      }
    }
  }
  function WebGLAttributes(gl) {
    var buffers = {};
    function createBuffer(attribute, bufferType) {
      var array = attribute.array;
      var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
      var buffer = gl.createBuffer();
      gl.bindBuffer(bufferType, buffer);
      gl.bufferData(bufferType, array, usage);
      attribute.onUploadCallback();
      var type = gl.FLOAT;
      if (array instanceof Float32Array) {
        type = gl.FLOAT;
      } else if (array instanceof Float64Array) {
        console.warn('THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.');
      } else if (array instanceof Uint16Array) {
        type = gl.UNSIGNED_SHORT;
      } else if (array instanceof Int16Array) {
        type = gl.SHORT;
      } else if (array instanceof Uint32Array) {
        type = gl.UNSIGNED_INT;
      } else if (array instanceof Int32Array) {
        type = gl.INT;
      } else if (array instanceof Int8Array) {
        type = gl.BYTE;
      } else if (array instanceof Uint8Array) {
        type = gl.UNSIGNED_BYTE;
      }
      return {
        buffer: buffer,
        type: type,
        bytesPerElement: array.BYTES_PER_ELEMENT,
        version: attribute.version
      };
    }
    function updateBuffer(buffer, attribute, bufferType) {
      var array = attribute.array;
      var updateRange = attribute.updateRange;
      gl.bindBuffer(bufferType, buffer);
      if (attribute.dynamic === false) {
        gl.bufferData(bufferType, array, gl.STATIC_DRAW);
      } else if (updateRange.count === -1) {
        gl.bufferSubData(bufferType, 0, array);
      } else if (updateRange.count === 0) {
        console.error('THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.');
      } else {
        gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, array.subarray(updateRange.offset, updateRange.offset + updateRange.count));
        updateRange.count = -1;
      }
    }
    function get(attribute) {
      if (attribute.isInterleavedBufferAttribute)
        attribute = attribute.data;
      return buffers[attribute.uuid];
    }
    function remove(attribute) {
      if (attribute.isInterleavedBufferAttribute)
        attribute = attribute.data;
      var data = buffers[attribute.uuid];
      if (data) {
        gl.deleteBuffer(data.buffer);
        delete buffers[attribute.uuid];
      }
    }
    function update(attribute, bufferType) {
      if (attribute.isInterleavedBufferAttribute)
        attribute = attribute.data;
      var data = buffers[attribute.uuid];
      if (data === undefined) {
        buffers[attribute.uuid] = createBuffer(attribute, bufferType);
      } else if (data.version < attribute.version) {
        updateBuffer(data.buffer, attribute, bufferType);
        data.version = attribute.version;
      }
    }
    return {
      get: get,
      remove: remove,
      update: update
    };
  }
  function Euler(x, y, z, order) {
    this._x = x || 0;
    this._y = y || 0;
    this._z = z || 0;
    this._order = order || Euler.DefaultOrder;
  }
  Euler.RotationOrders = ['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX'];
  Euler.DefaultOrder = 'XYZ';
  Object.defineProperties(Euler.prototype, {
    x: {
      get: function() {
        return this._x;
      },
      set: function(value) {
        this._x = value;
        this.onChangeCallback();
      }
    },
    y: {
      get: function() {
        return this._y;
      },
      set: function(value) {
        this._y = value;
        this.onChangeCallback();
      }
    },
    z: {
      get: function() {
        return this._z;
      },
      set: function(value) {
        this._z = value;
        this.onChangeCallback();
      }
    },
    order: {
      get: function() {
        return this._order;
      },
      set: function(value) {
        this._order = value;
        this.onChangeCallback();
      }
    }
  });
  Object.assign(Euler.prototype, {
    isEuler: true,
    set: function(x, y, z, order) {
      this._x = x;
      this._y = y;
      this._z = z;
      this._order = order || this._order;
      this.onChangeCallback();
      return this;
    },
    clone: function() {
      return new this.constructor(this._x, this._y, this._z, this._order);
    },
    copy: function(euler) {
      this._x = euler._x;
      this._y = euler._y;
      this._z = euler._z;
      this._order = euler._order;
      this.onChangeCallback();
      return this;
    },
    setFromRotationMatrix: function(m, order, update) {
      var clamp = _Math.clamp;
      var te = m.elements;
      var m11 = te[0],
          m12 = te[4],
          m13 = te[8];
      var m21 = te[1],
          m22 = te[5],
          m23 = te[9];
      var m31 = te[2],
          m32 = te[6],
          m33 = te[10];
      order = order || this._order;
      if (order === 'XYZ') {
        this._y = Math.asin(clamp(m13, -1, 1));
        if (Math.abs(m13) < 0.99999) {
          this._x = Math.atan2(-m23, m33);
          this._z = Math.atan2(-m12, m11);
        } else {
          this._x = Math.atan2(m32, m22);
          this._z = 0;
        }
      } else if (order === 'YXZ') {
        this._x = Math.asin(-clamp(m23, -1, 1));
        if (Math.abs(m23) < 0.99999) {
          this._y = Math.atan2(m13, m33);
          this._z = Math.atan2(m21, m22);
        } else {
          this._y = Math.atan2(-m31, m11);
          this._z = 0;
        }
      } else if (order === 'ZXY') {
        this._x = Math.asin(clamp(m32, -1, 1));
        if (Math.abs(m32) < 0.99999) {
          this._y = Math.atan2(-m31, m33);
          this._z = Math.atan2(-m12, m22);
        } else {
          this._y = 0;
          this._z = Math.atan2(m21, m11);
        }
      } else if (order === 'ZYX') {
        this._y = Math.asin(-clamp(m31, -1, 1));
        if (Math.abs(m31) < 0.99999) {
          this._x = Math.atan2(m32, m33);
          this._z = Math.atan2(m21, m11);
        } else {
          this._x = 0;
          this._z = Math.atan2(-m12, m22);
        }
      } else if (order === 'YZX') {
        this._z = Math.asin(clamp(m21, -1, 1));
        if (Math.abs(m21) < 0.99999) {
          this._x = Math.atan2(-m23, m22);
          this._y = Math.atan2(-m31, m11);
        } else {
          this._x = 0;
          this._y = Math.atan2(m13, m33);
        }
      } else if (order === 'XZY') {
        this._z = Math.asin(-clamp(m12, -1, 1));
        if (Math.abs(m12) < 0.99999) {
          this._x = Math.atan2(m32, m22);
          this._y = Math.atan2(m13, m11);
        } else {
          this._x = Math.atan2(-m23, m33);
          this._y = 0;
        }
      } else {
        console.warn('THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order);
      }
      this._order = order;
      if (update !== false)
        this.onChangeCallback();
      return this;
    },
    setFromQuaternion: function() {
      var matrix = new Matrix4();
      return function setFromQuaternion(q, order, update) {
        matrix.makeRotationFromQuaternion(q);
        return this.setFromRotationMatrix(matrix, order, update);
      };
    }(),
    setFromVector3: function(v, order) {
      return this.set(v.x, v.y, v.z, order || this._order);
    },
    reorder: function() {
      var q = new Quaternion();
      return function reorder(newOrder) {
        q.setFromEuler(this);
        return this.setFromQuaternion(q, newOrder);
      };
    }(),
    equals: function(euler) {
      return (euler._x === this._x) && (euler._y === this._y) && (euler._z === this._z) && (euler._order === this._order);
    },
    fromArray: function(array) {
      this._x = array[0];
      this._y = array[1];
      this._z = array[2];
      if (array[3] !== undefined)
        this._order = array[3];
      this.onChangeCallback();
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this._x;
      array[offset + 1] = this._y;
      array[offset + 2] = this._z;
      array[offset + 3] = this._order;
      return array;
    },
    toVector3: function(optionalResult) {
      if (optionalResult) {
        return optionalResult.set(this._x, this._y, this._z);
      } else {
        return new Vector3(this._x, this._y, this._z);
      }
    },
    onChange: function(callback) {
      this.onChangeCallback = callback;
      return this;
    },
    onChangeCallback: function() {}
  });
  function Layers() {
    this.mask = 1 | 0;
  }
  Object.assign(Layers.prototype, {
    set: function(channel) {
      this.mask = 1 << channel | 0;
    },
    enable: function(channel) {
      this.mask |= 1 << channel | 0;
    },
    toggle: function(channel) {
      this.mask ^= 1 << channel | 0;
    },
    disable: function(channel) {
      this.mask &= ~(1 << channel | 0);
    },
    test: function(layers) {
      return (this.mask & layers.mask) !== 0;
    }
  });
  var object3DId = 0;
  function Object3D() {
    Object.defineProperty(this, 'id', {value: object3DId++});
    this.uuid = _Math.generateUUID();
    this.name = '';
    this.type = 'Object3D';
    this.parent = null;
    this.children = [];
    this.up = Object3D.DefaultUp.clone();
    var position = new Vector3();
    var rotation = new Euler();
    var quaternion = new Quaternion();
    var scale = new Vector3(1, 1, 1);
    function onRotationChange() {
      quaternion.setFromEuler(rotation, false);
    }
    function onQuaternionChange() {
      rotation.setFromQuaternion(quaternion, undefined, false);
    }
    rotation.onChange(onRotationChange);
    quaternion.onChange(onQuaternionChange);
    Object.defineProperties(this, {
      position: {
        enumerable: true,
        value: position
      },
      rotation: {
        enumerable: true,
        value: rotation
      },
      quaternion: {
        enumerable: true,
        value: quaternion
      },
      scale: {
        enumerable: true,
        value: scale
      },
      modelViewMatrix: {value: new Matrix4()},
      normalMatrix: {value: new Matrix3()}
    });
    this.matrix = new Matrix4();
    this.matrixWorld = new Matrix4();
    this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
    this.matrixWorldNeedsUpdate = false;
    this.layers = new Layers();
    this.visible = true;
    this.castShadow = false;
    this.receiveShadow = false;
    this.frustumCulled = true;
    this.renderOrder = 0;
    this.userData = {};
  }
  Object3D.DefaultUp = new Vector3(0, 1, 0);
  Object3D.DefaultMatrixAutoUpdate = true;
  Object.assign(Object3D.prototype, EventDispatcher.prototype, {
    isObject3D: true,
    onBeforeRender: function() {},
    onAfterRender: function() {},
    applyMatrix: function(matrix) {
      this.matrix.multiplyMatrices(matrix, this.matrix);
      this.matrix.decompose(this.position, this.quaternion, this.scale);
    },
    applyQuaternion: function(q) {
      this.quaternion.premultiply(q);
      return this;
    },
    setRotationFromAxisAngle: function(axis, angle) {
      this.quaternion.setFromAxisAngle(axis, angle);
    },
    setRotationFromEuler: function(euler) {
      this.quaternion.setFromEuler(euler, true);
    },
    setRotationFromMatrix: function(m) {
      this.quaternion.setFromRotationMatrix(m);
    },
    setRotationFromQuaternion: function(q) {
      this.quaternion.copy(q);
    },
    rotateOnAxis: function() {
      var q1 = new Quaternion();
      return function rotateOnAxis(axis, angle) {
        q1.setFromAxisAngle(axis, angle);
        this.quaternion.multiply(q1);
        return this;
      };
    }(),
    rotateOnWorldAxis: function() {
      var q1 = new Quaternion();
      return function rotateOnWorldAxis(axis, angle) {
        q1.setFromAxisAngle(axis, angle);
        this.quaternion.premultiply(q1);
        return this;
      };
    }(),
    rotateX: function() {
      var v1 = new Vector3(1, 0, 0);
      return function rotateX(angle) {
        return this.rotateOnAxis(v1, angle);
      };
    }(),
    rotateY: function() {
      var v1 = new Vector3(0, 1, 0);
      return function rotateY(angle) {
        return this.rotateOnAxis(v1, angle);
      };
    }(),
    rotateZ: function() {
      var v1 = new Vector3(0, 0, 1);
      return function rotateZ(angle) {
        return this.rotateOnAxis(v1, angle);
      };
    }(),
    translateOnAxis: function() {
      var v1 = new Vector3();
      return function translateOnAxis(axis, distance) {
        v1.copy(axis).applyQuaternion(this.quaternion);
        this.position.add(v1.multiplyScalar(distance));
        return this;
      };
    }(),
    translateX: function() {
      var v1 = new Vector3(1, 0, 0);
      return function translateX(distance) {
        return this.translateOnAxis(v1, distance);
      };
    }(),
    translateY: function() {
      var v1 = new Vector3(0, 1, 0);
      return function translateY(distance) {
        return this.translateOnAxis(v1, distance);
      };
    }(),
    translateZ: function() {
      var v1 = new Vector3(0, 0, 1);
      return function translateZ(distance) {
        return this.translateOnAxis(v1, distance);
      };
    }(),
    localToWorld: function(vector) {
      return vector.applyMatrix4(this.matrixWorld);
    },
    worldToLocal: function() {
      var m1 = new Matrix4();
      return function worldToLocal(vector) {
        return vector.applyMatrix4(m1.getInverse(this.matrixWorld));
      };
    }(),
    lookAt: function() {
      var m1 = new Matrix4();
      var vector = new Vector3();
      return function lookAt(x, y, z) {
        if (x.isVector3) {
          vector.copy(x);
        } else {
          vector.set(x, y, z);
        }
        if (this.isCamera) {
          m1.lookAt(this.position, vector, this.up);
        } else {
          m1.lookAt(vector, this.position, this.up);
        }
        this.quaternion.setFromRotationMatrix(m1);
      };
    }(),
    add: function(object) {
      if (arguments.length > 1) {
        for (var i = 0; i < arguments.length; i++) {
          this.add(arguments[i]);
        }
        return this;
      }
      if (object === this) {
        console.error("THREE.Object3D.add: object can't be added as a child of itself.", object);
        return this;
      }
      if ((object && object.isObject3D)) {
        if (object.parent !== null) {
          object.parent.remove(object);
        }
        object.parent = this;
        object.dispatchEvent({type: 'added'});
        this.children.push(object);
      } else {
        console.error("THREE.Object3D.add: object not an instance of THREE.Object3D.", object);
      }
      return this;
    },
    remove: function(object) {
      if (arguments.length > 1) {
        for (var i = 0; i < arguments.length; i++) {
          this.remove(arguments[i]);
        }
        return this;
      }
      var index = this.children.indexOf(object);
      if (index !== -1) {
        object.parent = null;
        object.dispatchEvent({type: 'removed'});
        this.children.splice(index, 1);
      }
      return this;
    },
    getObjectById: function(id) {
      return this.getObjectByProperty('id', id);
    },
    getObjectByName: function(name) {
      return this.getObjectByProperty('name', name);
    },
    getObjectByProperty: function(name, value) {
      if (this[name] === value)
        return this;
      for (var i = 0,
          l = this.children.length; i < l; i++) {
        var child = this.children[i];
        var object = child.getObjectByProperty(name, value);
        if (object !== undefined) {
          return object;
        }
      }
      return undefined;
    },
    getWorldPosition: function(optionalTarget) {
      var result = optionalTarget || new Vector3();
      this.updateMatrixWorld(true);
      return result.setFromMatrixPosition(this.matrixWorld);
    },
    getWorldQuaternion: function() {
      var position = new Vector3();
      var scale = new Vector3();
      return function getWorldQuaternion(optionalTarget) {
        var result = optionalTarget || new Quaternion();
        this.updateMatrixWorld(true);
        this.matrixWorld.decompose(position, result, scale);
        return result;
      };
    }(),
    getWorldRotation: function() {
      var quaternion = new Quaternion();
      return function getWorldRotation(optionalTarget) {
        var result = optionalTarget || new Euler();
        this.getWorldQuaternion(quaternion);
        return result.setFromQuaternion(quaternion, this.rotation.order, false);
      };
    }(),
    getWorldScale: function() {
      var position = new Vector3();
      var quaternion = new Quaternion();
      return function getWorldScale(optionalTarget) {
        var result = optionalTarget || new Vector3();
        this.updateMatrixWorld(true);
        this.matrixWorld.decompose(position, quaternion, result);
        return result;
      };
    }(),
    getWorldDirection: function() {
      var quaternion = new Quaternion();
      return function getWorldDirection(optionalTarget) {
        var result = optionalTarget || new Vector3();
        this.getWorldQuaternion(quaternion);
        return result.set(0, 0, 1).applyQuaternion(quaternion);
      };
    }(),
    raycast: function() {},
    traverse: function(callback) {
      callback(this);
      var children = this.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        children[i].traverse(callback);
      }
    },
    traverseVisible: function(callback) {
      if (this.visible === false)
        return;
      callback(this);
      var children = this.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        children[i].traverseVisible(callback);
      }
    },
    traverseAncestors: function(callback) {
      var parent = this.parent;
      if (parent !== null) {
        callback(parent);
        parent.traverseAncestors(callback);
      }
    },
    updateMatrix: function() {
      this.matrix.compose(this.position, this.quaternion, this.scale);
      this.matrixWorldNeedsUpdate = true;
    },
    updateMatrixWorld: function(force) {
      if (this.matrixAutoUpdate)
        this.updateMatrix();
      if (this.matrixWorldNeedsUpdate || force) {
        if (this.parent === null) {
          this.matrixWorld.copy(this.matrix);
        } else {
          this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
        }
        this.matrixWorldNeedsUpdate = false;
        force = true;
      }
      var children = this.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        children[i].updateMatrixWorld(force);
      }
    },
    toJSON: function(meta) {
      var isRootObject = (meta === undefined || typeof meta === 'string');
      var output = {};
      if (isRootObject) {
        meta = {
          geometries: {},
          materials: {},
          textures: {},
          images: {}
        };
        output.metadata = {
          version: 4.5,
          type: 'Object',
          generator: 'Object3D.toJSON'
        };
      }
      var object = {};
      object.uuid = this.uuid;
      object.type = this.type;
      if (this.name !== '')
        object.name = this.name;
      if (this.castShadow === true)
        object.castShadow = true;
      if (this.receiveShadow === true)
        object.receiveShadow = true;
      if (this.visible === false)
        object.visible = false;
      if (JSON.stringify(this.userData) !== '{}')
        object.userData = this.userData;
      object.matrix = this.matrix.toArray();
      function serialize(library, element) {
        if (library[element.uuid] === undefined) {
          library[element.uuid] = element.toJSON(meta);
        }
        return element.uuid;
      }
      if (this.geometry !== undefined) {
        object.geometry = serialize(meta.geometries, this.geometry);
      }
      if (this.material !== undefined) {
        if (Array.isArray(this.material)) {
          var uuids = [];
          for (var i = 0,
              l = this.material.length; i < l; i++) {
            uuids.push(serialize(meta.materials, this.material[i]));
          }
          object.material = uuids;
        } else {
          object.material = serialize(meta.materials, this.material);
        }
      }
      if (this.children.length > 0) {
        object.children = [];
        for (var i = 0; i < this.children.length; i++) {
          object.children.push(this.children[i].toJSON(meta).object);
        }
      }
      if (isRootObject) {
        var geometries = extractFromCache(meta.geometries);
        var materials = extractFromCache(meta.materials);
        var textures = extractFromCache(meta.textures);
        var images = extractFromCache(meta.images);
        if (geometries.length > 0)
          output.geometries = geometries;
        if (materials.length > 0)
          output.materials = materials;
        if (textures.length > 0)
          output.textures = textures;
        if (images.length > 0)
          output.images = images;
      }
      output.object = object;
      return output;
      function extractFromCache(cache) {
        var values = [];
        for (var key in cache) {
          var data = cache[key];
          delete data.metadata;
          values.push(data);
        }
        return values;
      }
    },
    clone: function(recursive) {
      return new this.constructor().copy(this, recursive);
    },
    copy: function(source, recursive) {
      if (recursive === undefined)
        recursive = true;
      this.name = source.name;
      this.up.copy(source.up);
      this.position.copy(source.position);
      this.quaternion.copy(source.quaternion);
      this.scale.copy(source.scale);
      this.matrix.copy(source.matrix);
      this.matrixWorld.copy(source.matrixWorld);
      this.matrixAutoUpdate = source.matrixAutoUpdate;
      this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
      this.layers.mask = source.layers.mask;
      this.visible = source.visible;
      this.castShadow = source.castShadow;
      this.receiveShadow = source.receiveShadow;
      this.frustumCulled = source.frustumCulled;
      this.renderOrder = source.renderOrder;
      this.userData = JSON.parse(JSON.stringify(source.userData));
      if (recursive === true) {
        for (var i = 0; i < source.children.length; i++) {
          var child = source.children[i];
          this.add(child.clone());
        }
      }
      return this;
    }
  });
  function Camera() {
    Object3D.call(this);
    this.type = 'Camera';
    this.matrixWorldInverse = new Matrix4();
    this.projectionMatrix = new Matrix4();
  }
  Camera.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Camera,
    isCamera: true,
    copy: function(source, recursive) {
      Object3D.prototype.copy.call(this, source, recursive);
      this.matrixWorldInverse.copy(source.matrixWorldInverse);
      this.projectionMatrix.copy(source.projectionMatrix);
      return this;
    },
    getWorldDirection: function() {
      var quaternion = new Quaternion();
      return function getWorldDirection(optionalTarget) {
        var result = optionalTarget || new Vector3();
        this.getWorldQuaternion(quaternion);
        return result.set(0, 0, -1).applyQuaternion(quaternion);
      };
    }(),
    updateMatrixWorld: function(force) {
      Object3D.prototype.updateMatrixWorld.call(this, force);
      this.matrixWorldInverse.getInverse(this.matrixWorld);
    },
    clone: function() {
      return new this.constructor().copy(this);
    }
  });
  function OrthographicCamera(left, right, top, bottom, near, far) {
    Camera.call(this);
    this.type = 'OrthographicCamera';
    this.zoom = 1;
    this.view = null;
    this.left = left;
    this.right = right;
    this.top = top;
    this.bottom = bottom;
    this.near = (near !== undefined) ? near : 0.1;
    this.far = (far !== undefined) ? far : 2000;
    this.updateProjectionMatrix();
  }
  OrthographicCamera.prototype = Object.assign(Object.create(Camera.prototype), {
    constructor: OrthographicCamera,
    isOrthographicCamera: true,
    copy: function(source, recursive) {
      Camera.prototype.copy.call(this, source, recursive);
      this.left = source.left;
      this.right = source.right;
      this.top = source.top;
      this.bottom = source.bottom;
      this.near = source.near;
      this.far = source.far;
      this.zoom = source.zoom;
      this.view = source.view === null ? null : Object.assign({}, source.view);
      return this;
    },
    setViewOffset: function(fullWidth, fullHeight, x, y, width, height) {
      if (this.view === null) {
        this.view = {
          enabled: true,
          fullWidth: 1,
          fullHeight: 1,
          offsetX: 0,
          offsetY: 0,
          width: 1,
          height: 1
        };
      }
      this.view.enabled = true;
      this.view.fullWidth = fullWidth;
      this.view.fullHeight = fullHeight;
      this.view.offsetX = x;
      this.view.offsetY = y;
      this.view.width = width;
      this.view.height = height;
      this.updateProjectionMatrix();
    },
    clearViewOffset: function() {
      if (this.view !== null) {
        this.view.enabled = false;
      }
      this.updateProjectionMatrix();
    },
    updateProjectionMatrix: function() {
      var dx = (this.right - this.left) / (2 * this.zoom);
      var dy = (this.top - this.bottom) / (2 * this.zoom);
      var cx = (this.right + this.left) / 2;
      var cy = (this.top + this.bottom) / 2;
      var left = cx - dx;
      var right = cx + dx;
      var top = cy + dy;
      var bottom = cy - dy;
      if (this.view !== null && this.view.enabled) {
        var zoomW = this.zoom / (this.view.width / this.view.fullWidth);
        var zoomH = this.zoom / (this.view.height / this.view.fullHeight);
        var scaleW = (this.right - this.left) / this.view.width;
        var scaleH = (this.top - this.bottom) / this.view.height;
        left += scaleW * (this.view.offsetX / zoomW);
        right = left + scaleW * (this.view.width / zoomW);
        top -= scaleH * (this.view.offsetY / zoomH);
        bottom = top - scaleH * (this.view.height / zoomH);
      }
      this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far);
    },
    toJSON: function(meta) {
      var data = Object3D.prototype.toJSON.call(this, meta);
      data.object.zoom = this.zoom;
      data.object.left = this.left;
      data.object.right = this.right;
      data.object.top = this.top;
      data.object.bottom = this.bottom;
      data.object.near = this.near;
      data.object.far = this.far;
      if (this.view !== null)
        data.object.view = Object.assign({}, this.view);
      return data;
    }
  });
  function Face3(a, b, c, normal, color, materialIndex) {
    this.a = a;
    this.b = b;
    this.c = c;
    this.normal = (normal && normal.isVector3) ? normal : new Vector3();
    this.vertexNormals = Array.isArray(normal) ? normal : [];
    this.color = (color && color.isColor) ? color : new Color();
    this.vertexColors = Array.isArray(color) ? color : [];
    this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
  }
  Object.assign(Face3.prototype, {
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.a = source.a;
      this.b = source.b;
      this.c = source.c;
      this.normal.copy(source.normal);
      this.color.copy(source.color);
      this.materialIndex = source.materialIndex;
      for (var i = 0,
          il = source.vertexNormals.length; i < il; i++) {
        this.vertexNormals[i] = source.vertexNormals[i].clone();
      }
      for (var i = 0,
          il = source.vertexColors.length; i < il; i++) {
        this.vertexColors[i] = source.vertexColors[i].clone();
      }
      return this;
    }
  });
  var geometryId = 0;
  function Geometry() {
    Object.defineProperty(this, 'id', {value: geometryId += 2});
    this.uuid = _Math.generateUUID();
    this.name = '';
    this.type = 'Geometry';
    this.vertices = [];
    this.colors = [];
    this.faces = [];
    this.faceVertexUvs = [[]];
    this.morphTargets = [];
    this.morphNormals = [];
    this.skinWeights = [];
    this.skinIndices = [];
    this.lineDistances = [];
    this.boundingBox = null;
    this.boundingSphere = null;
    this.elementsNeedUpdate = false;
    this.verticesNeedUpdate = false;
    this.uvsNeedUpdate = false;
    this.normalsNeedUpdate = false;
    this.colorsNeedUpdate = false;
    this.lineDistancesNeedUpdate = false;
    this.groupsNeedUpdate = false;
  }
  Object.assign(Geometry.prototype, EventDispatcher.prototype, {
    isGeometry: true,
    applyMatrix: function(matrix) {
      var normalMatrix = new Matrix3().getNormalMatrix(matrix);
      for (var i = 0,
          il = this.vertices.length; i < il; i++) {
        var vertex = this.vertices[i];
        vertex.applyMatrix4(matrix);
      }
      for (var i = 0,
          il = this.faces.length; i < il; i++) {
        var face = this.faces[i];
        face.normal.applyMatrix3(normalMatrix).normalize();
        for (var j = 0,
            jl = face.vertexNormals.length; j < jl; j++) {
          face.vertexNormals[j].applyMatrix3(normalMatrix).normalize();
        }
      }
      if (this.boundingBox !== null) {
        this.computeBoundingBox();
      }
      if (this.boundingSphere !== null) {
        this.computeBoundingSphere();
      }
      this.verticesNeedUpdate = true;
      this.normalsNeedUpdate = true;
      return this;
    },
    rotateX: function() {
      var m1 = new Matrix4();
      return function rotateX(angle) {
        m1.makeRotationX(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    rotateY: function() {
      var m1 = new Matrix4();
      return function rotateY(angle) {
        m1.makeRotationY(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    rotateZ: function() {
      var m1 = new Matrix4();
      return function rotateZ(angle) {
        m1.makeRotationZ(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    translate: function() {
      var m1 = new Matrix4();
      return function translate(x, y, z) {
        m1.makeTranslation(x, y, z);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    scale: function() {
      var m1 = new Matrix4();
      return function scale(x, y, z) {
        m1.makeScale(x, y, z);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    lookAt: function() {
      var obj = new Object3D();
      return function lookAt(vector) {
        obj.lookAt(vector);
        obj.updateMatrix();
        this.applyMatrix(obj.matrix);
      };
    }(),
    fromBufferGeometry: function(geometry) {
      var scope = this;
      var indices = geometry.index !== null ? geometry.index.array : undefined;
      var attributes = geometry.attributes;
      var positions = attributes.position.array;
      var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
      var colors = attributes.color !== undefined ? attributes.color.array : undefined;
      var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
      var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
      if (uvs2 !== undefined)
        this.faceVertexUvs[1] = [];
      var tempNormals = [];
      var tempUVs = [];
      var tempUVs2 = [];
      for (var i = 0,
          j = 0; i < positions.length; i += 3, j += 2) {
        scope.vertices.push(new Vector3(positions[i], positions[i + 1], positions[i + 2]));
        if (normals !== undefined) {
          tempNormals.push(new Vector3(normals[i], normals[i + 1], normals[i + 2]));
        }
        if (colors !== undefined) {
          scope.colors.push(new Color(colors[i], colors[i + 1], colors[i + 2]));
        }
        if (uvs !== undefined) {
          tempUVs.push(new Vector2(uvs[j], uvs[j + 1]));
        }
        if (uvs2 !== undefined) {
          tempUVs2.push(new Vector2(uvs2[j], uvs2[j + 1]));
        }
      }
      function addFace(a, b, c, materialIndex) {
        var vertexNormals = normals !== undefined ? [tempNormals[a].clone(), tempNormals[b].clone(), tempNormals[c].clone()] : [];
        var vertexColors = colors !== undefined ? [scope.colors[a].clone(), scope.colors[b].clone(), scope.colors[c].clone()] : [];
        var face = new Face3(a, b, c, vertexNormals, vertexColors, materialIndex);
        scope.faces.push(face);
        if (uvs !== undefined) {
          scope.faceVertexUvs[0].push([tempUVs[a].clone(), tempUVs[b].clone(), tempUVs[c].clone()]);
        }
        if (uvs2 !== undefined) {
          scope.faceVertexUvs[1].push([tempUVs2[a].clone(), tempUVs2[b].clone(), tempUVs2[c].clone()]);
        }
      }
      var groups = geometry.groups;
      if (groups.length > 0) {
        for (var i = 0; i < groups.length; i++) {
          var group = groups[i];
          var start = group.start;
          var count = group.count;
          for (var j = start,
              jl = start + count; j < jl; j += 3) {
            if (indices !== undefined) {
              addFace(indices[j], indices[j + 1], indices[j + 2], group.materialIndex);
            } else {
              addFace(j, j + 1, j + 2, group.materialIndex);
            }
          }
        }
      } else {
        if (indices !== undefined) {
          for (var i = 0; i < indices.length; i += 3) {
            addFace(indices[i], indices[i + 1], indices[i + 2]);
          }
        } else {
          for (var i = 0; i < positions.length / 3; i += 3) {
            addFace(i, i + 1, i + 2);
          }
        }
      }
      this.computeFaceNormals();
      if (geometry.boundingBox !== null) {
        this.boundingBox = geometry.boundingBox.clone();
      }
      if (geometry.boundingSphere !== null) {
        this.boundingSphere = geometry.boundingSphere.clone();
      }
      return this;
    },
    center: function() {
      this.computeBoundingBox();
      var offset = this.boundingBox.getCenter().negate();
      this.translate(offset.x, offset.y, offset.z);
      return offset;
    },
    normalize: function() {
      this.computeBoundingSphere();
      var center = this.boundingSphere.center;
      var radius = this.boundingSphere.radius;
      var s = radius === 0 ? 1 : 1.0 / radius;
      var matrix = new Matrix4();
      matrix.set(s, 0, 0, -s * center.x, 0, s, 0, -s * center.y, 0, 0, s, -s * center.z, 0, 0, 0, 1);
      this.applyMatrix(matrix);
      return this;
    },
    computeFaceNormals: function() {
      var cb = new Vector3(),
          ab = new Vector3();
      for (var f = 0,
          fl = this.faces.length; f < fl; f++) {
        var face = this.faces[f];
        var vA = this.vertices[face.a];
        var vB = this.vertices[face.b];
        var vC = this.vertices[face.c];
        cb.subVectors(vC, vB);
        ab.subVectors(vA, vB);
        cb.cross(ab);
        cb.normalize();
        face.normal.copy(cb);
      }
    },
    computeVertexNormals: function(areaWeighted) {
      if (areaWeighted === undefined)
        areaWeighted = true;
      var v,
          vl,
          f,
          fl,
          face,
          vertices;
      vertices = new Array(this.vertices.length);
      for (v = 0, vl = this.vertices.length; v < vl; v++) {
        vertices[v] = new Vector3();
      }
      if (areaWeighted) {
        var vA,
            vB,
            vC;
        var cb = new Vector3(),
            ab = new Vector3();
        for (f = 0, fl = this.faces.length; f < fl; f++) {
          face = this.faces[f];
          vA = this.vertices[face.a];
          vB = this.vertices[face.b];
          vC = this.vertices[face.c];
          cb.subVectors(vC, vB);
          ab.subVectors(vA, vB);
          cb.cross(ab);
          vertices[face.a].add(cb);
          vertices[face.b].add(cb);
          vertices[face.c].add(cb);
        }
      } else {
        this.computeFaceNormals();
        for (f = 0, fl = this.faces.length; f < fl; f++) {
          face = this.faces[f];
          vertices[face.a].add(face.normal);
          vertices[face.b].add(face.normal);
          vertices[face.c].add(face.normal);
        }
      }
      for (v = 0, vl = this.vertices.length; v < vl; v++) {
        vertices[v].normalize();
      }
      for (f = 0, fl = this.faces.length; f < fl; f++) {
        face = this.faces[f];
        var vertexNormals = face.vertexNormals;
        if (vertexNormals.length === 3) {
          vertexNormals[0].copy(vertices[face.a]);
          vertexNormals[1].copy(vertices[face.b]);
          vertexNormals[2].copy(vertices[face.c]);
        } else {
          vertexNormals[0] = vertices[face.a].clone();
          vertexNormals[1] = vertices[face.b].clone();
          vertexNormals[2] = vertices[face.c].clone();
        }
      }
      if (this.faces.length > 0) {
        this.normalsNeedUpdate = true;
      }
    },
    computeFlatVertexNormals: function() {
      var f,
          fl,
          face;
      this.computeFaceNormals();
      for (f = 0, fl = this.faces.length; f < fl; f++) {
        face = this.faces[f];
        var vertexNormals = face.vertexNormals;
        if (vertexNormals.length === 3) {
          vertexNormals[0].copy(face.normal);
          vertexNormals[1].copy(face.normal);
          vertexNormals[2].copy(face.normal);
        } else {
          vertexNormals[0] = face.normal.clone();
          vertexNormals[1] = face.normal.clone();
          vertexNormals[2] = face.normal.clone();
        }
      }
      if (this.faces.length > 0) {
        this.normalsNeedUpdate = true;
      }
    },
    computeMorphNormals: function() {
      var i,
          il,
          f,
          fl,
          face;
      for (f = 0, fl = this.faces.length; f < fl; f++) {
        face = this.faces[f];
        if (!face.__originalFaceNormal) {
          face.__originalFaceNormal = face.normal.clone();
        } else {
          face.__originalFaceNormal.copy(face.normal);
        }
        if (!face.__originalVertexNormals)
          face.__originalVertexNormals = [];
        for (i = 0, il = face.vertexNormals.length; i < il; i++) {
          if (!face.__originalVertexNormals[i]) {
            face.__originalVertexNormals[i] = face.vertexNormals[i].clone();
          } else {
            face.__originalVertexNormals[i].copy(face.vertexNormals[i]);
          }
        }
      }
      var tmpGeo = new Geometry();
      tmpGeo.faces = this.faces;
      for (i = 0, il = this.morphTargets.length; i < il; i++) {
        if (!this.morphNormals[i]) {
          this.morphNormals[i] = {};
          this.morphNormals[i].faceNormals = [];
          this.morphNormals[i].vertexNormals = [];
          var dstNormalsFace = this.morphNormals[i].faceNormals;
          var dstNormalsVertex = this.morphNormals[i].vertexNormals;
          var faceNormal,
              vertexNormals;
          for (f = 0, fl = this.faces.length; f < fl; f++) {
            faceNormal = new Vector3();
            vertexNormals = {
              a: new Vector3(),
              b: new Vector3(),
              c: new Vector3()
            };
            dstNormalsFace.push(faceNormal);
            dstNormalsVertex.push(vertexNormals);
          }
        }
        var morphNormals = this.morphNormals[i];
        tmpGeo.vertices = this.morphTargets[i].vertices;
        tmpGeo.computeFaceNormals();
        tmpGeo.computeVertexNormals();
        var faceNormal,
            vertexNormals;
        for (f = 0, fl = this.faces.length; f < fl; f++) {
          face = this.faces[f];
          faceNormal = morphNormals.faceNormals[f];
          vertexNormals = morphNormals.vertexNormals[f];
          faceNormal.copy(face.normal);
          vertexNormals.a.copy(face.vertexNormals[0]);
          vertexNormals.b.copy(face.vertexNormals[1]);
          vertexNormals.c.copy(face.vertexNormals[2]);
        }
      }
      for (f = 0, fl = this.faces.length; f < fl; f++) {
        face = this.faces[f];
        face.normal = face.__originalFaceNormal;
        face.vertexNormals = face.__originalVertexNormals;
      }
    },
    computeLineDistances: function() {
      var d = 0;
      var vertices = this.vertices;
      for (var i = 0,
          il = vertices.length; i < il; i++) {
        if (i > 0) {
          d += vertices[i].distanceTo(vertices[i - 1]);
        }
        this.lineDistances[i] = d;
      }
    },
    computeBoundingBox: function() {
      if (this.boundingBox === null) {
        this.boundingBox = new Box3();
      }
      this.boundingBox.setFromPoints(this.vertices);
    },
    computeBoundingSphere: function() {
      if (this.boundingSphere === null) {
        this.boundingSphere = new Sphere();
      }
      this.boundingSphere.setFromPoints(this.vertices);
    },
    merge: function(geometry, matrix, materialIndexOffset) {
      if (!(geometry && geometry.isGeometry)) {
        console.error('THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry);
        return;
      }
      var normalMatrix,
          vertexOffset = this.vertices.length,
          vertices1 = this.vertices,
          vertices2 = geometry.vertices,
          faces1 = this.faces,
          faces2 = geometry.faces,
          uvs1 = this.faceVertexUvs[0],
          uvs2 = geometry.faceVertexUvs[0],
          colors1 = this.colors,
          colors2 = geometry.colors;
      if (materialIndexOffset === undefined)
        materialIndexOffset = 0;
      if (matrix !== undefined) {
        normalMatrix = new Matrix3().getNormalMatrix(matrix);
      }
      for (var i = 0,
          il = vertices2.length; i < il; i++) {
        var vertex = vertices2[i];
        var vertexCopy = vertex.clone();
        if (matrix !== undefined)
          vertexCopy.applyMatrix4(matrix);
        vertices1.push(vertexCopy);
      }
      for (var i = 0,
          il = colors2.length; i < il; i++) {
        colors1.push(colors2[i].clone());
      }
      for (i = 0, il = faces2.length; i < il; i++) {
        var face = faces2[i],
            faceCopy,
            normal,
            color,
            faceVertexNormals = face.vertexNormals,
            faceVertexColors = face.vertexColors;
        faceCopy = new Face3(face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset);
        faceCopy.normal.copy(face.normal);
        if (normalMatrix !== undefined) {
          faceCopy.normal.applyMatrix3(normalMatrix).normalize();
        }
        for (var j = 0,
            jl = faceVertexNormals.length; j < jl; j++) {
          normal = faceVertexNormals[j].clone();
          if (normalMatrix !== undefined) {
            normal.applyMatrix3(normalMatrix).normalize();
          }
          faceCopy.vertexNormals.push(normal);
        }
        faceCopy.color.copy(face.color);
        for (var j = 0,
            jl = faceVertexColors.length; j < jl; j++) {
          color = faceVertexColors[j];
          faceCopy.vertexColors.push(color.clone());
        }
        faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
        faces1.push(faceCopy);
      }
      for (i = 0, il = uvs2.length; i < il; i++) {
        var uv = uvs2[i],
            uvCopy = [];
        if (uv === undefined) {
          continue;
        }
        for (var j = 0,
            jl = uv.length; j < jl; j++) {
          uvCopy.push(uv[j].clone());
        }
        uvs1.push(uvCopy);
      }
    },
    mergeMesh: function(mesh) {
      if (!(mesh && mesh.isMesh)) {
        console.error('THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh);
        return;
      }
      mesh.matrixAutoUpdate && mesh.updateMatrix();
      this.merge(mesh.geometry, mesh.matrix);
    },
    mergeVertices: function() {
      var verticesMap = {};
      var unique = [],
          changes = [];
      var v,
          key;
      var precisionPoints = 4;
      var precision = Math.pow(10, precisionPoints);
      var i,
          il,
          face;
      var indices,
          j,
          jl;
      for (i = 0, il = this.vertices.length; i < il; i++) {
        v = this.vertices[i];
        key = Math.round(v.x * precision) + '_' + Math.round(v.y * precision) + '_' + Math.round(v.z * precision);
        if (verticesMap[key] === undefined) {
          verticesMap[key] = i;
          unique.push(this.vertices[i]);
          changes[i] = unique.length - 1;
        } else {
          changes[i] = changes[verticesMap[key]];
        }
      }
      var faceIndicesToRemove = [];
      for (i = 0, il = this.faces.length; i < il; i++) {
        face = this.faces[i];
        face.a = changes[face.a];
        face.b = changes[face.b];
        face.c = changes[face.c];
        indices = [face.a, face.b, face.c];
        for (var n = 0; n < 3; n++) {
          if (indices[n] === indices[(n + 1) % 3]) {
            faceIndicesToRemove.push(i);
            break;
          }
        }
      }
      for (i = faceIndicesToRemove.length - 1; i >= 0; i--) {
        var idx = faceIndicesToRemove[i];
        this.faces.splice(idx, 1);
        for (j = 0, jl = this.faceVertexUvs.length; j < jl; j++) {
          this.faceVertexUvs[j].splice(idx, 1);
        }
      }
      var diff = this.vertices.length - unique.length;
      this.vertices = unique;
      return diff;
    },
    setFromPoints: function(points) {
      this.vertices = [];
      for (var i = 0,
          l = points.length; i < l; i++) {
        var point = points[i];
        this.vertices.push(new Vector3(point.x, point.y, point.z || 0));
      }
      return this;
    },
    sortFacesByMaterialIndex: function() {
      var faces = this.faces;
      var length = faces.length;
      for (var i = 0; i < length; i++) {
        faces[i]._id = i;
      }
      function materialIndexSort(a, b) {
        return a.materialIndex - b.materialIndex;
      }
      faces.sort(materialIndexSort);
      var uvs1 = this.faceVertexUvs[0];
      var uvs2 = this.faceVertexUvs[1];
      var newUvs1,
          newUvs2;
      if (uvs1 && uvs1.length === length)
        newUvs1 = [];
      if (uvs2 && uvs2.length === length)
        newUvs2 = [];
      for (var i = 0; i < length; i++) {
        var id = faces[i]._id;
        if (newUvs1)
          newUvs1.push(uvs1[id]);
        if (newUvs2)
          newUvs2.push(uvs2[id]);
      }
      if (newUvs1)
        this.faceVertexUvs[0] = newUvs1;
      if (newUvs2)
        this.faceVertexUvs[1] = newUvs2;
    },
    toJSON: function() {
      var data = {metadata: {
          version: 4.5,
          type: 'Geometry',
          generator: 'Geometry.toJSON'
        }};
      data.uuid = this.uuid;
      data.type = this.type;
      if (this.name !== '')
        data.name = this.name;
      if (this.parameters !== undefined) {
        var parameters = this.parameters;
        for (var key in parameters) {
          if (parameters[key] !== undefined)
            data[key] = parameters[key];
        }
        return data;
      }
      var vertices = [];
      for (var i = 0; i < this.vertices.length; i++) {
        var vertex = this.vertices[i];
        vertices.push(vertex.x, vertex.y, vertex.z);
      }
      var faces = [];
      var normals = [];
      var normalsHash = {};
      var colors = [];
      var colorsHash = {};
      var uvs = [];
      var uvsHash = {};
      for (var i = 0; i < this.faces.length; i++) {
        var face = this.faces[i];
        var hasMaterial = true;
        var hasFaceUv = false;
        var hasFaceVertexUv = this.faceVertexUvs[0][i] !== undefined;
        var hasFaceNormal = face.normal.length() > 0;
        var hasFaceVertexNormal = face.vertexNormals.length > 0;
        var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
        var hasFaceVertexColor = face.vertexColors.length > 0;
        var faceType = 0;
        faceType = setBit(faceType, 0, 0);
        faceType = setBit(faceType, 1, hasMaterial);
        faceType = setBit(faceType, 2, hasFaceUv);
        faceType = setBit(faceType, 3, hasFaceVertexUv);
        faceType = setBit(faceType, 4, hasFaceNormal);
        faceType = setBit(faceType, 5, hasFaceVertexNormal);
        faceType = setBit(faceType, 6, hasFaceColor);
        faceType = setBit(faceType, 7, hasFaceVertexColor);
        faces.push(faceType);
        faces.push(face.a, face.b, face.c);
        faces.push(face.materialIndex);
        if (hasFaceVertexUv) {
          var faceVertexUvs = this.faceVertexUvs[0][i];
          faces.push(getUvIndex(faceVertexUvs[0]), getUvIndex(faceVertexUvs[1]), getUvIndex(faceVertexUvs[2]));
        }
        if (hasFaceNormal) {
          faces.push(getNormalIndex(face.normal));
        }
        if (hasFaceVertexNormal) {
          var vertexNormals = face.vertexNormals;
          faces.push(getNormalIndex(vertexNormals[0]), getNormalIndex(vertexNormals[1]), getNormalIndex(vertexNormals[2]));
        }
        if (hasFaceColor) {
          faces.push(getColorIndex(face.color));
        }
        if (hasFaceVertexColor) {
          var vertexColors = face.vertexColors;
          faces.push(getColorIndex(vertexColors[0]), getColorIndex(vertexColors[1]), getColorIndex(vertexColors[2]));
        }
      }
      function setBit(value, position, enabled) {
        return enabled ? value | (1 << position) : value & (~(1 << position));
      }
      function getNormalIndex(normal) {
        var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
        if (normalsHash[hash] !== undefined) {
          return normalsHash[hash];
        }
        normalsHash[hash] = normals.length / 3;
        normals.push(normal.x, normal.y, normal.z);
        return normalsHash[hash];
      }
      function getColorIndex(color) {
        var hash = color.r.toString() + color.g.toString() + color.b.toString();
        if (colorsHash[hash] !== undefined) {
          return colorsHash[hash];
        }
        colorsHash[hash] = colors.length;
        colors.push(color.getHex());
        return colorsHash[hash];
      }
      function getUvIndex(uv) {
        var hash = uv.x.toString() + uv.y.toString();
        if (uvsHash[hash] !== undefined) {
          return uvsHash[hash];
        }
        uvsHash[hash] = uvs.length / 2;
        uvs.push(uv.x, uv.y);
        return uvsHash[hash];
      }
      data.data = {};
      data.data.vertices = vertices;
      data.data.normals = normals;
      if (colors.length > 0)
        data.data.colors = colors;
      if (uvs.length > 0)
        data.data.uvs = [uvs];
      data.data.faces = faces;
      return data;
    },
    clone: function() {
      return new Geometry().copy(this);
    },
    copy: function(source) {
      var i,
          il,
          j,
          jl,
          k,
          kl;
      this.vertices = [];
      this.colors = [];
      this.faces = [];
      this.faceVertexUvs = [[]];
      this.morphTargets = [];
      this.morphNormals = [];
      this.skinWeights = [];
      this.skinIndices = [];
      this.lineDistances = [];
      this.boundingBox = null;
      this.boundingSphere = null;
      this.name = source.name;
      var vertices = source.vertices;
      for (i = 0, il = vertices.length; i < il; i++) {
        this.vertices.push(vertices[i].clone());
      }
      var colors = source.colors;
      for (i = 0, il = colors.length; i < il; i++) {
        this.colors.push(colors[i].clone());
      }
      var faces = source.faces;
      for (i = 0, il = faces.length; i < il; i++) {
        this.faces.push(faces[i].clone());
      }
      for (i = 0, il = source.faceVertexUvs.length; i < il; i++) {
        var faceVertexUvs = source.faceVertexUvs[i];
        if (this.faceVertexUvs[i] === undefined) {
          this.faceVertexUvs[i] = [];
        }
        for (j = 0, jl = faceVertexUvs.length; j < jl; j++) {
          var uvs = faceVertexUvs[j],
              uvsCopy = [];
          for (k = 0, kl = uvs.length; k < kl; k++) {
            var uv = uvs[k];
            uvsCopy.push(uv.clone());
          }
          this.faceVertexUvs[i].push(uvsCopy);
        }
      }
      var morphTargets = source.morphTargets;
      for (i = 0, il = morphTargets.length; i < il; i++) {
        var morphTarget = {};
        morphTarget.name = morphTargets[i].name;
        if (morphTargets[i].vertices !== undefined) {
          morphTarget.vertices = [];
          for (j = 0, jl = morphTargets[i].vertices.length; j < jl; j++) {
            morphTarget.vertices.push(morphTargets[i].vertices[j].clone());
          }
        }
        if (morphTargets[i].normals !== undefined) {
          morphTarget.normals = [];
          for (j = 0, jl = morphTargets[i].normals.length; j < jl; j++) {
            morphTarget.normals.push(morphTargets[i].normals[j].clone());
          }
        }
        this.morphTargets.push(morphTarget);
      }
      var morphNormals = source.morphNormals;
      for (i = 0, il = morphNormals.length; i < il; i++) {
        var morphNormal = {};
        if (morphNormals[i].vertexNormals !== undefined) {
          morphNormal.vertexNormals = [];
          for (j = 0, jl = morphNormals[i].vertexNormals.length; j < jl; j++) {
            var srcVertexNormal = morphNormals[i].vertexNormals[j];
            var destVertexNormal = {};
            destVertexNormal.a = srcVertexNormal.a.clone();
            destVertexNormal.b = srcVertexNormal.b.clone();
            destVertexNormal.c = srcVertexNormal.c.clone();
            morphNormal.vertexNormals.push(destVertexNormal);
          }
        }
        if (morphNormals[i].faceNormals !== undefined) {
          morphNormal.faceNormals = [];
          for (j = 0, jl = morphNormals[i].faceNormals.length; j < jl; j++) {
            morphNormal.faceNormals.push(morphNormals[i].faceNormals[j].clone());
          }
        }
        this.morphNormals.push(morphNormal);
      }
      var skinWeights = source.skinWeights;
      for (i = 0, il = skinWeights.length; i < il; i++) {
        this.skinWeights.push(skinWeights[i].clone());
      }
      var skinIndices = source.skinIndices;
      for (i = 0, il = skinIndices.length; i < il; i++) {
        this.skinIndices.push(skinIndices[i].clone());
      }
      var lineDistances = source.lineDistances;
      for (i = 0, il = lineDistances.length; i < il; i++) {
        this.lineDistances.push(lineDistances[i]);
      }
      var boundingBox = source.boundingBox;
      if (boundingBox !== null) {
        this.boundingBox = boundingBox.clone();
      }
      var boundingSphere = source.boundingSphere;
      if (boundingSphere !== null) {
        this.boundingSphere = boundingSphere.clone();
      }
      this.elementsNeedUpdate = source.elementsNeedUpdate;
      this.verticesNeedUpdate = source.verticesNeedUpdate;
      this.uvsNeedUpdate = source.uvsNeedUpdate;
      this.normalsNeedUpdate = source.normalsNeedUpdate;
      this.colorsNeedUpdate = source.colorsNeedUpdate;
      this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
      this.groupsNeedUpdate = source.groupsNeedUpdate;
      return this;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  });
  function BufferAttribute(array, itemSize, normalized) {
    if (Array.isArray(array)) {
      throw new TypeError('THREE.BufferAttribute: array should be a Typed Array.');
    }
    this.uuid = _Math.generateUUID();
    this.name = '';
    this.array = array;
    this.itemSize = itemSize;
    this.count = array !== undefined ? array.length / itemSize : 0;
    this.normalized = normalized === true;
    this.dynamic = false;
    this.updateRange = {
      offset: 0,
      count: -1
    };
    this.onUploadCallback = function() {};
    this.version = 0;
  }
  Object.defineProperty(BufferAttribute.prototype, 'needsUpdate', {set: function(value) {
      if (value === true)
        this.version++;
    }});
  Object.assign(BufferAttribute.prototype, {
    isBufferAttribute: true,
    setArray: function(array) {
      if (Array.isArray(array)) {
        throw new TypeError('THREE.BufferAttribute: array should be a Typed Array.');
      }
      this.count = array !== undefined ? array.length / this.itemSize : 0;
      this.array = array;
    },
    setDynamic: function(value) {
      this.dynamic = value;
      return this;
    },
    copy: function(source) {
      this.array = new source.array.constructor(source.array);
      this.itemSize = source.itemSize;
      this.count = source.count;
      this.normalized = source.normalized;
      this.dynamic = source.dynamic;
      return this;
    },
    copyAt: function(index1, attribute, index2) {
      index1 *= this.itemSize;
      index2 *= attribute.itemSize;
      for (var i = 0,
          l = this.itemSize; i < l; i++) {
        this.array[index1 + i] = attribute.array[index2 + i];
      }
      return this;
    },
    copyArray: function(array) {
      this.array.set(array);
      return this;
    },
    copyColorsArray: function(colors) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = colors.length; i < l; i++) {
        var color = colors[i];
        if (color === undefined) {
          console.warn('THREE.BufferAttribute.copyColorsArray(): color is undefined', i);
          color = new Color();
        }
        array[offset++] = color.r;
        array[offset++] = color.g;
        array[offset++] = color.b;
      }
      return this;
    },
    copyIndicesArray: function(indices) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = indices.length; i < l; i++) {
        var index = indices[i];
        array[offset++] = index.a;
        array[offset++] = index.b;
        array[offset++] = index.c;
      }
      return this;
    },
    copyVector2sArray: function(vectors) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = vectors.length; i < l; i++) {
        var vector = vectors[i];
        if (vector === undefined) {
          console.warn('THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i);
          vector = new Vector2();
        }
        array[offset++] = vector.x;
        array[offset++] = vector.y;
      }
      return this;
    },
    copyVector3sArray: function(vectors) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = vectors.length; i < l; i++) {
        var vector = vectors[i];
        if (vector === undefined) {
          console.warn('THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i);
          vector = new Vector3();
        }
        array[offset++] = vector.x;
        array[offset++] = vector.y;
        array[offset++] = vector.z;
      }
      return this;
    },
    copyVector4sArray: function(vectors) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = vectors.length; i < l; i++) {
        var vector = vectors[i];
        if (vector === undefined) {
          console.warn('THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i);
          vector = new Vector4();
        }
        array[offset++] = vector.x;
        array[offset++] = vector.y;
        array[offset++] = vector.z;
        array[offset++] = vector.w;
      }
      return this;
    },
    set: function(value, offset) {
      if (offset === undefined)
        offset = 0;
      this.array.set(value, offset);
      return this;
    },
    getX: function(index) {
      return this.array[index * this.itemSize];
    },
    setX: function(index, x) {
      this.array[index * this.itemSize] = x;
      return this;
    },
    getY: function(index) {
      return this.array[index * this.itemSize + 1];
    },
    setY: function(index, y) {
      this.array[index * this.itemSize + 1] = y;
      return this;
    },
    getZ: function(index) {
      return this.array[index * this.itemSize + 2];
    },
    setZ: function(index, z) {
      this.array[index * this.itemSize + 2] = z;
      return this;
    },
    getW: function(index) {
      return this.array[index * this.itemSize + 3];
    },
    setW: function(index, w) {
      this.array[index * this.itemSize + 3] = w;
      return this;
    },
    setXY: function(index, x, y) {
      index *= this.itemSize;
      this.array[index + 0] = x;
      this.array[index + 1] = y;
      return this;
    },
    setXYZ: function(index, x, y, z) {
      index *= this.itemSize;
      this.array[index + 0] = x;
      this.array[index + 1] = y;
      this.array[index + 2] = z;
      return this;
    },
    setXYZW: function(index, x, y, z, w) {
      index *= this.itemSize;
      this.array[index + 0] = x;
      this.array[index + 1] = y;
      this.array[index + 2] = z;
      this.array[index + 3] = w;
      return this;
    },
    onUpload: function(callback) {
      this.onUploadCallback = callback;
      return this;
    },
    clone: function() {
      return new this.constructor(this.array, this.itemSize).copy(this);
    }
  });
  function Int8BufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Int8Array(array), itemSize, normalized);
  }
  Int8BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
  function Uint8BufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Uint8Array(array), itemSize, normalized);
  }
  Uint8BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
  function Uint8ClampedBufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Uint8ClampedArray(array), itemSize, normalized);
  }
  Uint8ClampedBufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
  function Int16BufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Int16Array(array), itemSize, normalized);
  }
  Int16BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
  function Uint16BufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Uint16Array(array), itemSize, normalized);
  }
  Uint16BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
  function Int32BufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Int32Array(array), itemSize, normalized);
  }
  Int32BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
  function Uint32BufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Uint32Array(array), itemSize, normalized);
  }
  Uint32BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
  function Float32BufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Float32Array(array), itemSize, normalized);
  }
  Float32BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
  function Float64BufferAttribute(array, itemSize, normalized) {
    BufferAttribute.call(this, new Float64Array(array), itemSize, normalized);
  }
  Float64BufferAttribute.prototype = Object.create(BufferAttribute.prototype);
  Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
  function DirectGeometry() {
    this.indices = [];
    this.vertices = [];
    this.normals = [];
    this.colors = [];
    this.uvs = [];
    this.uvs2 = [];
    this.groups = [];
    this.morphTargets = {};
    this.skinWeights = [];
    this.skinIndices = [];
    this.boundingBox = null;
    this.boundingSphere = null;
    this.verticesNeedUpdate = false;
    this.normalsNeedUpdate = false;
    this.colorsNeedUpdate = false;
    this.uvsNeedUpdate = false;
    this.groupsNeedUpdate = false;
  }
  Object.assign(DirectGeometry.prototype, {
    computeGroups: function(geometry) {
      var group;
      var groups = [];
      var materialIndex = undefined;
      var faces = geometry.faces;
      for (var i = 0; i < faces.length; i++) {
        var face = faces[i];
        if (face.materialIndex !== materialIndex) {
          materialIndex = face.materialIndex;
          if (group !== undefined) {
            group.count = (i * 3) - group.start;
            groups.push(group);
          }
          group = {
            start: i * 3,
            materialIndex: materialIndex
          };
        }
      }
      if (group !== undefined) {
        group.count = (i * 3) - group.start;
        groups.push(group);
      }
      this.groups = groups;
    },
    fromGeometry: function(geometry) {
      var faces = geometry.faces;
      var vertices = geometry.vertices;
      var faceVertexUvs = geometry.faceVertexUvs;
      var hasFaceVertexUv = faceVertexUvs[0] && faceVertexUvs[0].length > 0;
      var hasFaceVertexUv2 = faceVertexUvs[1] && faceVertexUvs[1].length > 0;
      var morphTargets = geometry.morphTargets;
      var morphTargetsLength = morphTargets.length;
      var morphTargetsPosition;
      if (morphTargetsLength > 0) {
        morphTargetsPosition = [];
        for (var i = 0; i < morphTargetsLength; i++) {
          morphTargetsPosition[i] = [];
        }
        this.morphTargets.position = morphTargetsPosition;
      }
      var morphNormals = geometry.morphNormals;
      var morphNormalsLength = morphNormals.length;
      var morphTargetsNormal;
      if (morphNormalsLength > 0) {
        morphTargetsNormal = [];
        for (var i = 0; i < morphNormalsLength; i++) {
          morphTargetsNormal[i] = [];
        }
        this.morphTargets.normal = morphTargetsNormal;
      }
      var skinIndices = geometry.skinIndices;
      var skinWeights = geometry.skinWeights;
      var hasSkinIndices = skinIndices.length === vertices.length;
      var hasSkinWeights = skinWeights.length === vertices.length;
      for (var i = 0; i < faces.length; i++) {
        var face = faces[i];
        this.vertices.push(vertices[face.a], vertices[face.b], vertices[face.c]);
        var vertexNormals = face.vertexNormals;
        if (vertexNormals.length === 3) {
          this.normals.push(vertexNormals[0], vertexNormals[1], vertexNormals[2]);
        } else {
          var normal = face.normal;
          this.normals.push(normal, normal, normal);
        }
        var vertexColors = face.vertexColors;
        if (vertexColors.length === 3) {
          this.colors.push(vertexColors[0], vertexColors[1], vertexColors[2]);
        } else {
          var color = face.color;
          this.colors.push(color, color, color);
        }
        if (hasFaceVertexUv === true) {
          var vertexUvs = faceVertexUvs[0][i];
          if (vertexUvs !== undefined) {
            this.uvs.push(vertexUvs[0], vertexUvs[1], vertexUvs[2]);
          } else {
            console.warn('THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i);
            this.uvs.push(new Vector2(), new Vector2(), new Vector2());
          }
        }
        if (hasFaceVertexUv2 === true) {
          var vertexUvs = faceVertexUvs[1][i];
          if (vertexUvs !== undefined) {
            this.uvs2.push(vertexUvs[0], vertexUvs[1], vertexUvs[2]);
          } else {
            console.warn('THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i);
            this.uvs2.push(new Vector2(), new Vector2(), new Vector2());
          }
        }
        for (var j = 0; j < morphTargetsLength; j++) {
          var morphTarget = morphTargets[j].vertices;
          morphTargetsPosition[j].push(morphTarget[face.a], morphTarget[face.b], morphTarget[face.c]);
        }
        for (var j = 0; j < morphNormalsLength; j++) {
          var morphNormal = morphNormals[j].vertexNormals[i];
          morphTargetsNormal[j].push(morphNormal.a, morphNormal.b, morphNormal.c);
        }
        if (hasSkinIndices) {
          this.skinIndices.push(skinIndices[face.a], skinIndices[face.b], skinIndices[face.c]);
        }
        if (hasSkinWeights) {
          this.skinWeights.push(skinWeights[face.a], skinWeights[face.b], skinWeights[face.c]);
        }
      }
      this.computeGroups(geometry);
      this.verticesNeedUpdate = geometry.verticesNeedUpdate;
      this.normalsNeedUpdate = geometry.normalsNeedUpdate;
      this.colorsNeedUpdate = geometry.colorsNeedUpdate;
      this.uvsNeedUpdate = geometry.uvsNeedUpdate;
      this.groupsNeedUpdate = geometry.groupsNeedUpdate;
      return this;
    }
  });
  function arrayMax(array) {
    if (array.length === 0)
      return -Infinity;
    var max = array[0];
    for (var i = 1,
        l = array.length; i < l; ++i) {
      if (array[i] > max)
        max = array[i];
    }
    return max;
  }
  var bufferGeometryId = 1;
  function BufferGeometry() {
    Object.defineProperty(this, 'id', {value: bufferGeometryId += 2});
    this.uuid = _Math.generateUUID();
    this.name = '';
    this.type = 'BufferGeometry';
    this.index = null;
    this.attributes = {};
    this.morphAttributes = {};
    this.groups = [];
    this.boundingBox = null;
    this.boundingSphere = null;
    this.drawRange = {
      start: 0,
      count: Infinity
    };
  }
  Object.assign(BufferGeometry.prototype, EventDispatcher.prototype, {
    isBufferGeometry: true,
    getIndex: function() {
      return this.index;
    },
    setIndex: function(index) {
      if (Array.isArray(index)) {
        this.index = new (arrayMax(index) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute)(index, 1);
      } else {
        this.index = index;
      }
    },
    addAttribute: function(name, attribute) {
      if (!(attribute && attribute.isBufferAttribute) && !(attribute && attribute.isInterleavedBufferAttribute)) {
        console.warn('THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).');
        this.addAttribute(name, new BufferAttribute(arguments[1], arguments[2]));
        return;
      }
      if (name === 'index') {
        console.warn('THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.');
        this.setIndex(attribute);
        return;
      }
      this.attributes[name] = attribute;
      return this;
    },
    getAttribute: function(name) {
      return this.attributes[name];
    },
    removeAttribute: function(name) {
      delete this.attributes[name];
      return this;
    },
    addGroup: function(start, count, materialIndex) {
      this.groups.push({
        start: start,
        count: count,
        materialIndex: materialIndex !== undefined ? materialIndex : 0
      });
    },
    clearGroups: function() {
      this.groups = [];
    },
    setDrawRange: function(start, count) {
      this.drawRange.start = start;
      this.drawRange.count = count;
    },
    applyMatrix: function(matrix) {
      var position = this.attributes.position;
      if (position !== undefined) {
        matrix.applyToBufferAttribute(position);
        position.needsUpdate = true;
      }
      var normal = this.attributes.normal;
      if (normal !== undefined) {
        var normalMatrix = new Matrix3().getNormalMatrix(matrix);
        normalMatrix.applyToBufferAttribute(normal);
        normal.needsUpdate = true;
      }
      if (this.boundingBox !== null) {
        this.computeBoundingBox();
      }
      if (this.boundingSphere !== null) {
        this.computeBoundingSphere();
      }
      return this;
    },
    rotateX: function() {
      var m1 = new Matrix4();
      return function rotateX(angle) {
        m1.makeRotationX(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    rotateY: function() {
      var m1 = new Matrix4();
      return function rotateY(angle) {
        m1.makeRotationY(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    rotateZ: function() {
      var m1 = new Matrix4();
      return function rotateZ(angle) {
        m1.makeRotationZ(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    translate: function() {
      var m1 = new Matrix4();
      return function translate(x, y, z) {
        m1.makeTranslation(x, y, z);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    scale: function() {
      var m1 = new Matrix4();
      return function scale(x, y, z) {
        m1.makeScale(x, y, z);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    lookAt: function() {
      var obj = new Object3D();
      return function lookAt(vector) {
        obj.lookAt(vector);
        obj.updateMatrix();
        this.applyMatrix(obj.matrix);
      };
    }(),
    center: function() {
      this.computeBoundingBox();
      var offset = this.boundingBox.getCenter().negate();
      this.translate(offset.x, offset.y, offset.z);
      return offset;
    },
    setFromObject: function(object) {
      var geometry = object.geometry;
      if (object.isPoints || object.isLine) {
        var positions = new Float32BufferAttribute(geometry.vertices.length * 3, 3);
        var colors = new Float32BufferAttribute(geometry.colors.length * 3, 3);
        this.addAttribute('position', positions.copyVector3sArray(geometry.vertices));
        this.addAttribute('color', colors.copyColorsArray(geometry.colors));
        if (geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length) {
          var lineDistances = new Float32BufferAttribute(geometry.lineDistances.length, 1);
          this.addAttribute('lineDistance', lineDistances.copyArray(geometry.lineDistances));
        }
        if (geometry.boundingSphere !== null) {
          this.boundingSphere = geometry.boundingSphere.clone();
        }
        if (geometry.boundingBox !== null) {
          this.boundingBox = geometry.boundingBox.clone();
        }
      } else if (object.isMesh) {
        if (geometry && geometry.isGeometry) {
          this.fromGeometry(geometry);
        }
      }
      return this;
    },
    setFromPoints: function(points) {
      var position = [];
      for (var i = 0,
          l = points.length; i < l; i++) {
        var point = points[i];
        position.push(point.x, point.y, point.z || 0);
      }
      this.addAttribute('position', new Float32BufferAttribute(position, 3));
      return this;
    },
    updateFromObject: function(object) {
      var geometry = object.geometry;
      if (object.isMesh) {
        var direct = geometry.__directGeometry;
        if (geometry.elementsNeedUpdate === true) {
          direct = undefined;
          geometry.elementsNeedUpdate = false;
        }
        if (direct === undefined) {
          return this.fromGeometry(geometry);
        }
        direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
        direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
        direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
        direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
        direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
        geometry.verticesNeedUpdate = false;
        geometry.normalsNeedUpdate = false;
        geometry.colorsNeedUpdate = false;
        geometry.uvsNeedUpdate = false;
        geometry.groupsNeedUpdate = false;
        geometry = direct;
      }
      var attribute;
      if (geometry.verticesNeedUpdate === true) {
        attribute = this.attributes.position;
        if (attribute !== undefined) {
          attribute.copyVector3sArray(geometry.vertices);
          attribute.needsUpdate = true;
        }
        geometry.verticesNeedUpdate = false;
      }
      if (geometry.normalsNeedUpdate === true) {
        attribute = this.attributes.normal;
        if (attribute !== undefined) {
          attribute.copyVector3sArray(geometry.normals);
          attribute.needsUpdate = true;
        }
        geometry.normalsNeedUpdate = false;
      }
      if (geometry.colorsNeedUpdate === true) {
        attribute = this.attributes.color;
        if (attribute !== undefined) {
          attribute.copyColorsArray(geometry.colors);
          attribute.needsUpdate = true;
        }
        geometry.colorsNeedUpdate = false;
      }
      if (geometry.uvsNeedUpdate) {
        attribute = this.attributes.uv;
        if (attribute !== undefined) {
          attribute.copyVector2sArray(geometry.uvs);
          attribute.needsUpdate = true;
        }
        geometry.uvsNeedUpdate = false;
      }
      if (geometry.lineDistancesNeedUpdate) {
        attribute = this.attributes.lineDistance;
        if (attribute !== undefined) {
          attribute.copyArray(geometry.lineDistances);
          attribute.needsUpdate = true;
        }
        geometry.lineDistancesNeedUpdate = false;
      }
      if (geometry.groupsNeedUpdate) {
        geometry.computeGroups(object.geometry);
        this.groups = geometry.groups;
        geometry.groupsNeedUpdate = false;
      }
      return this;
    },
    fromGeometry: function(geometry) {
      geometry.__directGeometry = new DirectGeometry().fromGeometry(geometry);
      return this.fromDirectGeometry(geometry.__directGeometry);
    },
    fromDirectGeometry: function(geometry) {
      var positions = new Float32Array(geometry.vertices.length * 3);
      this.addAttribute('position', new BufferAttribute(positions, 3).copyVector3sArray(geometry.vertices));
      if (geometry.normals.length > 0) {
        var normals = new Float32Array(geometry.normals.length * 3);
        this.addAttribute('normal', new BufferAttribute(normals, 3).copyVector3sArray(geometry.normals));
      }
      if (geometry.colors.length > 0) {
        var colors = new Float32Array(geometry.colors.length * 3);
        this.addAttribute('color', new BufferAttribute(colors, 3).copyColorsArray(geometry.colors));
      }
      if (geometry.uvs.length > 0) {
        var uvs = new Float32Array(geometry.uvs.length * 2);
        this.addAttribute('uv', new BufferAttribute(uvs, 2).copyVector2sArray(geometry.uvs));
      }
      if (geometry.uvs2.length > 0) {
        var uvs2 = new Float32Array(geometry.uvs2.length * 2);
        this.addAttribute('uv2', new BufferAttribute(uvs2, 2).copyVector2sArray(geometry.uvs2));
      }
      if (geometry.indices.length > 0) {
        var TypeArray = arrayMax(geometry.indices) > 65535 ? Uint32Array : Uint16Array;
        var indices = new TypeArray(geometry.indices.length * 3);
        this.setIndex(new BufferAttribute(indices, 1).copyIndicesArray(geometry.indices));
      }
      this.groups = geometry.groups;
      for (var name in geometry.morphTargets) {
        var array = [];
        var morphTargets = geometry.morphTargets[name];
        for (var i = 0,
            l = morphTargets.length; i < l; i++) {
          var morphTarget = morphTargets[i];
          var attribute = new Float32BufferAttribute(morphTarget.length * 3, 3);
          array.push(attribute.copyVector3sArray(morphTarget));
        }
        this.morphAttributes[name] = array;
      }
      if (geometry.skinIndices.length > 0) {
        var skinIndices = new Float32BufferAttribute(geometry.skinIndices.length * 4, 4);
        this.addAttribute('skinIndex', skinIndices.copyVector4sArray(geometry.skinIndices));
      }
      if (geometry.skinWeights.length > 0) {
        var skinWeights = new Float32BufferAttribute(geometry.skinWeights.length * 4, 4);
        this.addAttribute('skinWeight', skinWeights.copyVector4sArray(geometry.skinWeights));
      }
      if (geometry.boundingSphere !== null) {
        this.boundingSphere = geometry.boundingSphere.clone();
      }
      if (geometry.boundingBox !== null) {
        this.boundingBox = geometry.boundingBox.clone();
      }
      return this;
    },
    computeBoundingBox: function() {
      if (this.boundingBox === null) {
        this.boundingBox = new Box3();
      }
      var position = this.attributes.position;
      if (position !== undefined) {
        this.boundingBox.setFromBufferAttribute(position);
      } else {
        this.boundingBox.makeEmpty();
      }
      if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) {
        console.error('THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this);
      }
    },
    computeBoundingSphere: function() {
      var box = new Box3();
      var vector = new Vector3();
      return function computeBoundingSphere() {
        if (this.boundingSphere === null) {
          this.boundingSphere = new Sphere();
        }
        var position = this.attributes.position;
        if (position) {
          var center = this.boundingSphere.center;
          box.setFromBufferAttribute(position);
          box.getCenter(center);
          var maxRadiusSq = 0;
          for (var i = 0,
              il = position.count; i < il; i++) {
            vector.x = position.getX(i);
            vector.y = position.getY(i);
            vector.z = position.getZ(i);
            maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector));
          }
          this.boundingSphere.radius = Math.sqrt(maxRadiusSq);
          if (isNaN(this.boundingSphere.radius)) {
            console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this);
          }
        }
      };
    }(),
    computeFaceNormals: function() {},
    computeVertexNormals: function() {
      var index = this.index;
      var attributes = this.attributes;
      var groups = this.groups;
      if (attributes.position) {
        var positions = attributes.position.array;
        if (attributes.normal === undefined) {
          this.addAttribute('normal', new BufferAttribute(new Float32Array(positions.length), 3));
        } else {
          var array = attributes.normal.array;
          for (var i = 0,
              il = array.length; i < il; i++) {
            array[i] = 0;
          }
        }
        var normals = attributes.normal.array;
        var vA,
            vB,
            vC;
        var pA = new Vector3(),
            pB = new Vector3(),
            pC = new Vector3();
        var cb = new Vector3(),
            ab = new Vector3();
        if (index) {
          var indices = index.array;
          if (groups.length === 0) {
            this.addGroup(0, indices.length);
          }
          for (var j = 0,
              jl = groups.length; j < jl; ++j) {
            var group = groups[j];
            var start = group.start;
            var count = group.count;
            for (var i = start,
                il = start + count; i < il; i += 3) {
              vA = indices[i + 0] * 3;
              vB = indices[i + 1] * 3;
              vC = indices[i + 2] * 3;
              pA.fromArray(positions, vA);
              pB.fromArray(positions, vB);
              pC.fromArray(positions, vC);
              cb.subVectors(pC, pB);
              ab.subVectors(pA, pB);
              cb.cross(ab);
              normals[vA] += cb.x;
              normals[vA + 1] += cb.y;
              normals[vA + 2] += cb.z;
              normals[vB] += cb.x;
              normals[vB + 1] += cb.y;
              normals[vB + 2] += cb.z;
              normals[vC] += cb.x;
              normals[vC + 1] += cb.y;
              normals[vC + 2] += cb.z;
            }
          }
        } else {
          for (var i = 0,
              il = positions.length; i < il; i += 9) {
            pA.fromArray(positions, i);
            pB.fromArray(positions, i + 3);
            pC.fromArray(positions, i + 6);
            cb.subVectors(pC, pB);
            ab.subVectors(pA, pB);
            cb.cross(ab);
            normals[i] = cb.x;
            normals[i + 1] = cb.y;
            normals[i + 2] = cb.z;
            normals[i + 3] = cb.x;
            normals[i + 4] = cb.y;
            normals[i + 5] = cb.z;
            normals[i + 6] = cb.x;
            normals[i + 7] = cb.y;
            normals[i + 8] = cb.z;
          }
        }
        this.normalizeNormals();
        attributes.normal.needsUpdate = true;
      }
    },
    merge: function(geometry, offset) {
      if (!(geometry && geometry.isBufferGeometry)) {
        console.error('THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry);
        return;
      }
      if (offset === undefined)
        offset = 0;
      var attributes = this.attributes;
      for (var key in attributes) {
        if (geometry.attributes[key] === undefined)
          continue;
        var attribute1 = attributes[key];
        var attributeArray1 = attribute1.array;
        var attribute2 = geometry.attributes[key];
        var attributeArray2 = attribute2.array;
        var attributeSize = attribute2.itemSize;
        for (var i = 0,
            j = attributeSize * offset; i < attributeArray2.length; i++, j++) {
          attributeArray1[j] = attributeArray2[i];
        }
      }
      return this;
    },
    normalizeNormals: function() {
      var vector = new Vector3();
      return function normalizeNormals() {
        var normals = this.attributes.normal;
        for (var i = 0,
            il = normals.count; i < il; i++) {
          vector.x = normals.getX(i);
          vector.y = normals.getY(i);
          vector.z = normals.getZ(i);
          vector.normalize();
          normals.setXYZ(i, vector.x, vector.y, vector.z);
        }
      };
    }(),
    toNonIndexed: function() {
      if (this.index === null) {
        console.warn('THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.');
        return this;
      }
      var geometry2 = new BufferGeometry();
      var indices = this.index.array;
      var attributes = this.attributes;
      for (var name in attributes) {
        var attribute = attributes[name];
        var array = attribute.array;
        var itemSize = attribute.itemSize;
        var array2 = new array.constructor(indices.length * itemSize);
        var index = 0,
            index2 = 0;
        for (var i = 0,
            l = indices.length; i < l; i++) {
          index = indices[i] * itemSize;
          for (var j = 0; j < itemSize; j++) {
            array2[index2++] = array[index++];
          }
        }
        geometry2.addAttribute(name, new BufferAttribute(array2, itemSize));
      }
      return geometry2;
    },
    toJSON: function() {
      var data = {metadata: {
          version: 4.5,
          type: 'BufferGeometry',
          generator: 'BufferGeometry.toJSON'
        }};
      data.uuid = this.uuid;
      data.type = this.type;
      if (this.name !== '')
        data.name = this.name;
      if (this.parameters !== undefined) {
        var parameters = this.parameters;
        for (var key in parameters) {
          if (parameters[key] !== undefined)
            data[key] = parameters[key];
        }
        return data;
      }
      data.data = {attributes: {}};
      var index = this.index;
      if (index !== null) {
        var array = Array.prototype.slice.call(index.array);
        data.data.index = {
          type: index.array.constructor.name,
          array: array
        };
      }
      var attributes = this.attributes;
      for (var key in attributes) {
        var attribute = attributes[key];
        var array = Array.prototype.slice.call(attribute.array);
        data.data.attributes[key] = {
          itemSize: attribute.itemSize,
          type: attribute.array.constructor.name,
          array: array,
          normalized: attribute.normalized
        };
      }
      var groups = this.groups;
      if (groups.length > 0) {
        data.data.groups = JSON.parse(JSON.stringify(groups));
      }
      var boundingSphere = this.boundingSphere;
      if (boundingSphere !== null) {
        data.data.boundingSphere = {
          center: boundingSphere.center.toArray(),
          radius: boundingSphere.radius
        };
      }
      return data;
    },
    clone: function() {
      return new BufferGeometry().copy(this);
    },
    copy: function(source) {
      var name,
          i,
          l;
      this.index = null;
      this.attributes = {};
      this.morphAttributes = {};
      this.groups = [];
      this.boundingBox = null;
      this.boundingSphere = null;
      this.name = source.name;
      var index = source.index;
      if (index !== null) {
        this.setIndex(index.clone());
      }
      var attributes = source.attributes;
      for (name in attributes) {
        var attribute = attributes[name];
        this.addAttribute(name, attribute.clone());
      }
      var morphAttributes = source.morphAttributes;
      for (name in morphAttributes) {
        var array = [];
        var morphAttribute = morphAttributes[name];
        for (i = 0, l = morphAttribute.length; i < l; i++) {
          array.push(morphAttribute[i].clone());
        }
        this.morphAttributes[name] = array;
      }
      var groups = source.groups;
      for (i = 0, l = groups.length; i < l; i++) {
        var group = groups[i];
        this.addGroup(group.start, group.count, group.materialIndex);
      }
      var boundingBox = source.boundingBox;
      if (boundingBox !== null) {
        this.boundingBox = boundingBox.clone();
      }
      var boundingSphere = source.boundingSphere;
      if (boundingSphere !== null) {
        this.boundingSphere = boundingSphere.clone();
      }
      this.drawRange.start = source.drawRange.start;
      this.drawRange.count = source.drawRange.count;
      return this;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  });
  function BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments) {
    Geometry.call(this);
    this.type = 'BoxGeometry';
    this.parameters = {
      width: width,
      height: height,
      depth: depth,
      widthSegments: widthSegments,
      heightSegments: heightSegments,
      depthSegments: depthSegments
    };
    this.fromBufferGeometry(new BoxBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments));
    this.mergeVertices();
  }
  BoxGeometry.prototype = Object.create(Geometry.prototype);
  BoxGeometry.prototype.constructor = BoxGeometry;
  function BoxBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments) {
    BufferGeometry.call(this);
    this.type = 'BoxBufferGeometry';
    this.parameters = {
      width: width,
      height: height,
      depth: depth,
      widthSegments: widthSegments,
      heightSegments: heightSegments,
      depthSegments: depthSegments
    };
    var scope = this;
    width = width || 1;
    height = height || 1;
    depth = depth || 1;
    widthSegments = Math.floor(widthSegments) || 1;
    heightSegments = Math.floor(heightSegments) || 1;
    depthSegments = Math.floor(depthSegments) || 1;
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    var numberOfVertices = 0;
    var groupStart = 0;
    buildPlane('z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0);
    buildPlane('z', 'y', 'x', 1, -1, depth, height, -width, depthSegments, heightSegments, 1);
    buildPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2);
    buildPlane('x', 'z', 'y', 1, -1, width, depth, -height, widthSegments, depthSegments, 3);
    buildPlane('x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4);
    buildPlane('x', 'y', 'z', -1, -1, width, height, -depth, widthSegments, heightSegments, 5);
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
    function buildPlane(u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex) {
      var segmentWidth = width / gridX;
      var segmentHeight = height / gridY;
      var widthHalf = width / 2;
      var heightHalf = height / 2;
      var depthHalf = depth / 2;
      var gridX1 = gridX + 1;
      var gridY1 = gridY + 1;
      var vertexCounter = 0;
      var groupCount = 0;
      var ix,
          iy;
      var vector = new Vector3();
      for (iy = 0; iy < gridY1; iy++) {
        var y = iy * segmentHeight - heightHalf;
        for (ix = 0; ix < gridX1; ix++) {
          var x = ix * segmentWidth - widthHalf;
          vector[u] = x * udir;
          vector[v] = y * vdir;
          vector[w] = depthHalf;
          vertices.push(vector.x, vector.y, vector.z);
          vector[u] = 0;
          vector[v] = 0;
          vector[w] = depth > 0 ? 1 : -1;
          normals.push(vector.x, vector.y, vector.z);
          uvs.push(ix / gridX);
          uvs.push(1 - (iy / gridY));
          vertexCounter += 1;
        }
      }
      for (iy = 0; iy < gridY; iy++) {
        for (ix = 0; ix < gridX; ix++) {
          var a = numberOfVertices + ix + gridX1 * iy;
          var b = numberOfVertices + ix + gridX1 * (iy + 1);
          var c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
          var d = numberOfVertices + (ix + 1) + gridX1 * iy;
          indices.push(a, b, d);
          indices.push(b, c, d);
          groupCount += 6;
        }
      }
      scope.addGroup(groupStart, groupCount, materialIndex);
      groupStart += groupCount;
      numberOfVertices += vertexCounter;
    }
  }
  BoxBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
  function PlaneGeometry(width, height, widthSegments, heightSegments) {
    Geometry.call(this);
    this.type = 'PlaneGeometry';
    this.parameters = {
      width: width,
      height: height,
      widthSegments: widthSegments,
      heightSegments: heightSegments
    };
    this.fromBufferGeometry(new PlaneBufferGeometry(width, height, widthSegments, heightSegments));
    this.mergeVertices();
  }
  PlaneGeometry.prototype = Object.create(Geometry.prototype);
  PlaneGeometry.prototype.constructor = PlaneGeometry;
  function PlaneBufferGeometry(width, height, widthSegments, heightSegments) {
    BufferGeometry.call(this);
    this.type = 'PlaneBufferGeometry';
    this.parameters = {
      width: width,
      height: height,
      widthSegments: widthSegments,
      heightSegments: heightSegments
    };
    width = width || 1;
    height = height || 1;
    var width_half = width / 2;
    var height_half = height / 2;
    var gridX = Math.floor(widthSegments) || 1;
    var gridY = Math.floor(heightSegments) || 1;
    var gridX1 = gridX + 1;
    var gridY1 = gridY + 1;
    var segment_width = width / gridX;
    var segment_height = height / gridY;
    var ix,
        iy;
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    for (iy = 0; iy < gridY1; iy++) {
      var y = iy * segment_height - height_half;
      for (ix = 0; ix < gridX1; ix++) {
        var x = ix * segment_width - width_half;
        vertices.push(x, -y, 0);
        normals.push(0, 0, 1);
        uvs.push(ix / gridX);
        uvs.push(1 - (iy / gridY));
      }
    }
    for (iy = 0; iy < gridY; iy++) {
      for (ix = 0; ix < gridX; ix++) {
        var a = ix + gridX1 * iy;
        var b = ix + gridX1 * (iy + 1);
        var c = (ix + 1) + gridX1 * (iy + 1);
        var d = (ix + 1) + gridX1 * iy;
        indices.push(a, b, d);
        indices.push(b, c, d);
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
  }
  PlaneBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
  function MeshBasicMaterial(parameters) {
    Material.call(this);
    this.type = 'MeshBasicMaterial';
    this.color = new Color(0xffffff);
    this.map = null;
    this.lightMap = null;
    this.lightMapIntensity = 1.0;
    this.aoMap = null;
    this.aoMapIntensity = 1.0;
    this.specularMap = null;
    this.alphaMap = null;
    this.envMap = null;
    this.combine = MultiplyOperation;
    this.reflectivity = 1;
    this.refractionRatio = 0.98;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.skinning = false;
    this.morphTargets = false;
    this.lights = false;
    this.setValues(parameters);
  }
  MeshBasicMaterial.prototype = Object.create(Material.prototype);
  MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
  MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
  MeshBasicMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.map = source.map;
    this.lightMap = source.lightMap;
    this.lightMapIntensity = source.lightMapIntensity;
    this.aoMap = source.aoMap;
    this.aoMapIntensity = source.aoMapIntensity;
    this.specularMap = source.specularMap;
    this.alphaMap = source.alphaMap;
    this.envMap = source.envMap;
    this.combine = source.combine;
    this.reflectivity = source.reflectivity;
    this.refractionRatio = source.refractionRatio;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.wireframeLinecap = source.wireframeLinecap;
    this.wireframeLinejoin = source.wireframeLinejoin;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    return this;
  };
  function ShaderMaterial(parameters) {
    Material.call(this);
    this.type = 'ShaderMaterial';
    this.defines = {};
    this.uniforms = {};
    this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
    this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
    this.linewidth = 1;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.fog = false;
    this.lights = false;
    this.clipping = false;
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.extensions = {
      derivatives: false,
      fragDepth: false,
      drawBuffers: false,
      shaderTextureLOD: false
    };
    this.defaultAttributeValues = {
      'color': [1, 1, 1],
      'uv': [0, 0],
      'uv2': [0, 0]
    };
    this.index0AttributeName = undefined;
    if (parameters !== undefined) {
      if (parameters.attributes !== undefined) {
        console.error('THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.');
      }
      this.setValues(parameters);
    }
  }
  ShaderMaterial.prototype = Object.create(Material.prototype);
  ShaderMaterial.prototype.constructor = ShaderMaterial;
  ShaderMaterial.prototype.isShaderMaterial = true;
  ShaderMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.fragmentShader = source.fragmentShader;
    this.vertexShader = source.vertexShader;
    this.uniforms = UniformsUtils.clone(source.uniforms);
    this.defines = source.defines;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.lights = source.lights;
    this.clipping = source.clipping;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    this.extensions = source.extensions;
    return this;
  };
  ShaderMaterial.prototype.toJSON = function(meta) {
    var data = Material.prototype.toJSON.call(this, meta);
    data.uniforms = this.uniforms;
    data.vertexShader = this.vertexShader;
    data.fragmentShader = this.fragmentShader;
    return data;
  };
  function Ray(origin, direction) {
    this.origin = (origin !== undefined) ? origin : new Vector3();
    this.direction = (direction !== undefined) ? direction : new Vector3();
  }
  Object.assign(Ray.prototype, {
    set: function(origin, direction) {
      this.origin.copy(origin);
      this.direction.copy(direction);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(ray) {
      this.origin.copy(ray.origin);
      this.direction.copy(ray.direction);
      return this;
    },
    at: function(t, optionalTarget) {
      var result = optionalTarget || new Vector3();
      return result.copy(this.direction).multiplyScalar(t).add(this.origin);
    },
    lookAt: function(v) {
      this.direction.copy(v).sub(this.origin).normalize();
      return this;
    },
    recast: function() {
      var v1 = new Vector3();
      return function recast(t) {
        this.origin.copy(this.at(t, v1));
        return this;
      };
    }(),
    closestPointToPoint: function(point, optionalTarget) {
      var result = optionalTarget || new Vector3();
      result.subVectors(point, this.origin);
      var directionDistance = result.dot(this.direction);
      if (directionDistance < 0) {
        return result.copy(this.origin);
      }
      return result.copy(this.direction).multiplyScalar(directionDistance).add(this.origin);
    },
    distanceToPoint: function(point) {
      return Math.sqrt(this.distanceSqToPoint(point));
    },
    distanceSqToPoint: function() {
      var v1 = new Vector3();
      return function distanceSqToPoint(point) {
        var directionDistance = v1.subVectors(point, this.origin).dot(this.direction);
        if (directionDistance < 0) {
          return this.origin.distanceToSquared(point);
        }
        v1.copy(this.direction).multiplyScalar(directionDistance).add(this.origin);
        return v1.distanceToSquared(point);
      };
    }(),
    distanceSqToSegment: function() {
      var segCenter = new Vector3();
      var segDir = new Vector3();
      var diff = new Vector3();
      return function distanceSqToSegment(v0, v1, optionalPointOnRay, optionalPointOnSegment) {
        segCenter.copy(v0).add(v1).multiplyScalar(0.5);
        segDir.copy(v1).sub(v0).normalize();
        diff.copy(this.origin).sub(segCenter);
        var segExtent = v0.distanceTo(v1) * 0.5;
        var a01 = -this.direction.dot(segDir);
        var b0 = diff.dot(this.direction);
        var b1 = -diff.dot(segDir);
        var c = diff.lengthSq();
        var det = Math.abs(1 - a01 * a01);
        var s0,
            s1,
            sqrDist,
            extDet;
        if (det > 0) {
          s0 = a01 * b1 - b0;
          s1 = a01 * b0 - b1;
          extDet = segExtent * det;
          if (s0 >= 0) {
            if (s1 >= -extDet) {
              if (s1 <= extDet) {
                var invDet = 1 / det;
                s0 *= invDet;
                s1 *= invDet;
                sqrDist = s0 * (s0 + a01 * s1 + 2 * b0) + s1 * (a01 * s0 + s1 + 2 * b1) + c;
              } else {
                s1 = segExtent;
                s0 = Math.max(0, -(a01 * s1 + b0));
                sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
              }
            } else {
              s1 = -segExtent;
              s0 = Math.max(0, -(a01 * s1 + b0));
              sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
            }
          } else {
            if (s1 <= -extDet) {
              s0 = Math.max(0, -(-a01 * segExtent + b0));
              s1 = (s0 > 0) ? -segExtent : Math.min(Math.max(-segExtent, -b1), segExtent);
              sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
            } else if (s1 <= extDet) {
              s0 = 0;
              s1 = Math.min(Math.max(-segExtent, -b1), segExtent);
              sqrDist = s1 * (s1 + 2 * b1) + c;
            } else {
              s0 = Math.max(0, -(a01 * segExtent + b0));
              s1 = (s0 > 0) ? segExtent : Math.min(Math.max(-segExtent, -b1), segExtent);
              sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
            }
          }
        } else {
          s1 = (a01 > 0) ? -segExtent : segExtent;
          s0 = Math.max(0, -(a01 * s1 + b0));
          sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
        }
        if (optionalPointOnRay) {
          optionalPointOnRay.copy(this.direction).multiplyScalar(s0).add(this.origin);
        }
        if (optionalPointOnSegment) {
          optionalPointOnSegment.copy(segDir).multiplyScalar(s1).add(segCenter);
        }
        return sqrDist;
      };
    }(),
    intersectSphere: function() {
      var v1 = new Vector3();
      return function intersectSphere(sphere, optionalTarget) {
        v1.subVectors(sphere.center, this.origin);
        var tca = v1.dot(this.direction);
        var d2 = v1.dot(v1) - tca * tca;
        var radius2 = sphere.radius * sphere.radius;
        if (d2 > radius2)
          return null;
        var thc = Math.sqrt(radius2 - d2);
        var t0 = tca - thc;
        var t1 = tca + thc;
        if (t0 < 0 && t1 < 0)
          return null;
        if (t0 < 0)
          return this.at(t1, optionalTarget);
        return this.at(t0, optionalTarget);
      };
    }(),
    intersectsSphere: function(sphere) {
      return this.distanceToPoint(sphere.center) <= sphere.radius;
    },
    distanceToPlane: function(plane) {
      var denominator = plane.normal.dot(this.direction);
      if (denominator === 0) {
        if (plane.distanceToPoint(this.origin) === 0) {
          return 0;
        }
        return null;
      }
      var t = -(this.origin.dot(plane.normal) + plane.constant) / denominator;
      return t >= 0 ? t : null;
    },
    intersectPlane: function(plane, optionalTarget) {
      var t = this.distanceToPlane(plane);
      if (t === null) {
        return null;
      }
      return this.at(t, optionalTarget);
    },
    intersectsPlane: function(plane) {
      var distToPoint = plane.distanceToPoint(this.origin);
      if (distToPoint === 0) {
        return true;
      }
      var denominator = plane.normal.dot(this.direction);
      if (denominator * distToPoint < 0) {
        return true;
      }
      return false;
    },
    intersectBox: function(box, optionalTarget) {
      var tmin,
          tmax,
          tymin,
          tymax,
          tzmin,
          tzmax;
      var invdirx = 1 / this.direction.x,
          invdiry = 1 / this.direction.y,
          invdirz = 1 / this.direction.z;
      var origin = this.origin;
      if (invdirx >= 0) {
        tmin = (box.min.x - origin.x) * invdirx;
        tmax = (box.max.x - origin.x) * invdirx;
      } else {
        tmin = (box.max.x - origin.x) * invdirx;
        tmax = (box.min.x - origin.x) * invdirx;
      }
      if (invdiry >= 0) {
        tymin = (box.min.y - origin.y) * invdiry;
        tymax = (box.max.y - origin.y) * invdiry;
      } else {
        tymin = (box.max.y - origin.y) * invdiry;
        tymax = (box.min.y - origin.y) * invdiry;
      }
      if ((tmin > tymax) || (tymin > tmax))
        return null;
      if (tymin > tmin || tmin !== tmin)
        tmin = tymin;
      if (tymax < tmax || tmax !== tmax)
        tmax = tymax;
      if (invdirz >= 0) {
        tzmin = (box.min.z - origin.z) * invdirz;
        tzmax = (box.max.z - origin.z) * invdirz;
      } else {
        tzmin = (box.max.z - origin.z) * invdirz;
        tzmax = (box.min.z - origin.z) * invdirz;
      }
      if ((tmin > tzmax) || (tzmin > tmax))
        return null;
      if (tzmin > tmin || tmin !== tmin)
        tmin = tzmin;
      if (tzmax < tmax || tmax !== tmax)
        tmax = tzmax;
      if (tmax < 0)
        return null;
      return this.at(tmin >= 0 ? tmin : tmax, optionalTarget);
    },
    intersectsBox: (function() {
      var v = new Vector3();
      return function intersectsBox(box) {
        return this.intersectBox(box, v) !== null;
      };
    })(),
    intersectTriangle: function() {
      var diff = new Vector3();
      var edge1 = new Vector3();
      var edge2 = new Vector3();
      var normal = new Vector3();
      return function intersectTriangle(a, b, c, backfaceCulling, optionalTarget) {
        edge1.subVectors(b, a);
        edge2.subVectors(c, a);
        normal.crossVectors(edge1, edge2);
        var DdN = this.direction.dot(normal);
        var sign;
        if (DdN > 0) {
          if (backfaceCulling)
            return null;
          sign = 1;
        } else if (DdN < 0) {
          sign = -1;
          DdN = -DdN;
        } else {
          return null;
        }
        diff.subVectors(this.origin, a);
        var DdQxE2 = sign * this.direction.dot(edge2.crossVectors(diff, edge2));
        if (DdQxE2 < 0) {
          return null;
        }
        var DdE1xQ = sign * this.direction.dot(edge1.cross(diff));
        if (DdE1xQ < 0) {
          return null;
        }
        if (DdQxE2 + DdE1xQ > DdN) {
          return null;
        }
        var QdN = -sign * diff.dot(normal);
        if (QdN < 0) {
          return null;
        }
        return this.at(QdN / DdN, optionalTarget);
      };
    }(),
    applyMatrix4: function(matrix4) {
      this.origin.applyMatrix4(matrix4);
      this.direction.transformDirection(matrix4);
      return this;
    },
    equals: function(ray) {
      return ray.origin.equals(this.origin) && ray.direction.equals(this.direction);
    }
  });
  function Line3(start, end) {
    this.start = (start !== undefined) ? start : new Vector3();
    this.end = (end !== undefined) ? end : new Vector3();
  }
  Object.assign(Line3.prototype, {
    set: function(start, end) {
      this.start.copy(start);
      this.end.copy(end);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(line) {
      this.start.copy(line.start);
      this.end.copy(line.end);
      return this;
    },
    getCenter: function(optionalTarget) {
      var result = optionalTarget || new Vector3();
      return result.addVectors(this.start, this.end).multiplyScalar(0.5);
    },
    delta: function(optionalTarget) {
      var result = optionalTarget || new Vector3();
      return result.subVectors(this.end, this.start);
    },
    distanceSq: function() {
      return this.start.distanceToSquared(this.end);
    },
    distance: function() {
      return this.start.distanceTo(this.end);
    },
    at: function(t, optionalTarget) {
      var result = optionalTarget || new Vector3();
      return this.delta(result).multiplyScalar(t).add(this.start);
    },
    closestPointToPointParameter: function() {
      var startP = new Vector3();
      var startEnd = new Vector3();
      return function closestPointToPointParameter(point, clampToLine) {
        startP.subVectors(point, this.start);
        startEnd.subVectors(this.end, this.start);
        var startEnd2 = startEnd.dot(startEnd);
        var startEnd_startP = startEnd.dot(startP);
        var t = startEnd_startP / startEnd2;
        if (clampToLine) {
          t = _Math.clamp(t, 0, 1);
        }
        return t;
      };
    }(),
    closestPointToPoint: function(point, clampToLine, optionalTarget) {
      var t = this.closestPointToPointParameter(point, clampToLine);
      var result = optionalTarget || new Vector3();
      return this.delta(result).multiplyScalar(t).add(this.start);
    },
    applyMatrix4: function(matrix) {
      this.start.applyMatrix4(matrix);
      this.end.applyMatrix4(matrix);
      return this;
    },
    equals: function(line) {
      return line.start.equals(this.start) && line.end.equals(this.end);
    }
  });
  function Triangle(a, b, c) {
    this.a = (a !== undefined) ? a : new Vector3();
    this.b = (b !== undefined) ? b : new Vector3();
    this.c = (c !== undefined) ? c : new Vector3();
  }
  Object.assign(Triangle, {
    normal: function() {
      var v0 = new Vector3();
      return function normal(a, b, c, optionalTarget) {
        var result = optionalTarget || new Vector3();
        result.subVectors(c, b);
        v0.subVectors(a, b);
        result.cross(v0);
        var resultLengthSq = result.lengthSq();
        if (resultLengthSq > 0) {
          return result.multiplyScalar(1 / Math.sqrt(resultLengthSq));
        }
        return result.set(0, 0, 0);
      };
    }(),
    barycoordFromPoint: function() {
      var v0 = new Vector3();
      var v1 = new Vector3();
      var v2 = new Vector3();
      return function barycoordFromPoint(point, a, b, c, optionalTarget) {
        v0.subVectors(c, a);
        v1.subVectors(b, a);
        v2.subVectors(point, a);
        var dot00 = v0.dot(v0);
        var dot01 = v0.dot(v1);
        var dot02 = v0.dot(v2);
        var dot11 = v1.dot(v1);
        var dot12 = v1.dot(v2);
        var denom = (dot00 * dot11 - dot01 * dot01);
        var result = optionalTarget || new Vector3();
        if (denom === 0) {
          return result.set(-2, -1, -1);
        }
        var invDenom = 1 / denom;
        var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
        var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
        return result.set(1 - u - v, v, u);
      };
    }(),
    containsPoint: function() {
      var v1 = new Vector3();
      return function containsPoint(point, a, b, c) {
        var result = Triangle.barycoordFromPoint(point, a, b, c, v1);
        return (result.x >= 0) && (result.y >= 0) && ((result.x + result.y) <= 1);
      };
    }()
  });
  Object.assign(Triangle.prototype, {
    set: function(a, b, c) {
      this.a.copy(a);
      this.b.copy(b);
      this.c.copy(c);
      return this;
    },
    setFromPointsAndIndices: function(points, i0, i1, i2) {
      this.a.copy(points[i0]);
      this.b.copy(points[i1]);
      this.c.copy(points[i2]);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(triangle) {
      this.a.copy(triangle.a);
      this.b.copy(triangle.b);
      this.c.copy(triangle.c);
      return this;
    },
    area: function() {
      var v0 = new Vector3();
      var v1 = new Vector3();
      return function area() {
        v0.subVectors(this.c, this.b);
        v1.subVectors(this.a, this.b);
        return v0.cross(v1).length() * 0.5;
      };
    }(),
    midpoint: function(optionalTarget) {
      var result = optionalTarget || new Vector3();
      return result.addVectors(this.a, this.b).add(this.c).multiplyScalar(1 / 3);
    },
    normal: function(optionalTarget) {
      return Triangle.normal(this.a, this.b, this.c, optionalTarget);
    },
    plane: function(optionalTarget) {
      var result = optionalTarget || new Plane();
      return result.setFromCoplanarPoints(this.a, this.b, this.c);
    },
    barycoordFromPoint: function(point, optionalTarget) {
      return Triangle.barycoordFromPoint(point, this.a, this.b, this.c, optionalTarget);
    },
    containsPoint: function(point) {
      return Triangle.containsPoint(point, this.a, this.b, this.c);
    },
    closestPointToPoint: function() {
      var plane = new Plane();
      var edgeList = [new Line3(), new Line3(), new Line3()];
      var projectedPoint = new Vector3();
      var closestPoint = new Vector3();
      return function closestPointToPoint(point, optionalTarget) {
        var result = optionalTarget || new Vector3();
        var minDistance = Infinity;
        plane.setFromCoplanarPoints(this.a, this.b, this.c);
        plane.projectPoint(point, projectedPoint);
        if (this.containsPoint(projectedPoint) === true) {
          result.copy(projectedPoint);
        } else {
          edgeList[0].set(this.a, this.b);
          edgeList[1].set(this.b, this.c);
          edgeList[2].set(this.c, this.a);
          for (var i = 0; i < edgeList.length; i++) {
            edgeList[i].closestPointToPoint(projectedPoint, true, closestPoint);
            var distance = projectedPoint.distanceToSquared(closestPoint);
            if (distance < minDistance) {
              minDistance = distance;
              result.copy(closestPoint);
            }
          }
        }
        return result;
      };
    }(),
    equals: function(triangle) {
      return triangle.a.equals(this.a) && triangle.b.equals(this.b) && triangle.c.equals(this.c);
    }
  });
  function Mesh(geometry, material) {
    Object3D.call(this);
    this.type = 'Mesh';
    this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
    this.material = material !== undefined ? material : new MeshBasicMaterial({color: Math.random() * 0xffffff});
    this.drawMode = TrianglesDrawMode;
    this.updateMorphTargets();
  }
  Mesh.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Mesh,
    isMesh: true,
    setDrawMode: function(value) {
      this.drawMode = value;
    },
    copy: function(source) {
      Object3D.prototype.copy.call(this, source);
      this.drawMode = source.drawMode;
      if (source.morphTargetInfluences !== undefined) {
        this.morphTargetInfluences = source.morphTargetInfluences.slice();
      }
      if (source.morphTargetDictionary !== undefined) {
        this.morphTargetDictionary = Object.assign({}, source.morphTargetDictionary);
      }
      return this;
    },
    updateMorphTargets: function() {
      var geometry = this.geometry;
      var m,
          ml,
          name;
      if (geometry.isBufferGeometry) {
        var morphAttributes = geometry.morphAttributes;
        var keys = Object.keys(morphAttributes);
        if (keys.length > 0) {
          var morphAttribute = morphAttributes[keys[0]];
          if (morphAttribute !== undefined) {
            this.morphTargetInfluences = [];
            this.morphTargetDictionary = {};
            for (m = 0, ml = morphAttribute.length; m < ml; m++) {
              name = morphAttribute[m].name || String(m);
              this.morphTargetInfluences.push(0);
              this.morphTargetDictionary[name] = m;
            }
          }
        }
      } else {
        var morphTargets = geometry.morphTargets;
        if (morphTargets !== undefined && morphTargets.length > 0) {
          this.morphTargetInfluences = [];
          this.morphTargetDictionary = {};
          for (m = 0, ml = morphTargets.length; m < ml; m++) {
            name = morphTargets[m].name || String(m);
            this.morphTargetInfluences.push(0);
            this.morphTargetDictionary[name] = m;
          }
        }
      }
    },
    raycast: (function() {
      var inverseMatrix = new Matrix4();
      var ray = new Ray();
      var sphere = new Sphere();
      var vA = new Vector3();
      var vB = new Vector3();
      var vC = new Vector3();
      var tempA = new Vector3();
      var tempB = new Vector3();
      var tempC = new Vector3();
      var uvA = new Vector2();
      var uvB = new Vector2();
      var uvC = new Vector2();
      var barycoord = new Vector3();
      var intersectionPoint = new Vector3();
      var intersectionPointWorld = new Vector3();
      function uvIntersection(point, p1, p2, p3, uv1, uv2, uv3) {
        Triangle.barycoordFromPoint(point, p1, p2, p3, barycoord);
        uv1.multiplyScalar(barycoord.x);
        uv2.multiplyScalar(barycoord.y);
        uv3.multiplyScalar(barycoord.z);
        uv1.add(uv2).add(uv3);
        return uv1.clone();
      }
      function checkIntersection(object, material, raycaster, ray, pA, pB, pC, point) {
        var intersect;
        if (material.side === BackSide) {
          intersect = ray.intersectTriangle(pC, pB, pA, true, point);
        } else {
          intersect = ray.intersectTriangle(pA, pB, pC, material.side !== DoubleSide, point);
        }
        if (intersect === null)
          return null;
        intersectionPointWorld.copy(point);
        intersectionPointWorld.applyMatrix4(object.matrixWorld);
        var distance = raycaster.ray.origin.distanceTo(intersectionPointWorld);
        if (distance < raycaster.near || distance > raycaster.far)
          return null;
        return {
          distance: distance,
          point: intersectionPointWorld.clone(),
          object: object
        };
      }
      function checkBufferGeometryIntersection(object, raycaster, ray, position, uv, a, b, c) {
        vA.fromBufferAttribute(position, a);
        vB.fromBufferAttribute(position, b);
        vC.fromBufferAttribute(position, c);
        var intersection = checkIntersection(object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint);
        if (intersection) {
          if (uv) {
            uvA.fromBufferAttribute(uv, a);
            uvB.fromBufferAttribute(uv, b);
            uvC.fromBufferAttribute(uv, c);
            intersection.uv = uvIntersection(intersectionPoint, vA, vB, vC, uvA, uvB, uvC);
          }
          intersection.face = new Face3(a, b, c, Triangle.normal(vA, vB, vC));
          intersection.faceIndex = a;
        }
        return intersection;
      }
      return function raycast(raycaster, intersects) {
        var geometry = this.geometry;
        var material = this.material;
        var matrixWorld = this.matrixWorld;
        if (material === undefined)
          return;
        if (geometry.boundingSphere === null)
          geometry.computeBoundingSphere();
        sphere.copy(geometry.boundingSphere);
        sphere.applyMatrix4(matrixWorld);
        if (raycaster.ray.intersectsSphere(sphere) === false)
          return;
        inverseMatrix.getInverse(matrixWorld);
        ray.copy(raycaster.ray).applyMatrix4(inverseMatrix);
        if (geometry.boundingBox !== null) {
          if (ray.intersectsBox(geometry.boundingBox) === false)
            return;
        }
        var intersection;
        if (geometry.isBufferGeometry) {
          var a,
              b,
              c;
          var index = geometry.index;
          var position = geometry.attributes.position;
          var uv = geometry.attributes.uv;
          var i,
              l;
          if (index !== null) {
            for (i = 0, l = index.count; i < l; i += 3) {
              a = index.getX(i);
              b = index.getX(i + 1);
              c = index.getX(i + 2);
              intersection = checkBufferGeometryIntersection(this, raycaster, ray, position, uv, a, b, c);
              if (intersection) {
                intersection.faceIndex = Math.floor(i / 3);
                intersects.push(intersection);
              }
            }
          } else if (position !== undefined) {
            for (i = 0, l = position.count; i < l; i += 3) {
              a = i;
              b = i + 1;
              c = i + 2;
              intersection = checkBufferGeometryIntersection(this, raycaster, ray, position, uv, a, b, c);
              if (intersection) {
                intersection.index = a;
                intersects.push(intersection);
              }
            }
          }
        } else if (geometry.isGeometry) {
          var fvA,
              fvB,
              fvC;
          var isMultiMaterial = Array.isArray(material);
          var vertices = geometry.vertices;
          var faces = geometry.faces;
          var uvs;
          var faceVertexUvs = geometry.faceVertexUvs[0];
          if (faceVertexUvs.length > 0)
            uvs = faceVertexUvs;
          for (var f = 0,
              fl = faces.length; f < fl; f++) {
            var face = faces[f];
            var faceMaterial = isMultiMaterial ? material[face.materialIndex] : material;
            if (faceMaterial === undefined)
              continue;
            fvA = vertices[face.a];
            fvB = vertices[face.b];
            fvC = vertices[face.c];
            if (faceMaterial.morphTargets === true) {
              var morphTargets = geometry.morphTargets;
              var morphInfluences = this.morphTargetInfluences;
              vA.set(0, 0, 0);
              vB.set(0, 0, 0);
              vC.set(0, 0, 0);
              for (var t = 0,
                  tl = morphTargets.length; t < tl; t++) {
                var influence = morphInfluences[t];
                if (influence === 0)
                  continue;
                var targets = morphTargets[t].vertices;
                vA.addScaledVector(tempA.subVectors(targets[face.a], fvA), influence);
                vB.addScaledVector(tempB.subVectors(targets[face.b], fvB), influence);
                vC.addScaledVector(tempC.subVectors(targets[face.c], fvC), influence);
              }
              vA.add(fvA);
              vB.add(fvB);
              vC.add(fvC);
              fvA = vA;
              fvB = vB;
              fvC = vC;
            }
            intersection = checkIntersection(this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint);
            if (intersection) {
              if (uvs && uvs[f]) {
                var uvs_f = uvs[f];
                uvA.copy(uvs_f[0]);
                uvB.copy(uvs_f[1]);
                uvC.copy(uvs_f[2]);
                intersection.uv = uvIntersection(intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC);
              }
              intersection.face = face;
              intersection.faceIndex = f;
              intersects.push(intersection);
            }
          }
        }
      };
    }()),
    clone: function() {
      return new this.constructor(this.geometry, this.material).copy(this);
    }
  });
  function WebGLBackground(renderer, state, geometries, premultipliedAlpha) {
    var clearColor = new Color(0x000000);
    var clearAlpha = 0;
    var planeCamera,
        planeMesh;
    var boxMesh;
    function render(renderList, scene, camera, forceClear) {
      var background = scene.background;
      if (background === null) {
        setClear(clearColor, clearAlpha);
      } else if (background && background.isColor) {
        setClear(background, 1);
        forceClear = true;
      }
      if (renderer.autoClear || forceClear) {
        renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil);
      }
      if (background && background.isCubeTexture) {
        if (boxMesh === undefined) {
          boxMesh = new Mesh(new BoxBufferGeometry(1, 1, 1), new ShaderMaterial({
            uniforms: ShaderLib.cube.uniforms,
            vertexShader: ShaderLib.cube.vertexShader,
            fragmentShader: ShaderLib.cube.fragmentShader,
            side: BackSide,
            depthTest: true,
            depthWrite: false,
            fog: false
          }));
          boxMesh.geometry.removeAttribute('normal');
          boxMesh.geometry.removeAttribute('uv');
          boxMesh.onBeforeRender = function(renderer, scene, camera) {
            this.matrixWorld.copyPosition(camera.matrixWorld);
          };
          geometries.update(boxMesh.geometry);
        }
        boxMesh.material.uniforms.tCube.value = background;
        renderList.push(boxMesh, boxMesh.geometry, boxMesh.material, 0, null);
      } else if (background && background.isTexture) {
        if (planeCamera === undefined) {
          planeCamera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
          planeMesh = new Mesh(new PlaneBufferGeometry(2, 2), new MeshBasicMaterial({
            depthTest: false,
            depthWrite: false,
            fog: false
          }));
          geometries.update(planeMesh.geometry);
        }
        planeMesh.material.map = background;
        renderer.renderBufferDirect(planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null);
      }
    }
    function setClear(color, alpha) {
      state.buffers.color.setClear(color.r, color.g, color.b, alpha, premultipliedAlpha);
    }
    return {
      getClearColor: function() {
        return clearColor;
      },
      setClearColor: function(color, alpha) {
        clearColor.set(color);
        clearAlpha = alpha !== undefined ? alpha : 1;
        setClear(clearColor, clearAlpha);
      },
      getClearAlpha: function() {
        return clearAlpha;
      },
      setClearAlpha: function(alpha) {
        clearAlpha = alpha;
        setClear(clearColor, clearAlpha);
      },
      render: render
    };
  }
  function painterSortStable(a, b) {
    if (a.renderOrder !== b.renderOrder) {
      return a.renderOrder - b.renderOrder;
    } else if (a.program && b.program && a.program !== b.program) {
      return a.program.id - b.program.id;
    } else if (a.material.id !== b.material.id) {
      return a.material.id - b.material.id;
    } else if (a.z !== b.z) {
      return a.z - b.z;
    } else {
      return a.id - b.id;
    }
  }
  function reversePainterSortStable(a, b) {
    if (a.renderOrder !== b.renderOrder) {
      return a.renderOrder - b.renderOrder;
    }
    if (a.z !== b.z) {
      return b.z - a.z;
    } else {
      return a.id - b.id;
    }
  }
  function WebGLRenderList() {
    var renderItems = [];
    var renderItemsIndex = 0;
    var opaque = [];
    var transparent = [];
    function init() {
      renderItemsIndex = 0;
      opaque.length = 0;
      transparent.length = 0;
    }
    function push(object, geometry, material, z, group) {
      var renderItem = renderItems[renderItemsIndex];
      if (renderItem === undefined) {
        renderItem = {
          id: object.id,
          object: object,
          geometry: geometry,
          material: material,
          program: material.program,
          renderOrder: object.renderOrder,
          z: z,
          group: group
        };
        renderItems[renderItemsIndex] = renderItem;
      } else {
        renderItem.id = object.id;
        renderItem.object = object;
        renderItem.geometry = geometry;
        renderItem.material = material;
        renderItem.program = material.program;
        renderItem.renderOrder = object.renderOrder;
        renderItem.z = z;
        renderItem.group = group;
      }
      (material.transparent === true ? transparent : opaque).push(renderItem);
      renderItemsIndex++;
    }
    function sort() {
      if (opaque.length > 1)
        opaque.sort(painterSortStable);
      if (transparent.length > 1)
        transparent.sort(reversePainterSortStable);
    }
    return {
      opaque: opaque,
      transparent: transparent,
      init: init,
      push: push,
      sort: sort
    };
  }
  function WebGLRenderLists() {
    var lists = {};
    function get(scene, camera) {
      var hash = scene.id + ',' + camera.id;
      var list = lists[hash];
      if (list === undefined) {
        list = new WebGLRenderList();
        lists[hash] = list;
      }
      return list;
    }
    function dispose() {
      lists = {};
    }
    return {
      get: get,
      dispose: dispose
    };
  }
  function absNumericalSort(a, b) {
    return Math.abs(b[1]) - Math.abs(a[1]);
  }
  function WebGLMorphtargets(gl) {
    var influencesList = {};
    var morphInfluences = new Float32Array(8);
    function update(object, geometry, material, program) {
      var objectInfluences = object.morphTargetInfluences;
      var length = objectInfluences.length;
      var influences = influencesList[geometry.id];
      if (influences === undefined) {
        influences = [];
        for (var i = 0; i < length; i++) {
          influences[i] = [i, 0];
        }
        influencesList[geometry.id] = influences;
      }
      var morphTargets = material.morphTargets && geometry.morphAttributes.position;
      var morphNormals = material.morphNormals && geometry.morphAttributes.normal;
      for (var i = 0; i < length; i++) {
        var influence = influences[i];
        if (influence[1] !== 0) {
          if (morphTargets)
            geometry.removeAttribute('morphTarget' + i);
          if (morphNormals)
            geometry.removeAttribute('morphNormal' + i);
        }
      }
      for (var i = 0; i < length; i++) {
        var influence = influences[i];
        influence[0] = i;
        influence[1] = objectInfluences[i];
      }
      influences.sort(absNumericalSort);
      for (var i = 0; i < 8; i++) {
        var influence = influences[i];
        if (influence) {
          var index = influence[0];
          var value = influence[1];
          if (value) {
            if (morphTargets)
              geometry.addAttribute('morphTarget' + i, morphTargets[index]);
            if (morphNormals)
              geometry.addAttribute('morphNormal' + i, morphNormals[index]);
            morphInfluences[i] = value;
            continue;
          }
        }
        morphInfluences[i] = 0;
      }
      program.getUniforms().setValue(gl, 'morphTargetInfluences', morphInfluences);
    }
    return {update: update};
  }
  function WebGLIndexedBufferRenderer(gl, extensions, infoRender) {
    var mode;
    function setMode(value) {
      mode = value;
    }
    var type,
        bytesPerElement;
    function setIndex(value) {
      type = value.type;
      bytesPerElement = value.bytesPerElement;
    }
    function render(start, count) {
      gl.drawElements(mode, count, type, start * bytesPerElement);
      infoRender.calls++;
      infoRender.vertices += count;
      if (mode === gl.TRIANGLES)
        infoRender.faces += count / 3;
      else if (mode === gl.POINTS)
        infoRender.points += count;
    }
    function renderInstances(geometry, start, count) {
      var extension = extensions.get('ANGLE_instanced_arrays');
      if (extension === null) {
        console.error('THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');
        return;
      }
      extension.drawElementsInstancedANGLE(mode, count, type, start * bytesPerElement, geometry.maxInstancedCount);
      infoRender.calls++;
      infoRender.vertices += count * geometry.maxInstancedCount;
      if (mode === gl.TRIANGLES)
        infoRender.faces += geometry.maxInstancedCount * count / 3;
      else if (mode === gl.POINTS)
        infoRender.points += geometry.maxInstancedCount * count;
    }
    this.setMode = setMode;
    this.setIndex = setIndex;
    this.render = render;
    this.renderInstances = renderInstances;
  }
  function WebGLBufferRenderer(gl, extensions, infoRender) {
    var mode;
    function setMode(value) {
      mode = value;
    }
    function render(start, count) {
      gl.drawArrays(mode, start, count);
      infoRender.calls++;
      infoRender.vertices += count;
      if (mode === gl.TRIANGLES)
        infoRender.faces += count / 3;
      else if (mode === gl.POINTS)
        infoRender.points += count;
    }
    function renderInstances(geometry, start, count) {
      var extension = extensions.get('ANGLE_instanced_arrays');
      if (extension === null) {
        console.error('THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');
        return;
      }
      var position = geometry.attributes.position;
      if (position.isInterleavedBufferAttribute) {
        count = position.data.count;
        extension.drawArraysInstancedANGLE(mode, 0, count, geometry.maxInstancedCount);
      } else {
        extension.drawArraysInstancedANGLE(mode, start, count, geometry.maxInstancedCount);
      }
      infoRender.calls++;
      infoRender.vertices += count * geometry.maxInstancedCount;
      if (mode === gl.TRIANGLES)
        infoRender.faces += geometry.maxInstancedCount * count / 3;
      else if (mode === gl.POINTS)
        infoRender.points += geometry.maxInstancedCount * count;
    }
    this.setMode = setMode;
    this.render = render;
    this.renderInstances = renderInstances;
  }
  function WebGLGeometries(gl, attributes, infoMemory) {
    var geometries = {};
    var wireframeAttributes = {};
    function onGeometryDispose(event) {
      var geometry = event.target;
      var buffergeometry = geometries[geometry.id];
      if (buffergeometry.index !== null) {
        attributes.remove(buffergeometry.index);
      }
      for (var name in buffergeometry.attributes) {
        attributes.remove(buffergeometry.attributes[name]);
      }
      geometry.removeEventListener('dispose', onGeometryDispose);
      delete geometries[geometry.id];
      var attribute = wireframeAttributes[geometry.id];
      if (attribute) {
        attributes.remove(attribute);
        delete wireframeAttributes[geometry.id];
      }
      attribute = wireframeAttributes[buffergeometry.id];
      if (attribute) {
        attributes.remove(attribute);
        delete wireframeAttributes[buffergeometry.id];
      }
      infoMemory.geometries--;
    }
    function get(object, geometry) {
      var buffergeometry = geometries[geometry.id];
      if (buffergeometry)
        return buffergeometry;
      geometry.addEventListener('dispose', onGeometryDispose);
      if (geometry.isBufferGeometry) {
        buffergeometry = geometry;
      } else if (geometry.isGeometry) {
        if (geometry._bufferGeometry === undefined) {
          geometry._bufferGeometry = new BufferGeometry().setFromObject(object);
        }
        buffergeometry = geometry._bufferGeometry;
      }
      geometries[geometry.id] = buffergeometry;
      infoMemory.geometries++;
      return buffergeometry;
    }
    function update(geometry) {
      var index = geometry.index;
      var geometryAttributes = geometry.attributes;
      if (index !== null) {
        attributes.update(index, gl.ELEMENT_ARRAY_BUFFER);
      }
      for (var name in geometryAttributes) {
        attributes.update(geometryAttributes[name], gl.ARRAY_BUFFER);
      }
      var morphAttributes = geometry.morphAttributes;
      for (var name in morphAttributes) {
        var array = morphAttributes[name];
        for (var i = 0,
            l = array.length; i < l; i++) {
          attributes.update(array[i], gl.ARRAY_BUFFER);
        }
      }
    }
    function getWireframeAttribute(geometry) {
      var attribute = wireframeAttributes[geometry.id];
      if (attribute)
        return attribute;
      var indices = [];
      var geometryIndex = geometry.index;
      var geometryAttributes = geometry.attributes;
      if (geometryIndex !== null) {
        var array = geometryIndex.array;
        for (var i = 0,
            l = array.length; i < l; i += 3) {
          var a = array[i + 0];
          var b = array[i + 1];
          var c = array[i + 2];
          indices.push(a, b, b, c, c, a);
        }
      } else {
        var array = geometryAttributes.position.array;
        for (var i = 0,
            l = (array.length / 3) - 1; i < l; i += 3) {
          var a = i + 0;
          var b = i + 1;
          var c = i + 2;
          indices.push(a, b, b, c, c, a);
        }
      }
      attribute = new (arrayMax(indices) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute)(indices, 1);
      attributes.update(attribute, gl.ELEMENT_ARRAY_BUFFER);
      wireframeAttributes[geometry.id] = attribute;
      return attribute;
    }
    return {
      get: get,
      update: update,
      getWireframeAttribute: getWireframeAttribute
    };
  }
  function UniformsCache() {
    var lights = {};
    return {get: function(light) {
        if (lights[light.id] !== undefined) {
          return lights[light.id];
        }
        var uniforms;
        switch (light.type) {
          case 'DirectionalLight':
            uniforms = {
              direction: new Vector3(),
              color: new Color(),
              shadow: false,
              shadowBias: 0,
              shadowRadius: 1,
              shadowMapSize: new Vector2()
            };
            break;
          case 'SpotLight':
            uniforms = {
              position: new Vector3(),
              direction: new Vector3(),
              color: new Color(),
              distance: 0,
              coneCos: 0,
              penumbraCos: 0,
              decay: 0,
              shadow: false,
              shadowBias: 0,
              shadowRadius: 1,
              shadowMapSize: new Vector2()
            };
            break;
          case 'PointLight':
            uniforms = {
              position: new Vector3(),
              color: new Color(),
              distance: 0,
              decay: 0,
              shadow: false,
              shadowBias: 0,
              shadowRadius: 1,
              shadowMapSize: new Vector2(),
              shadowCameraNear: 1,
              shadowCameraFar: 1000
            };
            break;
          case 'HemisphereLight':
            uniforms = {
              direction: new Vector3(),
              skyColor: new Color(),
              groundColor: new Color()
            };
            break;
          case 'RectAreaLight':
            uniforms = {
              color: new Color(),
              position: new Vector3(),
              halfWidth: new Vector3(),
              halfHeight: new Vector3()
            };
            break;
        }
        lights[light.id] = uniforms;
        return uniforms;
      }};
  }
  function WebGLLights() {
    var cache = new UniformsCache();
    var state = {
      hash: '',
      ambient: [0, 0, 0],
      directional: [],
      directionalShadowMap: [],
      directionalShadowMatrix: [],
      spot: [],
      spotShadowMap: [],
      spotShadowMatrix: [],
      rectArea: [],
      point: [],
      pointShadowMap: [],
      pointShadowMatrix: [],
      hemi: []
    };
    var vector3 = new Vector3();
    var matrix4 = new Matrix4();
    var matrix42 = new Matrix4();
    function setup(lights, shadows, camera) {
      var r = 0,
          g = 0,
          b = 0;
      var directionalLength = 0;
      var pointLength = 0;
      var spotLength = 0;
      var rectAreaLength = 0;
      var hemiLength = 0;
      var viewMatrix = camera.matrixWorldInverse;
      for (var i = 0,
          l = lights.length; i < l; i++) {
        var light = lights[i];
        var color = light.color;
        var intensity = light.intensity;
        var distance = light.distance;
        var shadowMap = (light.shadow && light.shadow.map) ? light.shadow.map.texture : null;
        if (light.isAmbientLight) {
          r += color.r * intensity;
          g += color.g * intensity;
          b += color.b * intensity;
        } else if (light.isDirectionalLight) {
          var uniforms = cache.get(light);
          uniforms.color.copy(light.color).multiplyScalar(light.intensity);
          uniforms.direction.setFromMatrixPosition(light.matrixWorld);
          vector3.setFromMatrixPosition(light.target.matrixWorld);
          uniforms.direction.sub(vector3);
          uniforms.direction.transformDirection(viewMatrix);
          uniforms.shadow = light.castShadow;
          if (light.castShadow) {
            var shadow = light.shadow;
            uniforms.shadowBias = shadow.bias;
            uniforms.shadowRadius = shadow.radius;
            uniforms.shadowMapSize = shadow.mapSize;
          }
          state.directionalShadowMap[directionalLength] = shadowMap;
          state.directionalShadowMatrix[directionalLength] = light.shadow.matrix;
          state.directional[directionalLength] = uniforms;
          directionalLength++;
        } else if (light.isSpotLight) {
          var uniforms = cache.get(light);
          uniforms.position.setFromMatrixPosition(light.matrixWorld);
          uniforms.position.applyMatrix4(viewMatrix);
          uniforms.color.copy(color).multiplyScalar(intensity);
          uniforms.distance = distance;
          uniforms.direction.setFromMatrixPosition(light.matrixWorld);
          vector3.setFromMatrixPosition(light.target.matrixWorld);
          uniforms.direction.sub(vector3);
          uniforms.direction.transformDirection(viewMatrix);
          uniforms.coneCos = Math.cos(light.angle);
          uniforms.penumbraCos = Math.cos(light.angle * (1 - light.penumbra));
          uniforms.decay = (light.distance === 0) ? 0.0 : light.decay;
          uniforms.shadow = light.castShadow;
          if (light.castShadow) {
            var shadow = light.shadow;
            uniforms.shadowBias = shadow.bias;
            uniforms.shadowRadius = shadow.radius;
            uniforms.shadowMapSize = shadow.mapSize;
          }
          state.spotShadowMap[spotLength] = shadowMap;
          state.spotShadowMatrix[spotLength] = light.shadow.matrix;
          state.spot[spotLength] = uniforms;
          spotLength++;
        } else if (light.isRectAreaLight) {
          var uniforms = cache.get(light);
          uniforms.color.copy(color).multiplyScalar(intensity / (light.width * light.height));
          uniforms.position.setFromMatrixPosition(light.matrixWorld);
          uniforms.position.applyMatrix4(viewMatrix);
          matrix42.identity();
          matrix4.copy(light.matrixWorld);
          matrix4.premultiply(viewMatrix);
          matrix42.extractRotation(matrix4);
          uniforms.halfWidth.set(light.width * 0.5, 0.0, 0.0);
          uniforms.halfHeight.set(0.0, light.height * 0.5, 0.0);
          uniforms.halfWidth.applyMatrix4(matrix42);
          uniforms.halfHeight.applyMatrix4(matrix42);
          state.rectArea[rectAreaLength] = uniforms;
          rectAreaLength++;
        } else if (light.isPointLight) {
          var uniforms = cache.get(light);
          uniforms.position.setFromMatrixPosition(light.matrixWorld);
          uniforms.position.applyMatrix4(viewMatrix);
          uniforms.color.copy(light.color).multiplyScalar(light.intensity);
          uniforms.distance = light.distance;
          uniforms.decay = (light.distance === 0) ? 0.0 : light.decay;
          uniforms.shadow = light.castShadow;
          if (light.castShadow) {
            var shadow = light.shadow;
            uniforms.shadowBias = shadow.bias;
            uniforms.shadowRadius = shadow.radius;
            uniforms.shadowMapSize = shadow.mapSize;
            uniforms.shadowCameraNear = shadow.camera.near;
            uniforms.shadowCameraFar = shadow.camera.far;
          }
          state.pointShadowMap[pointLength] = shadowMap;
          state.pointShadowMatrix[pointLength] = light.shadow.matrix;
          state.point[pointLength] = uniforms;
          pointLength++;
        } else if (light.isHemisphereLight) {
          var uniforms = cache.get(light);
          uniforms.direction.setFromMatrixPosition(light.matrixWorld);
          uniforms.direction.transformDirection(viewMatrix);
          uniforms.direction.normalize();
          uniforms.skyColor.copy(light.color).multiplyScalar(intensity);
          uniforms.groundColor.copy(light.groundColor).multiplyScalar(intensity);
          state.hemi[hemiLength] = uniforms;
          hemiLength++;
        }
      }
      state.ambient[0] = r;
      state.ambient[1] = g;
      state.ambient[2] = b;
      state.directional.length = directionalLength;
      state.spot.length = spotLength;
      state.rectArea.length = rectAreaLength;
      state.point.length = pointLength;
      state.hemi.length = hemiLength;
      state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length;
    }
    return {
      setup: setup,
      state: state
    };
  }
  function WebGLObjects(geometries, infoRender) {
    var updateList = {};
    function update(object) {
      var frame = infoRender.frame;
      var geometry = object.geometry;
      var buffergeometry = geometries.get(object, geometry);
      if (updateList[buffergeometry.id] !== frame) {
        if (geometry.isGeometry) {
          buffergeometry.updateFromObject(object);
        }
        geometries.update(buffergeometry);
        updateList[buffergeometry.id] = frame;
      }
      return buffergeometry;
    }
    function clear() {
      updateList = {};
    }
    return {
      update: update,
      clear: clear
    };
  }
  function addLineNumbers(string) {
    var lines = string.split('\n');
    for (var i = 0; i < lines.length; i++) {
      lines[i] = (i + 1) + ': ' + lines[i];
    }
    return lines.join('\n');
  }
  function WebGLShader(gl, type, string) {
    var shader = gl.createShader(type);
    gl.shaderSource(shader, string);
    gl.compileShader(shader);
    if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) === false) {
      console.error('THREE.WebGLShader: Shader couldn\'t compile.');
    }
    if (gl.getShaderInfoLog(shader) !== '') {
      console.warn('THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog(shader), addLineNumbers(string));
    }
    return shader;
  }
  var programIdCount = 0;
  function getEncodingComponents(encoding) {
    switch (encoding) {
      case LinearEncoding:
        return ['Linear', '( value )'];
      case sRGBEncoding:
        return ['sRGB', '( value )'];
      case RGBEEncoding:
        return ['RGBE', '( value )'];
      case RGBM7Encoding:
        return ['RGBM', '( value, 7.0 )'];
      case RGBM16Encoding:
        return ['RGBM', '( value, 16.0 )'];
      case RGBDEncoding:
        return ['RGBD', '( value, 256.0 )'];
      case GammaEncoding:
        return ['Gamma', '( value, float( GAMMA_FACTOR ) )'];
      default:
        throw new Error('unsupported encoding: ' + encoding);
    }
  }
  function getTexelDecodingFunction(functionName, encoding) {
    var components = getEncodingComponents(encoding);
    return "vec4 " + functionName + "( vec4 value ) { return " + components[0] + "ToLinear" + components[1] + "; }";
  }
  function getTexelEncodingFunction(functionName, encoding) {
    var components = getEncodingComponents(encoding);
    return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[0] + components[1] + "; }";
  }
  function getToneMappingFunction(functionName, toneMapping) {
    var toneMappingName;
    switch (toneMapping) {
      case LinearToneMapping:
        toneMappingName = "Linear";
        break;
      case ReinhardToneMapping:
        toneMappingName = "Reinhard";
        break;
      case Uncharted2ToneMapping:
        toneMappingName = "Uncharted2";
        break;
      case CineonToneMapping:
        toneMappingName = "OptimizedCineon";
        break;
      default:
        throw new Error('unsupported toneMapping: ' + toneMapping);
    }
    return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }";
  }
  function generateExtensions(extensions, parameters, rendererExtensions) {
    extensions = extensions || {};
    var chunks = [(extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading) ? '#extension GL_OES_standard_derivatives : enable' : '', (extensions.fragDepth || parameters.logarithmicDepthBuffer) && rendererExtensions.get('EXT_frag_depth') ? '#extension GL_EXT_frag_depth : enable' : '', (extensions.drawBuffers) && rendererExtensions.get('WEBGL_draw_buffers') ? '#extension GL_EXT_draw_buffers : require' : '', (extensions.shaderTextureLOD || parameters.envMap) && rendererExtensions.get('EXT_shader_texture_lod') ? '#extension GL_EXT_shader_texture_lod : enable' : ''];
    return chunks.filter(filterEmptyLine).join('\n');
  }
  function generateDefines(defines) {
    var chunks = [];
    for (var name in defines) {
      var value = defines[name];
      if (value === false)
        continue;
      chunks.push('#define ' + name + ' ' + value);
    }
    return chunks.join('\n');
  }
  function fetchAttributeLocations(gl, program) {
    var attributes = {};
    var n = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
    for (var i = 0; i < n; i++) {
      var info = gl.getActiveAttrib(program, i);
      var name = info.name;
      attributes[name] = gl.getAttribLocation(program, name);
    }
    return attributes;
  }
  function filterEmptyLine(string) {
    return string !== '';
  }
  function replaceLightNums(string, parameters) {
    return string.replace(/NUM_DIR_LIGHTS/g, parameters.numDirLights).replace(/NUM_SPOT_LIGHTS/g, parameters.numSpotLights).replace(/NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g, parameters.numPointLights).replace(/NUM_HEMI_LIGHTS/g, parameters.numHemiLights);
  }
  function parseIncludes(string) {
    var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm;
    function replace(match, include) {
      var replace = ShaderChunk[include];
      if (replace === undefined) {
        throw new Error('Can not resolve #include <' + include + '>');
      }
      return parseIncludes(replace);
    }
    return string.replace(pattern, replace);
  }
  function unrollLoops(string) {
    var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
    function replace(match, start, end, snippet) {
      var unroll = '';
      for (var i = parseInt(start); i < parseInt(end); i++) {
        unroll += snippet.replace(/\[ i \]/g, '[ ' + i + ' ]');
      }
      return unroll;
    }
    return string.replace(pattern, replace);
  }
  function WebGLProgram(renderer, extensions, code, material, shader, parameters) {
    var gl = renderer.context;
    var defines = material.defines;
    var vertexShader = shader.vertexShader;
    var fragmentShader = shader.fragmentShader;
    var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
    if (parameters.shadowMapType === PCFShadowMap) {
      shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
    } else if (parameters.shadowMapType === PCFSoftShadowMap) {
      shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
    }
    var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
    var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
    var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
    if (parameters.envMap) {
      switch (material.envMap.mapping) {
        case CubeReflectionMapping:
        case CubeRefractionMapping:
          envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
          break;
        case CubeUVReflectionMapping:
        case CubeUVRefractionMapping:
          envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
          break;
        case EquirectangularReflectionMapping:
        case EquirectangularRefractionMapping:
          envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
          break;
        case SphericalReflectionMapping:
          envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
          break;
      }
      switch (material.envMap.mapping) {
        case CubeRefractionMapping:
        case EquirectangularRefractionMapping:
          envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
          break;
      }
      switch (material.combine) {
        case MultiplyOperation:
          envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
          break;
        case MixOperation:
          envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
          break;
        case AddOperation:
          envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
          break;
      }
    }
    var gammaFactorDefine = (renderer.gammaFactor > 0) ? renderer.gammaFactor : 1.0;
    var customExtensions = generateExtensions(material.extensions, parameters, extensions);
    var customDefines = generateDefines(defines);
    var program = gl.createProgram();
    var prefixVertex,
        prefixFragment;
    if (material.isRawShaderMaterial) {
      prefixVertex = [customDefines].filter(filterEmptyLine).join('\n');
      if (prefixVertex.length > 0) {
        prefixVertex += '\n';
      }
      prefixFragment = [customExtensions, customDefines].filter(filterEmptyLine).join('\n');
      if (prefixFragment.length > 0) {
        prefixFragment += '\n';
      }
    } else {
      prefixVertex = ['precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', '#define SHADER_NAME ' + shader.name, customDefines, parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', '#define GAMMA_FACTOR ' + gammaFactorDefine, '#define MAX_BONES ' + parameters.maxBones, (parameters.useFog && parameters.fog) ? '#define USE_FOG' : '', (parameters.useFog && parameters.fogExp) ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.skinning ? '#define USE_SKINNING' : '', parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && extensions.get('EXT_frag_depth') ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat3 normalMatrix;', 'uniform vec3 cameraPosition;', 'attribute vec3 position;', 'attribute vec3 normal;', 'attribute vec2 uv;', '#ifdef USE_COLOR', '	attribute vec3 color;', '#endif', '#ifdef USE_MORPHTARGETS', '	attribute vec3 morphTarget0;', '	attribute vec3 morphTarget1;', '	attribute vec3 morphTarget2;', '	attribute vec3 morphTarget3;', '	#ifdef USE_MORPHNORMALS', '		attribute vec3 morphNormal0;', '		attribute vec3 morphNormal1;', '		attribute vec3 morphNormal2;', '		attribute vec3 morphNormal3;', '	#else', '		attribute vec3 morphTarget4;', '		attribute vec3 morphTarget5;', '		attribute vec3 morphTarget6;', '		attribute vec3 morphTarget7;', '	#endif', '#endif', '#ifdef USE_SKINNING', '	attribute vec4 skinIndex;', '	attribute vec4 skinWeight;', '#endif', '\n'].filter(filterEmptyLine).join('\n');
      prefixFragment = [customExtensions, 'precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', '#define SHADER_NAME ' + shader.name, customDefines, parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '', '#define GAMMA_FACTOR ' + gammaFactorDefine, (parameters.useFog && parameters.fog) ? '#define USE_FOG' : '', (parameters.useFog && parameters.fogExp) ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapTypeDefine : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.envMap ? '#define ' + envMapBlendingDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, '#define UNION_CLIPPING_PLANES ' + (parameters.numClippingPlanes - parameters.numClipIntersection), parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : '', parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && extensions.get('EXT_frag_depth') ? '#define USE_LOGDEPTHBUF_EXT' : '', parameters.envMap && extensions.get('EXT_shader_texture_lod') ? '#define TEXTURE_LOD_EXT' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', (parameters.toneMapping !== NoToneMapping) ? "#define TONE_MAPPING" : '', (parameters.toneMapping !== NoToneMapping) ? ShaderChunk['tonemapping_pars_fragment'] : '', (parameters.toneMapping !== NoToneMapping) ? getToneMappingFunction("toneMapping", parameters.toneMapping) : '', parameters.dithering ? '#define DITHERING' : '', (parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding) ? ShaderChunk['encodings_pars_fragment'] : '', parameters.mapEncoding ? getTexelDecodingFunction('mapTexelToLinear', parameters.mapEncoding) : '', parameters.envMapEncoding ? getTexelDecodingFunction('envMapTexelToLinear', parameters.envMapEncoding) : '', parameters.emissiveMapEncoding ? getTexelDecodingFunction('emissiveMapTexelToLinear', parameters.emissiveMapEncoding) : '', parameters.outputEncoding ? getTexelEncodingFunction("linearToOutputTexel", parameters.outputEncoding) : '', parameters.depthPacking ? "#define DEPTH_PACKING " + material.depthPacking : '', '\n'].filter(filterEmptyLine).join('\n');
    }
    vertexShader = parseIncludes(vertexShader);
    vertexShader = replaceLightNums(vertexShader, parameters);
    fragmentShader = parseIncludes(fragmentShader);
    fragmentShader = replaceLightNums(fragmentShader, parameters);
    if (!material.isShaderMaterial) {
      vertexShader = unrollLoops(vertexShader);
      fragmentShader = unrollLoops(fragmentShader);
    }
    var vertexGlsl = prefixVertex + vertexShader;
    var fragmentGlsl = prefixFragment + fragmentShader;
    var glVertexShader = WebGLShader(gl, gl.VERTEX_SHADER, vertexGlsl);
    var glFragmentShader = WebGLShader(gl, gl.FRAGMENT_SHADER, fragmentGlsl);
    gl.attachShader(program, glVertexShader);
    gl.attachShader(program, glFragmentShader);
    if (material.index0AttributeName !== undefined) {
      gl.bindAttribLocation(program, 0, material.index0AttributeName);
    } else if (parameters.morphTargets === true) {
      gl.bindAttribLocation(program, 0, 'position');
    }
    gl.linkProgram(program);
    var programLog = gl.getProgramInfoLog(program);
    var vertexLog = gl.getShaderInfoLog(glVertexShader);
    var fragmentLog = gl.getShaderInfoLog(glFragmentShader);
    var runnable = true;
    var haveDiagnostics = true;
    if (gl.getProgramParameter(program, gl.LINK_STATUS) === false) {
      runnable = false;
      console.error('THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog);
    } else if (programLog !== '') {
      console.warn('THREE.WebGLProgram: gl.getProgramInfoLog()', programLog);
    } else if (vertexLog === '' || fragmentLog === '') {
      haveDiagnostics = false;
    }
    if (haveDiagnostics) {
      this.diagnostics = {
        runnable: runnable,
        material: material,
        programLog: programLog,
        vertexShader: {
          log: vertexLog,
          prefix: prefixVertex
        },
        fragmentShader: {
          log: fragmentLog,
          prefix: prefixFragment
        }
      };
    }
    gl.deleteShader(glVertexShader);
    gl.deleteShader(glFragmentShader);
    var cachedUniforms;
    this.getUniforms = function() {
      if (cachedUniforms === undefined) {
        cachedUniforms = new WebGLUniforms(gl, program, renderer);
      }
      return cachedUniforms;
    };
    var cachedAttributes;
    this.getAttributes = function() {
      if (cachedAttributes === undefined) {
        cachedAttributes = fetchAttributeLocations(gl, program);
      }
      return cachedAttributes;
    };
    this.destroy = function() {
      gl.deleteProgram(program);
      this.program = undefined;
    };
    Object.defineProperties(this, {
      uniforms: {get: function() {
          console.warn('THREE.WebGLProgram: .uniforms is now .getUniforms().');
          return this.getUniforms();
        }},
      attributes: {get: function() {
          console.warn('THREE.WebGLProgram: .attributes is now .getAttributes().');
          return this.getAttributes();
        }}
    });
    this.id = programIdCount++;
    this.code = code;
    this.usedTimes = 1;
    this.program = program;
    this.vertexShader = glVertexShader;
    this.fragmentShader = glFragmentShader;
    return this;
  }
  function WebGLPrograms(renderer, extensions, capabilities) {
    var programs = [];
    var shaderIDs = {
      MeshDepthMaterial: 'depth',
      MeshDistanceMaterial: 'distanceRGBA',
      MeshNormalMaterial: 'normal',
      MeshBasicMaterial: 'basic',
      MeshLambertMaterial: 'lambert',
      MeshPhongMaterial: 'phong',
      MeshToonMaterial: 'phong',
      MeshStandardMaterial: 'physical',
      MeshPhysicalMaterial: 'physical',
      LineBasicMaterial: 'basic',
      LineDashedMaterial: 'dashed',
      PointsMaterial: 'points',
      ShadowMaterial: 'shadow'
    };
    var parameterNames = ["precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding", "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap", "roughnessMap", "metalnessMap", "gradientMap", "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp", "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", "maxBones", "useVertexTexture", "morphTargets", "morphNormals", "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights", "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights', "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering"];
    function allocateBones(object) {
      var skeleton = object.skeleton;
      var bones = skeleton.bones;
      if (capabilities.floatVertexTextures) {
        return 1024;
      } else {
        var nVertexUniforms = capabilities.maxVertexUniforms;
        var nVertexMatrices = Math.floor((nVertexUniforms - 20) / 4);
        var maxBones = Math.min(nVertexMatrices, bones.length);
        if (maxBones < bones.length) {
          console.warn('THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.');
          return 0;
        }
        return maxBones;
      }
    }
    function getTextureEncodingFromMap(map, gammaOverrideLinear) {
      var encoding;
      if (!map) {
        encoding = LinearEncoding;
      } else if (map.isTexture) {
        encoding = map.encoding;
      } else if (map.isWebGLRenderTarget) {
        console.warn("THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead.");
        encoding = map.texture.encoding;
      }
      if (encoding === LinearEncoding && gammaOverrideLinear) {
        encoding = GammaEncoding;
      }
      return encoding;
    }
    this.getParameters = function(material, lights, shadows, fog, nClipPlanes, nClipIntersection, object) {
      var shaderID = shaderIDs[material.type];
      var maxBones = object.isSkinnedMesh ? allocateBones(object) : 0;
      var precision = capabilities.precision;
      if (material.precision !== null) {
        precision = capabilities.getMaxPrecision(material.precision);
        if (precision !== material.precision) {
          console.warn('THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.');
        }
      }
      var currentRenderTarget = renderer.getRenderTarget();
      var parameters = {
        shaderID: shaderID,
        precision: precision,
        supportsVertexTextures: capabilities.vertexTextures,
        outputEncoding: getTextureEncodingFromMap((!currentRenderTarget) ? null : currentRenderTarget.texture, renderer.gammaOutput),
        map: !!material.map,
        mapEncoding: getTextureEncodingFromMap(material.map, renderer.gammaInput),
        envMap: !!material.envMap,
        envMapMode: material.envMap && material.envMap.mapping,
        envMapEncoding: getTextureEncodingFromMap(material.envMap, renderer.gammaInput),
        envMapCubeUV: (!!material.envMap) && ((material.envMap.mapping === CubeUVReflectionMapping) || (material.envMap.mapping === CubeUVRefractionMapping)),
        lightMap: !!material.lightMap,
        aoMap: !!material.aoMap,
        emissiveMap: !!material.emissiveMap,
        emissiveMapEncoding: getTextureEncodingFromMap(material.emissiveMap, renderer.gammaInput),
        bumpMap: !!material.bumpMap,
        normalMap: !!material.normalMap,
        displacementMap: !!material.displacementMap,
        roughnessMap: !!material.roughnessMap,
        metalnessMap: !!material.metalnessMap,
        specularMap: !!material.specularMap,
        alphaMap: !!material.alphaMap,
        gradientMap: !!material.gradientMap,
        combine: material.combine,
        vertexColors: material.vertexColors,
        fog: !!fog,
        useFog: material.fog,
        fogExp: (fog && fog.isFogExp2),
        flatShading: material.flatShading,
        sizeAttenuation: material.sizeAttenuation,
        logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
        skinning: material.skinning && maxBones > 0,
        maxBones: maxBones,
        useVertexTexture: capabilities.floatVertexTextures,
        morphTargets: material.morphTargets,
        morphNormals: material.morphNormals,
        maxMorphTargets: renderer.maxMorphTargets,
        maxMorphNormals: renderer.maxMorphNormals,
        numDirLights: lights.directional.length,
        numPointLights: lights.point.length,
        numSpotLights: lights.spot.length,
        numRectAreaLights: lights.rectArea.length,
        numHemiLights: lights.hemi.length,
        numClippingPlanes: nClipPlanes,
        numClipIntersection: nClipIntersection,
        dithering: material.dithering,
        shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0,
        shadowMapType: renderer.shadowMap.type,
        toneMapping: renderer.toneMapping,
        physicallyCorrectLights: renderer.physicallyCorrectLights,
        premultipliedAlpha: material.premultipliedAlpha,
        alphaTest: material.alphaTest,
        doubleSided: material.side === DoubleSide,
        flipSided: material.side === BackSide,
        depthPacking: (material.depthPacking !== undefined) ? material.depthPacking : false
      };
      return parameters;
    };
    this.getProgramCode = function(material, parameters) {
      var array = [];
      if (parameters.shaderID) {
        array.push(parameters.shaderID);
      } else {
        array.push(material.fragmentShader);
        array.push(material.vertexShader);
      }
      if (material.defines !== undefined) {
        for (var name in material.defines) {
          array.push(name);
          array.push(material.defines[name]);
        }
      }
      for (var i = 0; i < parameterNames.length; i++) {
        array.push(parameters[parameterNames[i]]);
      }
      array.push(material.onBeforeCompile.toString());
      array.push(renderer.gammaOutput);
      return array.join();
    };
    this.acquireProgram = function(material, shader, parameters, code) {
      var program;
      for (var p = 0,
          pl = programs.length; p < pl; p++) {
        var programInfo = programs[p];
        if (programInfo.code === code) {
          program = programInfo;
          ++program.usedTimes;
          break;
        }
      }
      if (program === undefined) {
        program = new WebGLProgram(renderer, extensions, code, material, shader, parameters);
        programs.push(program);
      }
      return program;
    };
    this.releaseProgram = function(program) {
      if (--program.usedTimes === 0) {
        var i = programs.indexOf(program);
        programs[i] = programs[programs.length - 1];
        programs.pop();
        program.destroy();
      }
    };
    this.programs = programs;
  }
  function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, infoMemory) {
    var _isWebGL2 = (typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof window.WebGL2RenderingContext);
    function clampToMaxSize(image, maxSize) {
      if (image.width > maxSize || image.height > maxSize) {
        var scale = maxSize / Math.max(image.width, image.height);
        var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
        canvas.width = Math.floor(image.width * scale);
        canvas.height = Math.floor(image.height * scale);
        var context = canvas.getContext('2d');
        context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
        console.warn('THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image);
        return canvas;
      }
      return image;
    }
    function isPowerOfTwo(image) {
      return _Math.isPowerOfTwo(image.width) && _Math.isPowerOfTwo(image.height);
    }
    function makePowerOfTwo(image) {
      if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap) {
        var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
        canvas.width = _Math.floorPowerOfTwo(image.width);
        canvas.height = _Math.floorPowerOfTwo(image.height);
        var context = canvas.getContext('2d');
        context.drawImage(image, 0, 0, canvas.width, canvas.height);
        console.warn('THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image);
        return canvas;
      }
      return image;
    }
    function textureNeedsPowerOfTwo(texture) {
      return (texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping) || (texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter);
    }
    function textureNeedsGenerateMipmaps(texture, isPowerOfTwo) {
      return texture.generateMipmaps && isPowerOfTwo && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
    }
    function filterFallback(f) {
      if (f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter) {
        return _gl.NEAREST;
      }
      return _gl.LINEAR;
    }
    function onTextureDispose(event) {
      var texture = event.target;
      texture.removeEventListener('dispose', onTextureDispose);
      deallocateTexture(texture);
      infoMemory.textures--;
    }
    function onRenderTargetDispose(event) {
      var renderTarget = event.target;
      renderTarget.removeEventListener('dispose', onRenderTargetDispose);
      deallocateRenderTarget(renderTarget);
      infoMemory.textures--;
    }
    function deallocateTexture(texture) {
      var textureProperties = properties.get(texture);
      if (texture.image && textureProperties.__image__webglTextureCube) {
        _gl.deleteTexture(textureProperties.__image__webglTextureCube);
      } else {
        if (textureProperties.__webglInit === undefined)
          return;
        _gl.deleteTexture(textureProperties.__webglTexture);
      }
      properties.remove(texture);
    }
    function deallocateRenderTarget(renderTarget) {
      var renderTargetProperties = properties.get(renderTarget);
      var textureProperties = properties.get(renderTarget.texture);
      if (!renderTarget)
        return;
      if (textureProperties.__webglTexture !== undefined) {
        _gl.deleteTexture(textureProperties.__webglTexture);
      }
      if (renderTarget.depthTexture) {
        renderTarget.depthTexture.dispose();
      }
      if (renderTarget.isWebGLRenderTargetCube) {
        for (var i = 0; i < 6; i++) {
          _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[i]);
          if (renderTargetProperties.__webglDepthbuffer)
            _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer[i]);
        }
      } else {
        _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer);
        if (renderTargetProperties.__webglDepthbuffer)
          _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer);
      }
      properties.remove(renderTarget.texture);
      properties.remove(renderTarget);
    }
    function setTexture2D(texture, slot) {
      var textureProperties = properties.get(texture);
      if (texture.version > 0 && textureProperties.__version !== texture.version) {
        var image = texture.image;
        if (image === undefined) {
          console.warn('THREE.WebGLRenderer: Texture marked for update but image is undefined', texture);
        } else if (image.complete === false) {
          console.warn('THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture);
        } else {
          uploadTexture(textureProperties, texture, slot);
          return;
        }
      }
      state.activeTexture(_gl.TEXTURE0 + slot);
      state.bindTexture(_gl.TEXTURE_2D, textureProperties.__webglTexture);
    }
    function setTextureCube(texture, slot) {
      var textureProperties = properties.get(texture);
      if (texture.image.length === 6) {
        if (texture.version > 0 && textureProperties.__version !== texture.version) {
          if (!textureProperties.__image__webglTextureCube) {
            texture.addEventListener('dispose', onTextureDispose);
            textureProperties.__image__webglTextureCube = _gl.createTexture();
            infoMemory.textures++;
          }
          state.activeTexture(_gl.TEXTURE0 + slot);
          state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube);
          _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
          var isCompressed = (texture && texture.isCompressedTexture);
          var isDataTexture = (texture.image[0] && texture.image[0].isDataTexture);
          var cubeImage = [];
          for (var i = 0; i < 6; i++) {
            if (!isCompressed && !isDataTexture) {
              cubeImage[i] = clampToMaxSize(texture.image[i], capabilities.maxCubemapSize);
            } else {
              cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i];
            }
          }
          var image = cubeImage[0],
              isPowerOfTwoImage = isPowerOfTwo(image),
              glFormat = utils.convert(texture.format),
              glType = utils.convert(texture.type);
          setTextureParameters(_gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage);
          for (var i = 0; i < 6; i++) {
            if (!isCompressed) {
              if (isDataTexture) {
                state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[i].width, cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data);
              } else {
                state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[i]);
              }
            } else {
              var mipmap,
                  mipmaps = cubeImage[i].mipmaps;
              for (var j = 0,
                  jl = mipmaps.length; j < jl; j++) {
                mipmap = mipmaps[j];
                if (texture.format !== RGBAFormat && texture.format !== RGBFormat) {
                  if (state.getCompressedTextureFormats().indexOf(glFormat) > -1) {
                    state.compressedTexImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data);
                  } else {
                    console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()');
                  }
                } else {
                  state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
                }
              }
            }
          }
          if (textureNeedsGenerateMipmaps(texture, isPowerOfTwoImage)) {
            _gl.generateMipmap(_gl.TEXTURE_CUBE_MAP);
          }
          textureProperties.__version = texture.version;
          if (texture.onUpdate)
            texture.onUpdate(texture);
        } else {
          state.activeTexture(_gl.TEXTURE0 + slot);
          state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube);
        }
      }
    }
    function setTextureCubeDynamic(texture, slot) {
      state.activeTexture(_gl.TEXTURE0 + slot);
      state.bindTexture(_gl.TEXTURE_CUBE_MAP, properties.get(texture).__webglTexture);
    }
    function setTextureParameters(textureType, texture, isPowerOfTwoImage) {
      var extension;
      if (isPowerOfTwoImage) {
        _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_S, utils.convert(texture.wrapS));
        _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, utils.convert(texture.wrapT));
        _gl.texParameteri(textureType, _gl.TEXTURE_MAG_FILTER, utils.convert(texture.magFilter));
        _gl.texParameteri(textureType, _gl.TEXTURE_MIN_FILTER, utils.convert(texture.minFilter));
      } else {
        _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE);
        _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE);
        if (texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping) {
          console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture);
        }
        _gl.texParameteri(textureType, _gl.TEXTURE_MAG_FILTER, filterFallback(texture.magFilter));
        _gl.texParameteri(textureType, _gl.TEXTURE_MIN_FILTER, filterFallback(texture.minFilter));
        if (texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter) {
          console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture);
        }
      }
      extension = extensions.get('EXT_texture_filter_anisotropic');
      if (extension) {
        if (texture.type === FloatType && extensions.get('OES_texture_float_linear') === null)
          return;
        if (texture.type === HalfFloatType && extensions.get('OES_texture_half_float_linear') === null)
          return;
        if (texture.anisotropy > 1 || properties.get(texture).__currentAnisotropy) {
          _gl.texParameterf(textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropy, capabilities.getMaxAnisotropy()));
          properties.get(texture).__currentAnisotropy = texture.anisotropy;
        }
      }
    }
    function uploadTexture(textureProperties, texture, slot) {
      if (textureProperties.__webglInit === undefined) {
        textureProperties.__webglInit = true;
        texture.addEventListener('dispose', onTextureDispose);
        textureProperties.__webglTexture = _gl.createTexture();
        infoMemory.textures++;
      }
      state.activeTexture(_gl.TEXTURE0 + slot);
      state.bindTexture(_gl.TEXTURE_2D, textureProperties.__webglTexture);
      _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
      _gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha);
      _gl.pixelStorei(_gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
      var image = clampToMaxSize(texture.image, capabilities.maxTextureSize);
      if (textureNeedsPowerOfTwo(texture) && isPowerOfTwo(image) === false) {
        image = makePowerOfTwo(image);
      }
      var isPowerOfTwoImage = isPowerOfTwo(image),
          glFormat = utils.convert(texture.format),
          glType = utils.convert(texture.type);
      setTextureParameters(_gl.TEXTURE_2D, texture, isPowerOfTwoImage);
      var mipmap,
          mipmaps = texture.mipmaps;
      if (texture.isDepthTexture) {
        var internalFormat = _gl.DEPTH_COMPONENT;
        if (texture.type === FloatType) {
          if (!_isWebGL2)
            throw new Error('Float Depth Texture only supported in WebGL2.0');
          internalFormat = _gl.DEPTH_COMPONENT32F;
        } else if (_isWebGL2) {
          internalFormat = _gl.DEPTH_COMPONENT16;
        }
        if (texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT) {
          if (texture.type !== UnsignedShortType && texture.type !== UnsignedIntType) {
            console.warn('THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.');
            texture.type = UnsignedShortType;
            glType = utils.convert(texture.type);
          }
        }
        if (texture.format === DepthStencilFormat) {
          internalFormat = _gl.DEPTH_STENCIL;
          if (texture.type !== UnsignedInt248Type) {
            console.warn('THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.');
            texture.type = UnsignedInt248Type;
            glType = utils.convert(texture.type);
          }
        }
        state.texImage2D(_gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null);
      } else if (texture.isDataTexture) {
        if (mipmaps.length > 0 && isPowerOfTwoImage) {
          for (var i = 0,
              il = mipmaps.length; i < il; i++) {
            mipmap = mipmaps[i];
            state.texImage2D(_gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
          }
          texture.generateMipmaps = false;
        } else {
          state.texImage2D(_gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data);
        }
      } else if (texture.isCompressedTexture) {
        for (var i = 0,
            il = mipmaps.length; i < il; i++) {
          mipmap = mipmaps[i];
          if (texture.format !== RGBAFormat && texture.format !== RGBFormat) {
            if (state.getCompressedTextureFormats().indexOf(glFormat) > -1) {
              state.compressedTexImage2D(_gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data);
            } else {
              console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()');
            }
          } else {
            state.texImage2D(_gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
          }
        }
      } else {
        if (mipmaps.length > 0 && isPowerOfTwoImage) {
          for (var i = 0,
              il = mipmaps.length; i < il; i++) {
            mipmap = mipmaps[i];
            state.texImage2D(_gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap);
          }
          texture.generateMipmaps = false;
        } else {
          state.texImage2D(_gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image);
        }
      }
      if (textureNeedsGenerateMipmaps(texture, isPowerOfTwoImage))
        _gl.generateMipmap(_gl.TEXTURE_2D);
      textureProperties.__version = texture.version;
      if (texture.onUpdate)
        texture.onUpdate(texture);
    }
    function setupFrameBufferTexture(framebuffer, renderTarget, attachment, textureTarget) {
      var glFormat = utils.convert(renderTarget.texture.format);
      var glType = utils.convert(renderTarget.texture.type);
      state.texImage2D(textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null);
      _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
      _gl.framebufferTexture2D(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(renderTarget.texture).__webglTexture, 0);
      _gl.bindFramebuffer(_gl.FRAMEBUFFER, null);
    }
    function setupRenderBufferStorage(renderbuffer, renderTarget) {
      _gl.bindRenderbuffer(_gl.RENDERBUFFER, renderbuffer);
      if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) {
        _gl.renderbufferStorage(_gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height);
        _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer);
      } else if (renderTarget.depthBuffer && renderTarget.stencilBuffer) {
        _gl.renderbufferStorage(_gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height);
        _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer);
      } else {
        _gl.renderbufferStorage(_gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height);
      }
      _gl.bindRenderbuffer(_gl.RENDERBUFFER, null);
    }
    function setupDepthTexture(framebuffer, renderTarget) {
      var isCube = (renderTarget && renderTarget.isWebGLRenderTargetCube);
      if (isCube)
        throw new Error('Depth Texture with cube render targets is not supported');
      _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
      if (!(renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture)) {
        throw new Error('renderTarget.depthTexture must be an instance of THREE.DepthTexture');
      }
      if (!properties.get(renderTarget.depthTexture).__webglTexture || renderTarget.depthTexture.image.width !== renderTarget.width || renderTarget.depthTexture.image.height !== renderTarget.height) {
        renderTarget.depthTexture.image.width = renderTarget.width;
        renderTarget.depthTexture.image.height = renderTarget.height;
        renderTarget.depthTexture.needsUpdate = true;
      }
      setTexture2D(renderTarget.depthTexture, 0);
      var webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture;
      if (renderTarget.depthTexture.format === DepthFormat) {
        _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0);
      } else if (renderTarget.depthTexture.format === DepthStencilFormat) {
        _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0);
      } else {
        throw new Error('Unknown depthTexture format');
      }
    }
    function setupDepthRenderbuffer(renderTarget) {
      var renderTargetProperties = properties.get(renderTarget);
      var isCube = (renderTarget.isWebGLRenderTargetCube === true);
      if (renderTarget.depthTexture) {
        if (isCube)
          throw new Error('target.depthTexture not supported in Cube render targets');
        setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget);
      } else {
        if (isCube) {
          renderTargetProperties.__webglDepthbuffer = [];
          for (var i = 0; i < 6; i++) {
            _gl.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[i]);
            renderTargetProperties.__webglDepthbuffer[i] = _gl.createRenderbuffer();
            setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer[i], renderTarget);
          }
        } else {
          _gl.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer);
          renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
          setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer, renderTarget);
        }
      }
      _gl.bindFramebuffer(_gl.FRAMEBUFFER, null);
    }
    function setupRenderTarget(renderTarget) {
      var renderTargetProperties = properties.get(renderTarget);
      var textureProperties = properties.get(renderTarget.texture);
      renderTarget.addEventListener('dispose', onRenderTargetDispose);
      textureProperties.__webglTexture = _gl.createTexture();
      infoMemory.textures++;
      var isCube = (renderTarget.isWebGLRenderTargetCube === true);
      var isTargetPowerOfTwo = isPowerOfTwo(renderTarget);
      if (isCube) {
        renderTargetProperties.__webglFramebuffer = [];
        for (var i = 0; i < 6; i++) {
          renderTargetProperties.__webglFramebuffer[i] = _gl.createFramebuffer();
        }
      } else {
        renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
      }
      if (isCube) {
        state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture);
        setTextureParameters(_gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo);
        for (var i = 0; i < 6; i++) {
          setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i);
        }
        if (textureNeedsGenerateMipmaps(renderTarget.texture, isTargetPowerOfTwo))
          _gl.generateMipmap(_gl.TEXTURE_CUBE_MAP);
        state.bindTexture(_gl.TEXTURE_CUBE_MAP, null);
      } else {
        state.bindTexture(_gl.TEXTURE_2D, textureProperties.__webglTexture);
        setTextureParameters(_gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo);
        setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D);
        if (textureNeedsGenerateMipmaps(renderTarget.texture, isTargetPowerOfTwo))
          _gl.generateMipmap(_gl.TEXTURE_2D);
        state.bindTexture(_gl.TEXTURE_2D, null);
      }
      if (renderTarget.depthBuffer) {
        setupDepthRenderbuffer(renderTarget);
      }
    }
    function updateRenderTargetMipmap(renderTarget) {
      var texture = renderTarget.texture;
      var isTargetPowerOfTwo = isPowerOfTwo(renderTarget);
      if (textureNeedsGenerateMipmaps(texture, isTargetPowerOfTwo)) {
        var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
        var webglTexture = properties.get(texture).__webglTexture;
        state.bindTexture(target, webglTexture);
        _gl.generateMipmap(target);
        state.bindTexture(target, null);
      }
    }
    this.setTexture2D = setTexture2D;
    this.setTextureCube = setTextureCube;
    this.setTextureCubeDynamic = setTextureCubeDynamic;
    this.setupRenderTarget = setupRenderTarget;
    this.updateRenderTargetMipmap = updateRenderTargetMipmap;
  }
  function WebGLProperties() {
    var properties = {};
    function get(object) {
      var uuid = object.uuid;
      var map = properties[uuid];
      if (map === undefined) {
        map = {};
        properties[uuid] = map;
      }
      return map;
    }
    function remove(object) {
      delete properties[object.uuid];
    }
    function clear() {
      properties = {};
    }
    return {
      get: get,
      remove: remove,
      clear: clear
    };
  }
  function WebGLState(gl, extensions, utils) {
    function ColorBuffer() {
      var locked = false;
      var color = new Vector4();
      var currentColorMask = null;
      var currentColorClear = new Vector4(0, 0, 0, 0);
      return {
        setMask: function(colorMask) {
          if (currentColorMask !== colorMask && !locked) {
            gl.colorMask(colorMask, colorMask, colorMask, colorMask);
            currentColorMask = colorMask;
          }
        },
        setLocked: function(lock) {
          locked = lock;
        },
        setClear: function(r, g, b, a, premultipliedAlpha) {
          if (premultipliedAlpha === true) {
            r *= a;
            g *= a;
            b *= a;
          }
          color.set(r, g, b, a);
          if (currentColorClear.equals(color) === false) {
            gl.clearColor(r, g, b, a);
            currentColorClear.copy(color);
          }
        },
        reset: function() {
          locked = false;
          currentColorMask = null;
          currentColorClear.set(-1, 0, 0, 0);
        }
      };
    }
    function DepthBuffer() {
      var locked = false;
      var currentDepthMask = null;
      var currentDepthFunc = null;
      var currentDepthClear = null;
      return {
        setTest: function(depthTest) {
          if (depthTest) {
            enable(gl.DEPTH_TEST);
          } else {
            disable(gl.DEPTH_TEST);
          }
        },
        setMask: function(depthMask) {
          if (currentDepthMask !== depthMask && !locked) {
            gl.depthMask(depthMask);
            currentDepthMask = depthMask;
          }
        },
        setFunc: function(depthFunc) {
          if (currentDepthFunc !== depthFunc) {
            if (depthFunc) {
              switch (depthFunc) {
                case NeverDepth:
                  gl.depthFunc(gl.NEVER);
                  break;
                case AlwaysDepth:
                  gl.depthFunc(gl.ALWAYS);
                  break;
                case LessDepth:
                  gl.depthFunc(gl.LESS);
                  break;
                case LessEqualDepth:
                  gl.depthFunc(gl.LEQUAL);
                  break;
                case EqualDepth:
                  gl.depthFunc(gl.EQUAL);
                  break;
                case GreaterEqualDepth:
                  gl.depthFunc(gl.GEQUAL);
                  break;
                case GreaterDepth:
                  gl.depthFunc(gl.GREATER);
                  break;
                case NotEqualDepth:
                  gl.depthFunc(gl.NOTEQUAL);
                  break;
                default:
                  gl.depthFunc(gl.LEQUAL);
              }
            } else {
              gl.depthFunc(gl.LEQUAL);
            }
            currentDepthFunc = depthFunc;
          }
        },
        setLocked: function(lock) {
          locked = lock;
        },
        setClear: function(depth) {
          if (currentDepthClear !== depth) {
            gl.clearDepth(depth);
            currentDepthClear = depth;
          }
        },
        reset: function() {
          locked = false;
          currentDepthMask = null;
          currentDepthFunc = null;
          currentDepthClear = null;
        }
      };
    }
    function StencilBuffer() {
      var locked = false;
      var currentStencilMask = null;
      var currentStencilFunc = null;
      var currentStencilRef = null;
      var currentStencilFuncMask = null;
      var currentStencilFail = null;
      var currentStencilZFail = null;
      var currentStencilZPass = null;
      var currentStencilClear = null;
      return {
        setTest: function(stencilTest) {
          if (stencilTest) {
            enable(gl.STENCIL_TEST);
          } else {
            disable(gl.STENCIL_TEST);
          }
        },
        setMask: function(stencilMask) {
          if (currentStencilMask !== stencilMask && !locked) {
            gl.stencilMask(stencilMask);
            currentStencilMask = stencilMask;
          }
        },
        setFunc: function(stencilFunc, stencilRef, stencilMask) {
          if (currentStencilFunc !== stencilFunc || currentStencilRef !== stencilRef || currentStencilFuncMask !== stencilMask) {
            gl.stencilFunc(stencilFunc, stencilRef, stencilMask);
            currentStencilFunc = stencilFunc;
            currentStencilRef = stencilRef;
            currentStencilFuncMask = stencilMask;
          }
        },
        setOp: function(stencilFail, stencilZFail, stencilZPass) {
          if (currentStencilFail !== stencilFail || currentStencilZFail !== stencilZFail || currentStencilZPass !== stencilZPass) {
            gl.stencilOp(stencilFail, stencilZFail, stencilZPass);
            currentStencilFail = stencilFail;
            currentStencilZFail = stencilZFail;
            currentStencilZPass = stencilZPass;
          }
        },
        setLocked: function(lock) {
          locked = lock;
        },
        setClear: function(stencil) {
          if (currentStencilClear !== stencil) {
            gl.clearStencil(stencil);
            currentStencilClear = stencil;
          }
        },
        reset: function() {
          locked = false;
          currentStencilMask = null;
          currentStencilFunc = null;
          currentStencilRef = null;
          currentStencilFuncMask = null;
          currentStencilFail = null;
          currentStencilZFail = null;
          currentStencilZPass = null;
          currentStencilClear = null;
        }
      };
    }
    var colorBuffer = new ColorBuffer();
    var depthBuffer = new DepthBuffer();
    var stencilBuffer = new StencilBuffer();
    var maxVertexAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
    var newAttributes = new Uint8Array(maxVertexAttributes);
    var enabledAttributes = new Uint8Array(maxVertexAttributes);
    var attributeDivisors = new Uint8Array(maxVertexAttributes);
    var capabilities = {};
    var compressedTextureFormats = null;
    var currentProgram = null;
    var currentBlending = null;
    var currentBlendEquation = null;
    var currentBlendSrc = null;
    var currentBlendDst = null;
    var currentBlendEquationAlpha = null;
    var currentBlendSrcAlpha = null;
    var currentBlendDstAlpha = null;
    var currentPremultipledAlpha = false;
    var currentFlipSided = null;
    var currentCullFace = null;
    var currentLineWidth = null;
    var currentPolygonOffsetFactor = null;
    var currentPolygonOffsetUnits = null;
    var maxTextures = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);
    var version = parseFloat(/^WebGL\ ([0-9])/.exec(gl.getParameter(gl.VERSION))[1]);
    var lineWidthAvailable = parseFloat(version) >= 1.0;
    var currentTextureSlot = null;
    var currentBoundTextures = {};
    var currentScissor = new Vector4();
    var currentViewport = new Vector4();
    function createTexture(type, target, count) {
      var data = new Uint8Array(4);
      var texture = gl.createTexture();
      gl.bindTexture(type, texture);
      gl.texParameteri(type, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(type, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      for (var i = 0; i < count; i++) {
        gl.texImage2D(target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
      }
      return texture;
    }
    var emptyTextures = {};
    emptyTextures[gl.TEXTURE_2D] = createTexture(gl.TEXTURE_2D, gl.TEXTURE_2D, 1);
    emptyTextures[gl.TEXTURE_CUBE_MAP] = createTexture(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6);
    colorBuffer.setClear(0, 0, 0, 1);
    depthBuffer.setClear(1);
    stencilBuffer.setClear(0);
    enable(gl.DEPTH_TEST);
    depthBuffer.setFunc(LessEqualDepth);
    setFlipSided(false);
    setCullFace(CullFaceBack);
    enable(gl.CULL_FACE);
    enable(gl.BLEND);
    setBlending(NormalBlending);
    function initAttributes() {
      for (var i = 0,
          l = newAttributes.length; i < l; i++) {
        newAttributes[i] = 0;
      }
    }
    function enableAttribute(attribute) {
      newAttributes[attribute] = 1;
      if (enabledAttributes[attribute] === 0) {
        gl.enableVertexAttribArray(attribute);
        enabledAttributes[attribute] = 1;
      }
      if (attributeDivisors[attribute] !== 0) {
        var extension = extensions.get('ANGLE_instanced_arrays');
        extension.vertexAttribDivisorANGLE(attribute, 0);
        attributeDivisors[attribute] = 0;
      }
    }
    function enableAttributeAndDivisor(attribute, meshPerAttribute) {
      newAttributes[attribute] = 1;
      if (enabledAttributes[attribute] === 0) {
        gl.enableVertexAttribArray(attribute);
        enabledAttributes[attribute] = 1;
      }
      if (attributeDivisors[attribute] !== meshPerAttribute) {
        var extension = extensions.get('ANGLE_instanced_arrays');
        extension.vertexAttribDivisorANGLE(attribute, meshPerAttribute);
        attributeDivisors[attribute] = meshPerAttribute;
      }
    }
    function disableUnusedAttributes() {
      for (var i = 0,
          l = enabledAttributes.length; i !== l; ++i) {
        if (enabledAttributes[i] !== newAttributes[i]) {
          gl.disableVertexAttribArray(i);
          enabledAttributes[i] = 0;
        }
      }
    }
    function enable(id) {
      if (capabilities[id] !== true) {
        gl.enable(id);
        capabilities[id] = true;
      }
    }
    function disable(id) {
      if (capabilities[id] !== false) {
        gl.disable(id);
        capabilities[id] = false;
      }
    }
    function getCompressedTextureFormats() {
      if (compressedTextureFormats === null) {
        compressedTextureFormats = [];
        if (extensions.get('WEBGL_compressed_texture_pvrtc') || extensions.get('WEBGL_compressed_texture_s3tc') || extensions.get('WEBGL_compressed_texture_etc1')) {
          var formats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
          for (var i = 0; i < formats.length; i++) {
            compressedTextureFormats.push(formats[i]);
          }
        }
      }
      return compressedTextureFormats;
    }
    function useProgram(program) {
      if (currentProgram !== program) {
        gl.useProgram(program);
        currentProgram = program;
        return true;
      }
      return false;
    }
    function setBlending(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha) {
      if (blending !== NoBlending) {
        enable(gl.BLEND);
      } else {
        disable(gl.BLEND);
      }
      if (blending !== CustomBlending) {
        if (blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha) {
          switch (blending) {
            case AdditiveBlending:
              if (premultipliedAlpha) {
                gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
                gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE);
              } else {
                gl.blendEquation(gl.FUNC_ADD);
                gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
              }
              break;
            case SubtractiveBlending:
              if (premultipliedAlpha) {
                gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
                gl.blendFuncSeparate(gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA);
              } else {
                gl.blendEquation(gl.FUNC_ADD);
                gl.blendFunc(gl.ZERO, gl.ONE_MINUS_SRC_COLOR);
              }
              break;
            case MultiplyBlending:
              if (premultipliedAlpha) {
                gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
                gl.blendFuncSeparate(gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA);
              } else {
                gl.blendEquation(gl.FUNC_ADD);
                gl.blendFunc(gl.ZERO, gl.SRC_COLOR);
              }
              break;
            default:
              if (premultipliedAlpha) {
                gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
                gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
              } else {
                gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
                gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
              }
          }
        }
        currentBlendEquation = null;
        currentBlendSrc = null;
        currentBlendDst = null;
        currentBlendEquationAlpha = null;
        currentBlendSrcAlpha = null;
        currentBlendDstAlpha = null;
      } else {
        blendEquationAlpha = blendEquationAlpha || blendEquation;
        blendSrcAlpha = blendSrcAlpha || blendSrc;
        blendDstAlpha = blendDstAlpha || blendDst;
        if (blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha) {
          gl.blendEquationSeparate(utils.convert(blendEquation), utils.convert(blendEquationAlpha));
          currentBlendEquation = blendEquation;
          currentBlendEquationAlpha = blendEquationAlpha;
        }
        if (blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha) {
          gl.blendFuncSeparate(utils.convert(blendSrc), utils.convert(blendDst), utils.convert(blendSrcAlpha), utils.convert(blendDstAlpha));
          currentBlendSrc = blendSrc;
          currentBlendDst = blendDst;
          currentBlendSrcAlpha = blendSrcAlpha;
          currentBlendDstAlpha = blendDstAlpha;
        }
      }
      currentBlending = blending;
      currentPremultipledAlpha = premultipliedAlpha;
    }
    function setMaterial(material) {
      material.side === DoubleSide ? disable(gl.CULL_FACE) : enable(gl.CULL_FACE);
      setFlipSided(material.side === BackSide);
      material.transparent === true ? setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha) : setBlending(NoBlending);
      depthBuffer.setFunc(material.depthFunc);
      depthBuffer.setTest(material.depthTest);
      depthBuffer.setMask(material.depthWrite);
      colorBuffer.setMask(material.colorWrite);
      setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits);
    }
    function setFlipSided(flipSided) {
      if (currentFlipSided !== flipSided) {
        if (flipSided) {
          gl.frontFace(gl.CW);
        } else {
          gl.frontFace(gl.CCW);
        }
        currentFlipSided = flipSided;
      }
    }
    function setCullFace(cullFace) {
      if (cullFace !== CullFaceNone) {
        enable(gl.CULL_FACE);
        if (cullFace !== currentCullFace) {
          if (cullFace === CullFaceBack) {
            gl.cullFace(gl.BACK);
          } else if (cullFace === CullFaceFront) {
            gl.cullFace(gl.FRONT);
          } else {
            gl.cullFace(gl.FRONT_AND_BACK);
          }
        }
      } else {
        disable(gl.CULL_FACE);
      }
      currentCullFace = cullFace;
    }
    function setLineWidth(width) {
      if (width !== currentLineWidth) {
        if (lineWidthAvailable)
          gl.lineWidth(width);
        currentLineWidth = width;
      }
    }
    function setPolygonOffset(polygonOffset, factor, units) {
      if (polygonOffset) {
        enable(gl.POLYGON_OFFSET_FILL);
        if (currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units) {
          gl.polygonOffset(factor, units);
          currentPolygonOffsetFactor = factor;
          currentPolygonOffsetUnits = units;
        }
      } else {
        disable(gl.POLYGON_OFFSET_FILL);
      }
    }
    function setScissorTest(scissorTest) {
      if (scissorTest) {
        enable(gl.SCISSOR_TEST);
      } else {
        disable(gl.SCISSOR_TEST);
      }
    }
    function activeTexture(webglSlot) {
      if (webglSlot === undefined)
        webglSlot = gl.TEXTURE0 + maxTextures - 1;
      if (currentTextureSlot !== webglSlot) {
        gl.activeTexture(webglSlot);
        currentTextureSlot = webglSlot;
      }
    }
    function bindTexture(webglType, webglTexture) {
      if (currentTextureSlot === null) {
        activeTexture();
      }
      var boundTexture = currentBoundTextures[currentTextureSlot];
      if (boundTexture === undefined) {
        boundTexture = {
          type: undefined,
          texture: undefined
        };
        currentBoundTextures[currentTextureSlot] = boundTexture;
      }
      if (boundTexture.type !== webglType || boundTexture.texture !== webglTexture) {
        gl.bindTexture(webglType, webglTexture || emptyTextures[webglType]);
        boundTexture.type = webglType;
        boundTexture.texture = webglTexture;
      }
    }
    function compressedTexImage2D() {
      try {
        gl.compressedTexImage2D.apply(gl, arguments);
      } catch (error) {
        console.error('THREE.WebGLState:', error);
      }
    }
    function texImage2D() {
      try {
        gl.texImage2D.apply(gl, arguments);
      } catch (error) {
        console.error('THREE.WebGLState:', error);
      }
    }
    function scissor(scissor) {
      if (currentScissor.equals(scissor) === false) {
        gl.scissor(scissor.x, scissor.y, scissor.z, scissor.w);
        currentScissor.copy(scissor);
      }
    }
    function viewport(viewport) {
      if (currentViewport.equals(viewport) === false) {
        gl.viewport(viewport.x, viewport.y, viewport.z, viewport.w);
        currentViewport.copy(viewport);
      }
    }
    function reset() {
      for (var i = 0; i < enabledAttributes.length; i++) {
        if (enabledAttributes[i] === 1) {
          gl.disableVertexAttribArray(i);
          enabledAttributes[i] = 0;
        }
      }
      capabilities = {};
      compressedTextureFormats = null;
      currentTextureSlot = null;
      currentBoundTextures = {};
      currentProgram = null;
      currentBlending = null;
      currentFlipSided = null;
      currentCullFace = null;
      colorBuffer.reset();
      depthBuffer.reset();
      stencilBuffer.reset();
    }
    return {
      buffers: {
        color: colorBuffer,
        depth: depthBuffer,
        stencil: stencilBuffer
      },
      initAttributes: initAttributes,
      enableAttribute: enableAttribute,
      enableAttributeAndDivisor: enableAttributeAndDivisor,
      disableUnusedAttributes: disableUnusedAttributes,
      enable: enable,
      disable: disable,
      getCompressedTextureFormats: getCompressedTextureFormats,
      useProgram: useProgram,
      setBlending: setBlending,
      setMaterial: setMaterial,
      setFlipSided: setFlipSided,
      setCullFace: setCullFace,
      setLineWidth: setLineWidth,
      setPolygonOffset: setPolygonOffset,
      setScissorTest: setScissorTest,
      activeTexture: activeTexture,
      bindTexture: bindTexture,
      compressedTexImage2D: compressedTexImage2D,
      texImage2D: texImage2D,
      scissor: scissor,
      viewport: viewport,
      reset: reset
    };
  }
  function WebGLCapabilities(gl, extensions, parameters) {
    var maxAnisotropy;
    function getMaxAnisotropy() {
      if (maxAnisotropy !== undefined)
        return maxAnisotropy;
      var extension = extensions.get('EXT_texture_filter_anisotropic');
      if (extension !== null) {
        maxAnisotropy = gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
      } else {
        maxAnisotropy = 0;
      }
      return maxAnisotropy;
    }
    function getMaxPrecision(precision) {
      if (precision === 'highp') {
        if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0) {
          return 'highp';
        }
        precision = 'mediump';
      }
      if (precision === 'mediump') {
        if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0) {
          return 'mediump';
        }
      }
      return 'lowp';
    }
    var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
    var maxPrecision = getMaxPrecision(precision);
    if (maxPrecision !== precision) {
      console.warn('THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.');
      precision = maxPrecision;
    }
    var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
    var maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
    var maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
    var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
    var maxCubemapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
    var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
    var maxVertexUniforms = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);
    var maxVaryings = gl.getParameter(gl.MAX_VARYING_VECTORS);
    var maxFragmentUniforms = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
    var vertexTextures = maxVertexTextures > 0;
    var floatFragmentTextures = !!extensions.get('OES_texture_float');
    var floatVertexTextures = vertexTextures && floatFragmentTextures;
    return {
      getMaxAnisotropy: getMaxAnisotropy,
      getMaxPrecision: getMaxPrecision,
      precision: precision,
      logarithmicDepthBuffer: logarithmicDepthBuffer,
      maxTextures: maxTextures,
      maxVertexTextures: maxVertexTextures,
      maxTextureSize: maxTextureSize,
      maxCubemapSize: maxCubemapSize,
      maxAttributes: maxAttributes,
      maxVertexUniforms: maxVertexUniforms,
      maxVaryings: maxVaryings,
      maxFragmentUniforms: maxFragmentUniforms,
      vertexTextures: vertexTextures,
      floatFragmentTextures: floatFragmentTextures,
      floatVertexTextures: floatVertexTextures
    };
  }
  function PerspectiveCamera(fov, aspect, near, far) {
    Camera.call(this);
    this.type = 'PerspectiveCamera';
    this.fov = fov !== undefined ? fov : 50;
    this.zoom = 1;
    this.near = near !== undefined ? near : 0.1;
    this.far = far !== undefined ? far : 2000;
    this.focus = 10;
    this.aspect = aspect !== undefined ? aspect : 1;
    this.view = null;
    this.filmGauge = 35;
    this.filmOffset = 0;
    this.updateProjectionMatrix();
  }
  PerspectiveCamera.prototype = Object.assign(Object.create(Camera.prototype), {
    constructor: PerspectiveCamera,
    isPerspectiveCamera: true,
    copy: function(source, recursive) {
      Camera.prototype.copy.call(this, source, recursive);
      this.fov = source.fov;
      this.zoom = source.zoom;
      this.near = source.near;
      this.far = source.far;
      this.focus = source.focus;
      this.aspect = source.aspect;
      this.view = source.view === null ? null : Object.assign({}, source.view);
      this.filmGauge = source.filmGauge;
      this.filmOffset = source.filmOffset;
      return this;
    },
    setFocalLength: function(focalLength) {
      var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
      this.fov = _Math.RAD2DEG * 2 * Math.atan(vExtentSlope);
      this.updateProjectionMatrix();
    },
    getFocalLength: function() {
      var vExtentSlope = Math.tan(_Math.DEG2RAD * 0.5 * this.fov);
      return 0.5 * this.getFilmHeight() / vExtentSlope;
    },
    getEffectiveFOV: function() {
      return _Math.RAD2DEG * 2 * Math.atan(Math.tan(_Math.DEG2RAD * 0.5 * this.fov) / this.zoom);
    },
    getFilmWidth: function() {
      return this.filmGauge * Math.min(this.aspect, 1);
    },
    getFilmHeight: function() {
      return this.filmGauge / Math.max(this.aspect, 1);
    },
    setViewOffset: function(fullWidth, fullHeight, x, y, width, height) {
      this.aspect = fullWidth / fullHeight;
      if (this.view === null) {
        this.view = {
          enabled: true,
          fullWidth: 1,
          fullHeight: 1,
          offsetX: 0,
          offsetY: 0,
          width: 1,
          height: 1
        };
      }
      this.view.enabled = true;
      this.view.fullWidth = fullWidth;
      this.view.fullHeight = fullHeight;
      this.view.offsetX = x;
      this.view.offsetY = y;
      this.view.width = width;
      this.view.height = height;
      this.updateProjectionMatrix();
    },
    clearViewOffset: function() {
      if (this.view !== null) {
        this.view.enabled = false;
      }
      this.updateProjectionMatrix();
    },
    updateProjectionMatrix: function() {
      var near = this.near,
          top = near * Math.tan(_Math.DEG2RAD * 0.5 * this.fov) / this.zoom,
          height = 2 * top,
          width = this.aspect * height,
          left = -0.5 * width,
          view = this.view;
      if (this.view !== null && this.view.enabled) {
        var fullWidth = view.fullWidth,
            fullHeight = view.fullHeight;
        left += view.offsetX * width / fullWidth;
        top -= view.offsetY * height / fullHeight;
        width *= view.width / fullWidth;
        height *= view.height / fullHeight;
      }
      var skew = this.filmOffset;
      if (skew !== 0)
        left += near * skew / this.getFilmWidth();
      this.projectionMatrix.makePerspective(left, left + width, top, top - height, near, this.far);
    },
    toJSON: function(meta) {
      var data = Object3D.prototype.toJSON.call(this, meta);
      data.object.fov = this.fov;
      data.object.zoom = this.zoom;
      data.object.near = this.near;
      data.object.far = this.far;
      data.object.focus = this.focus;
      data.object.aspect = this.aspect;
      if (this.view !== null)
        data.object.view = Object.assign({}, this.view);
      data.object.filmGauge = this.filmGauge;
      data.object.filmOffset = this.filmOffset;
      return data;
    }
  });
  function ArrayCamera(array) {
    PerspectiveCamera.call(this);
    this.cameras = array || [];
  }
  ArrayCamera.prototype = Object.assign(Object.create(PerspectiveCamera.prototype), {
    constructor: ArrayCamera,
    isArrayCamera: true
  });
  function WebVRManager(renderer) {
    var scope = this;
    var device = null;
    var frameData = null;
    if (typeof window !== 'undefined' && 'VRFrameData' in window) {
      frameData = new window.VRFrameData();
    }
    var matrixWorldInverse = new Matrix4();
    var standingMatrix = new Matrix4();
    var standingMatrixInverse = new Matrix4();
    var cameraL = new PerspectiveCamera();
    cameraL.bounds = new Vector4(0.0, 0.0, 0.5, 1.0);
    cameraL.layers.enable(1);
    var cameraR = new PerspectiveCamera();
    cameraR.bounds = new Vector4(0.5, 0.0, 0.5, 1.0);
    cameraR.layers.enable(2);
    var cameraVR = new ArrayCamera([cameraL, cameraR]);
    cameraVR.layers.enable(1);
    cameraVR.layers.enable(2);
    var currentSize,
        currentPixelRatio;
    function onVRDisplayPresentChange() {
      if (device !== null && device.isPresenting) {
        var eyeParameters = device.getEyeParameters('left');
        var renderWidth = eyeParameters.renderWidth;
        var renderHeight = eyeParameters.renderHeight;
        currentPixelRatio = renderer.getPixelRatio();
        currentSize = renderer.getSize();
        renderer.setDrawingBufferSize(renderWidth * 2, renderHeight, 1);
      } else if (scope.enabled) {
        renderer.setDrawingBufferSize(currentSize.width, currentSize.height, currentPixelRatio);
      }
    }
    if (typeof window !== 'undefined') {
      window.addEventListener('vrdisplaypresentchange', onVRDisplayPresentChange, false);
    }
    this.enabled = false;
    this.standing = false;
    this.getDevice = function() {
      return device;
    };
    this.setDevice = function(value) {
      if (value !== undefined)
        device = value;
    };
    this.getCamera = function(camera) {
      if (device === null)
        return camera;
      device.depthNear = camera.near;
      device.depthFar = camera.far;
      device.getFrameData(frameData);
      var pose = frameData.pose;
      if (pose.position !== null) {
        camera.position.fromArray(pose.position);
      } else {
        camera.position.set(0, 0, 0);
      }
      if (pose.orientation !== null) {
        camera.quaternion.fromArray(pose.orientation);
      }
      camera.updateMatrixWorld();
      var stageParameters = device.stageParameters;
      if (this.standing && stageParameters) {
        standingMatrix.fromArray(stageParameters.sittingToStandingTransform);
        standingMatrixInverse.getInverse(standingMatrix);
        camera.matrixWorld.multiply(standingMatrix);
        camera.matrixWorldInverse.multiply(standingMatrixInverse);
      }
      if (device.isPresenting === false)
        return camera;
      cameraL.near = camera.near;
      cameraR.near = camera.near;
      cameraL.far = camera.far;
      cameraR.far = camera.far;
      cameraVR.matrixWorld.copy(camera.matrixWorld);
      cameraVR.matrixWorldInverse.copy(camera.matrixWorldInverse);
      cameraL.matrixWorldInverse.fromArray(frameData.leftViewMatrix);
      cameraR.matrixWorldInverse.fromArray(frameData.rightViewMatrix);
      if (this.standing && stageParameters) {
        cameraL.matrixWorldInverse.multiply(standingMatrixInverse);
        cameraR.matrixWorldInverse.multiply(standingMatrixInverse);
      }
      var parent = camera.parent;
      if (parent !== null) {
        matrixWorldInverse.getInverse(parent.matrixWorld);
        cameraL.matrixWorldInverse.multiply(matrixWorldInverse);
        cameraR.matrixWorldInverse.multiply(matrixWorldInverse);
      }
      cameraL.matrixWorld.getInverse(cameraL.matrixWorldInverse);
      cameraR.matrixWorld.getInverse(cameraR.matrixWorldInverse);
      cameraL.projectionMatrix.fromArray(frameData.leftProjectionMatrix);
      cameraR.projectionMatrix.fromArray(frameData.rightProjectionMatrix);
      cameraVR.projectionMatrix.copy(cameraL.projectionMatrix);
      var layers = device.getLayers();
      if (layers.length) {
        var layer = layers[0];
        if (layer.leftBounds !== null && layer.leftBounds.length === 4) {
          cameraL.bounds.fromArray(layer.leftBounds);
        }
        if (layer.rightBounds !== null && layer.rightBounds.length === 4) {
          cameraR.bounds.fromArray(layer.rightBounds);
        }
      }
      return cameraVR;
    };
    this.getStandingMatrix = function() {
      return standingMatrix;
    };
    this.submitFrame = function() {
      if (device && device.isPresenting)
        device.submitFrame();
    };
    this.dispose = function() {
      if (typeof window !== 'undefined') {
        window.removeEventListener('vrdisplaypresentchange', onVRDisplayPresentChange);
      }
    };
  }
  function WebGLExtensions(gl) {
    var extensions = {};
    return {get: function(name) {
        if (extensions[name] !== undefined) {
          return extensions[name];
        }
        var extension;
        switch (name) {
          case 'WEBGL_depth_texture':
            extension = gl.getExtension('WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture') || gl.getExtension('WEBKIT_WEBGL_depth_texture');
            break;
          case 'EXT_texture_filter_anisotropic':
            extension = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
            break;
          case 'WEBGL_compressed_texture_s3tc':
            extension = gl.getExtension('WEBGL_compressed_texture_s3tc') || gl.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
            break;
          case 'WEBGL_compressed_texture_pvrtc':
            extension = gl.getExtension('WEBGL_compressed_texture_pvrtc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');
            break;
          case 'WEBGL_compressed_texture_etc1':
            extension = gl.getExtension('WEBGL_compressed_texture_etc1');
            break;
          default:
            extension = gl.getExtension(name);
        }
        if (extension === null) {
          console.warn('THREE.WebGLRenderer: ' + name + ' extension not supported.');
        }
        extensions[name] = extension;
        return extension;
      }};
  }
  function WebGLClipping() {
    var scope = this,
        globalState = null,
        numGlobalPlanes = 0,
        localClippingEnabled = false,
        renderingShadows = false,
        plane = new Plane(),
        viewNormalMatrix = new Matrix3(),
        uniform = {
          value: null,
          needsUpdate: false
        };
    this.uniform = uniform;
    this.numPlanes = 0;
    this.numIntersection = 0;
    this.init = function(planes, enableLocalClipping, camera) {
      var enabled = planes.length !== 0 || enableLocalClipping || numGlobalPlanes !== 0 || localClippingEnabled;
      localClippingEnabled = enableLocalClipping;
      globalState = projectPlanes(planes, camera, 0);
      numGlobalPlanes = planes.length;
      return enabled;
    };
    this.beginShadows = function() {
      renderingShadows = true;
      projectPlanes(null);
    };
    this.endShadows = function() {
      renderingShadows = false;
      resetGlobalState();
    };
    this.setState = function(planes, clipIntersection, clipShadows, camera, cache, fromCache) {
      if (!localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && !clipShadows) {
        if (renderingShadows) {
          projectPlanes(null);
        } else {
          resetGlobalState();
        }
      } else {
        var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
            lGlobal = nGlobal * 4,
            dstArray = cache.clippingState || null;
        uniform.value = dstArray;
        dstArray = projectPlanes(planes, camera, lGlobal, fromCache);
        for (var i = 0; i !== lGlobal; ++i) {
          dstArray[i] = globalState[i];
        }
        cache.clippingState = dstArray;
        this.numIntersection = clipIntersection ? this.numPlanes : 0;
        this.numPlanes += nGlobal;
      }
    };
    function resetGlobalState() {
      if (uniform.value !== globalState) {
        uniform.value = globalState;
        uniform.needsUpdate = numGlobalPlanes > 0;
      }
      scope.numPlanes = numGlobalPlanes;
      scope.numIntersection = 0;
    }
    function projectPlanes(planes, camera, dstOffset, skipTransform) {
      var nPlanes = planes !== null ? planes.length : 0,
          dstArray = null;
      if (nPlanes !== 0) {
        dstArray = uniform.value;
        if (skipTransform !== true || dstArray === null) {
          var flatSize = dstOffset + nPlanes * 4,
              viewMatrix = camera.matrixWorldInverse;
          viewNormalMatrix.getNormalMatrix(viewMatrix);
          if (dstArray === null || dstArray.length < flatSize) {
            dstArray = new Float32Array(flatSize);
          }
          for (var i = 0,
              i4 = dstOffset; i !== nPlanes; ++i, i4 += 4) {
            plane.copy(planes[i]).applyMatrix4(viewMatrix, viewNormalMatrix);
            plane.normal.toArray(dstArray, i4);
            dstArray[i4 + 3] = plane.constant;
          }
        }
        uniform.value = dstArray;
        uniform.needsUpdate = true;
      }
      scope.numPlanes = nPlanes;
      return dstArray;
    }
  }
  function WebGLUtils(gl, extensions) {
    function convert(p) {
      var extension;
      if (p === RepeatWrapping)
        return gl.REPEAT;
      if (p === ClampToEdgeWrapping)
        return gl.CLAMP_TO_EDGE;
      if (p === MirroredRepeatWrapping)
        return gl.MIRRORED_REPEAT;
      if (p === NearestFilter)
        return gl.NEAREST;
      if (p === NearestMipMapNearestFilter)
        return gl.NEAREST_MIPMAP_NEAREST;
      if (p === NearestMipMapLinearFilter)
        return gl.NEAREST_MIPMAP_LINEAR;
      if (p === LinearFilter)
        return gl.LINEAR;
      if (p === LinearMipMapNearestFilter)
        return gl.LINEAR_MIPMAP_NEAREST;
      if (p === LinearMipMapLinearFilter)
        return gl.LINEAR_MIPMAP_LINEAR;
      if (p === UnsignedByteType)
        return gl.UNSIGNED_BYTE;
      if (p === UnsignedShort4444Type)
        return gl.UNSIGNED_SHORT_4_4_4_4;
      if (p === UnsignedShort5551Type)
        return gl.UNSIGNED_SHORT_5_5_5_1;
      if (p === UnsignedShort565Type)
        return gl.UNSIGNED_SHORT_5_6_5;
      if (p === ByteType)
        return gl.BYTE;
      if (p === ShortType)
        return gl.SHORT;
      if (p === UnsignedShortType)
        return gl.UNSIGNED_SHORT;
      if (p === IntType)
        return gl.INT;
      if (p === UnsignedIntType)
        return gl.UNSIGNED_INT;
      if (p === FloatType)
        return gl.FLOAT;
      if (p === HalfFloatType) {
        extension = extensions.get('OES_texture_half_float');
        if (extension !== null)
          return extension.HALF_FLOAT_OES;
      }
      if (p === AlphaFormat)
        return gl.ALPHA;
      if (p === RGBFormat)
        return gl.RGB;
      if (p === RGBAFormat)
        return gl.RGBA;
      if (p === LuminanceFormat)
        return gl.LUMINANCE;
      if (p === LuminanceAlphaFormat)
        return gl.LUMINANCE_ALPHA;
      if (p === DepthFormat)
        return gl.DEPTH_COMPONENT;
      if (p === DepthStencilFormat)
        return gl.DEPTH_STENCIL;
      if (p === AddEquation)
        return gl.FUNC_ADD;
      if (p === SubtractEquation)
        return gl.FUNC_SUBTRACT;
      if (p === ReverseSubtractEquation)
        return gl.FUNC_REVERSE_SUBTRACT;
      if (p === ZeroFactor)
        return gl.ZERO;
      if (p === OneFactor)
        return gl.ONE;
      if (p === SrcColorFactor)
        return gl.SRC_COLOR;
      if (p === OneMinusSrcColorFactor)
        return gl.ONE_MINUS_SRC_COLOR;
      if (p === SrcAlphaFactor)
        return gl.SRC_ALPHA;
      if (p === OneMinusSrcAlphaFactor)
        return gl.ONE_MINUS_SRC_ALPHA;
      if (p === DstAlphaFactor)
        return gl.DST_ALPHA;
      if (p === OneMinusDstAlphaFactor)
        return gl.ONE_MINUS_DST_ALPHA;
      if (p === DstColorFactor)
        return gl.DST_COLOR;
      if (p === OneMinusDstColorFactor)
        return gl.ONE_MINUS_DST_COLOR;
      if (p === SrcAlphaSaturateFactor)
        return gl.SRC_ALPHA_SATURATE;
      if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
        extension = extensions.get('WEBGL_compressed_texture_s3tc');
        if (extension !== null) {
          if (p === RGB_S3TC_DXT1_Format)
            return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
          if (p === RGBA_S3TC_DXT1_Format)
            return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
          if (p === RGBA_S3TC_DXT3_Format)
            return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
          if (p === RGBA_S3TC_DXT5_Format)
            return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
        }
      }
      if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
        extension = extensions.get('WEBGL_compressed_texture_pvrtc');
        if (extension !== null) {
          if (p === RGB_PVRTC_4BPPV1_Format)
            return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
          if (p === RGB_PVRTC_2BPPV1_Format)
            return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
          if (p === RGBA_PVRTC_4BPPV1_Format)
            return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
          if (p === RGBA_PVRTC_2BPPV1_Format)
            return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
        }
      }
      if (p === RGB_ETC1_Format) {
        extension = extensions.get('WEBGL_compressed_texture_etc1');
        if (extension !== null)
          return extension.COMPRESSED_RGB_ETC1_WEBGL;
      }
      if (p === MinEquation || p === MaxEquation) {
        extension = extensions.get('EXT_blend_minmax');
        if (extension !== null) {
          if (p === MinEquation)
            return extension.MIN_EXT;
          if (p === MaxEquation)
            return extension.MAX_EXT;
        }
      }
      if (p === UnsignedInt248Type) {
        extension = extensions.get('WEBGL_depth_texture');
        if (extension !== null)
          return extension.UNSIGNED_INT_24_8_WEBGL;
      }
      return 0;
    }
    return {convert: convert};
  }
  function WebGLRenderer(parameters) {
    console.log('THREE.WebGLRenderer', REVISION);
    parameters = parameters || {};
    var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas'),
        _context = parameters.context !== undefined ? parameters.context : null,
        _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
        _depth = parameters.depth !== undefined ? parameters.depth : true,
        _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
        _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
        _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
        _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false;
    var lightsArray = [];
    var shadowsArray = [];
    var currentRenderList = null;
    var spritesArray = [];
    var flaresArray = [];
    this.domElement = _canvas;
    this.context = null;
    this.autoClear = true;
    this.autoClearColor = true;
    this.autoClearDepth = true;
    this.autoClearStencil = true;
    this.sortObjects = true;
    this.clippingPlanes = [];
    this.localClippingEnabled = false;
    this.gammaFactor = 2.0;
    this.gammaInput = false;
    this.gammaOutput = false;
    this.physicallyCorrectLights = false;
    this.toneMapping = LinearToneMapping;
    this.toneMappingExposure = 1.0;
    this.toneMappingWhitePoint = 1.0;
    this.maxMorphTargets = 8;
    this.maxMorphNormals = 4;
    var _this = this,
        _isContextLost = false,
        _currentRenderTarget = null,
        _currentFramebuffer = null,
        _currentMaterialId = -1,
        _currentGeometryProgram = '',
        _currentCamera = null,
        _currentArrayCamera = null,
        _currentViewport = new Vector4(),
        _currentScissor = new Vector4(),
        _currentScissorTest = null,
        _usedTextureUnits = 0,
        _width = _canvas.width,
        _height = _canvas.height,
        _pixelRatio = 1,
        _viewport = new Vector4(0, 0, _width, _height),
        _scissor = new Vector4(0, 0, _width, _height),
        _scissorTest = false,
        _frustum = new Frustum(),
        _clipping = new WebGLClipping(),
        _clippingEnabled = false,
        _localClippingEnabled = false,
        _projScreenMatrix = new Matrix4(),
        _vector3 = new Vector3(),
        _infoMemory = {
          geometries: 0,
          textures: 0
        },
        _infoRender = {
          frame: 0,
          calls: 0,
          vertices: 0,
          faces: 0,
          points: 0
        };
    this.info = {
      render: _infoRender,
      memory: _infoMemory,
      programs: null
    };
    function getTargetPixelRatio() {
      return _currentRenderTarget === null ? _pixelRatio : 1;
    }
    var _gl;
    try {
      var contextAttributes = {
        alpha: _alpha,
        depth: _depth,
        stencil: _stencil,
        antialias: _antialias,
        premultipliedAlpha: _premultipliedAlpha,
        preserveDrawingBuffer: _preserveDrawingBuffer
      };
      _gl = _context || _canvas.getContext('webgl', contextAttributes) || _canvas.getContext('experimental-webgl', contextAttributes);
      if (_gl === null) {
        if (_canvas.getContext('webgl') !== null) {
          throw 'Error creating WebGL context with your selected attributes.';
        } else {
          throw 'Error creating WebGL context.';
        }
      }
      if (_gl.getShaderPrecisionFormat === undefined) {
        _gl.getShaderPrecisionFormat = function() {
          return {
            'rangeMin': 1,
            'rangeMax': 1,
            'precision': 1
          };
        };
      }
      _canvas.addEventListener('webglcontextlost', onContextLost, false);
      _canvas.addEventListener('webglcontextrestored', onContextRestore, false);
    } catch (error) {
      console.error('THREE.WebGLRenderer: ' + error);
    }
    var extensions,
        capabilities,
        state;
    var properties,
        textures,
        attributes,
        geometries,
        objects,
        lights;
    var programCache,
        renderLists;
    var background,
        morphtargets,
        bufferRenderer,
        indexedBufferRenderer;
    var flareRenderer,
        spriteRenderer;
    var utils;
    function initGLContext() {
      extensions = new WebGLExtensions(_gl);
      extensions.get('WEBGL_depth_texture');
      extensions.get('OES_texture_float');
      extensions.get('OES_texture_float_linear');
      extensions.get('OES_texture_half_float');
      extensions.get('OES_texture_half_float_linear');
      extensions.get('OES_standard_derivatives');
      extensions.get('OES_element_index_uint');
      extensions.get('ANGLE_instanced_arrays');
      utils = new WebGLUtils(_gl, extensions);
      capabilities = new WebGLCapabilities(_gl, extensions, parameters);
      state = new WebGLState(_gl, extensions, utils);
      state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio));
      state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio));
      properties = new WebGLProperties();
      textures = new WebGLTextures(_gl, extensions, state, properties, capabilities, utils, _infoMemory);
      attributes = new WebGLAttributes(_gl);
      geometries = new WebGLGeometries(_gl, attributes, _infoMemory);
      objects = new WebGLObjects(geometries, _infoRender);
      morphtargets = new WebGLMorphtargets(_gl);
      programCache = new WebGLPrograms(_this, extensions, capabilities);
      lights = new WebGLLights();
      renderLists = new WebGLRenderLists();
      background = new WebGLBackground(_this, state, geometries, _premultipliedAlpha);
      bufferRenderer = new WebGLBufferRenderer(_gl, extensions, _infoRender);
      indexedBufferRenderer = new WebGLIndexedBufferRenderer(_gl, extensions, _infoRender);
      flareRenderer = new WebGLFlareRenderer(_this, _gl, state, textures, capabilities);
      spriteRenderer = new WebGLSpriteRenderer(_this, _gl, state, textures, capabilities);
      _this.info.programs = programCache.programs;
      _this.context = _gl;
      _this.capabilities = capabilities;
      _this.extensions = extensions;
      _this.properties = properties;
      _this.renderLists = renderLists;
      _this.state = state;
    }
    initGLContext();
    var vr = new WebVRManager(_this);
    this.vr = vr;
    var shadowMap = new WebGLShadowMap(_this, objects, capabilities.maxTextureSize);
    this.shadowMap = shadowMap;
    this.getContext = function() {
      return _gl;
    };
    this.getContextAttributes = function() {
      return _gl.getContextAttributes();
    };
    this.forceContextLoss = function() {
      var extension = extensions.get('WEBGL_lose_context');
      if (extension)
        extension.loseContext();
    };
    this.forceContextRestore = function() {
      var extension = extensions.get('WEBGL_lose_context');
      if (extension)
        extension.restoreContext();
    };
    this.getPixelRatio = function() {
      return _pixelRatio;
    };
    this.setPixelRatio = function(value) {
      if (value === undefined)
        return;
      _pixelRatio = value;
      this.setSize(_width, _height, false);
    };
    this.getSize = function() {
      return {
        width: _width,
        height: _height
      };
    };
    this.setSize = function(width, height, updateStyle) {
      var device = vr.getDevice();
      if (device && device.isPresenting) {
        console.warn('THREE.WebGLRenderer: Can\'t change size while VR device is presenting.');
        return;
      }
      _width = width;
      _height = height;
      _canvas.width = width * _pixelRatio;
      _canvas.height = height * _pixelRatio;
      if (updateStyle !== false) {
        _canvas.style.width = width + 'px';
        _canvas.style.height = height + 'px';
      }
      this.setViewport(0, 0, width, height);
    };
    this.getDrawingBufferSize = function() {
      return {
        width: _width * _pixelRatio,
        height: _height * _pixelRatio
      };
    };
    this.setDrawingBufferSize = function(width, height, pixelRatio) {
      _width = width;
      _height = height;
      _pixelRatio = pixelRatio;
      _canvas.width = width * pixelRatio;
      _canvas.height = height * pixelRatio;
      this.setViewport(0, 0, width, height);
    };
    this.setViewport = function(x, y, width, height) {
      _viewport.set(x, _height - y - height, width, height);
      state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio));
    };
    this.setScissor = function(x, y, width, height) {
      _scissor.set(x, _height - y - height, width, height);
      state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio));
    };
    this.setScissorTest = function(boolean) {
      state.setScissorTest(_scissorTest = boolean);
    };
    this.getClearColor = function() {
      return background.getClearColor();
    };
    this.setClearColor = function() {
      background.setClearColor.apply(background, arguments);
    };
    this.getClearAlpha = function() {
      return background.getClearAlpha();
    };
    this.setClearAlpha = function() {
      background.setClearAlpha.apply(background, arguments);
    };
    this.clear = function(color, depth, stencil) {
      var bits = 0;
      if (color === undefined || color)
        bits |= _gl.COLOR_BUFFER_BIT;
      if (depth === undefined || depth)
        bits |= _gl.DEPTH_BUFFER_BIT;
      if (stencil === undefined || stencil)
        bits |= _gl.STENCIL_BUFFER_BIT;
      _gl.clear(bits);
    };
    this.clearColor = function() {
      this.clear(true, false, false);
    };
    this.clearDepth = function() {
      this.clear(false, true, false);
    };
    this.clearStencil = function() {
      this.clear(false, false, true);
    };
    this.clearTarget = function(renderTarget, color, depth, stencil) {
      this.setRenderTarget(renderTarget);
      this.clear(color, depth, stencil);
    };
    this.dispose = function() {
      _canvas.removeEventListener('webglcontextlost', onContextLost, false);
      _canvas.removeEventListener('webglcontextrestored', onContextRestore, false);
      renderLists.dispose();
      vr.dispose();
    };
    function onContextLost(event) {
      event.preventDefault();
      console.log('THREE.WebGLRenderer: Context Lost.');
      _isContextLost = true;
    }
    function onContextRestore() {
      console.log('THREE.WebGLRenderer: Context Restored.');
      _isContextLost = false;
      initGLContext();
    }
    function onMaterialDispose(event) {
      var material = event.target;
      material.removeEventListener('dispose', onMaterialDispose);
      deallocateMaterial(material);
    }
    function deallocateMaterial(material) {
      releaseMaterialProgramReference(material);
      properties.remove(material);
    }
    function releaseMaterialProgramReference(material) {
      var programInfo = properties.get(material).program;
      material.program = undefined;
      if (programInfo !== undefined) {
        programCache.releaseProgram(programInfo);
      }
    }
    function renderObjectImmediate(object, program, material) {
      object.render(function(object) {
        _this.renderBufferImmediate(object, program, material);
      });
    }
    this.renderBufferImmediate = function(object, program, material) {
      state.initAttributes();
      var buffers = properties.get(object);
      if (object.hasPositions && !buffers.position)
        buffers.position = _gl.createBuffer();
      if (object.hasNormals && !buffers.normal)
        buffers.normal = _gl.createBuffer();
      if (object.hasUvs && !buffers.uv)
        buffers.uv = _gl.createBuffer();
      if (object.hasColors && !buffers.color)
        buffers.color = _gl.createBuffer();
      var programAttributes = program.getAttributes();
      if (object.hasPositions) {
        _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.position);
        _gl.bufferData(_gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW);
        state.enableAttribute(programAttributes.position);
        _gl.vertexAttribPointer(programAttributes.position, 3, _gl.FLOAT, false, 0, 0);
      }
      if (object.hasNormals) {
        _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.normal);
        if (!material.isMeshPhongMaterial && !material.isMeshStandardMaterial && !material.isMeshNormalMaterial && material.flatShading === true) {
          for (var i = 0,
              l = object.count * 3; i < l; i += 9) {
            var array = object.normalArray;
            var nx = (array[i + 0] + array[i + 3] + array[i + 6]) / 3;
            var ny = (array[i + 1] + array[i + 4] + array[i + 7]) / 3;
            var nz = (array[i + 2] + array[i + 5] + array[i + 8]) / 3;
            array[i + 0] = nx;
            array[i + 1] = ny;
            array[i + 2] = nz;
            array[i + 3] = nx;
            array[i + 4] = ny;
            array[i + 5] = nz;
            array[i + 6] = nx;
            array[i + 7] = ny;
            array[i + 8] = nz;
          }
        }
        _gl.bufferData(_gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW);
        state.enableAttribute(programAttributes.normal);
        _gl.vertexAttribPointer(programAttributes.normal, 3, _gl.FLOAT, false, 0, 0);
      }
      if (object.hasUvs && material.map) {
        _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.uv);
        _gl.bufferData(_gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW);
        state.enableAttribute(programAttributes.uv);
        _gl.vertexAttribPointer(programAttributes.uv, 2, _gl.FLOAT, false, 0, 0);
      }
      if (object.hasColors && material.vertexColors !== NoColors) {
        _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.color);
        _gl.bufferData(_gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW);
        state.enableAttribute(programAttributes.color);
        _gl.vertexAttribPointer(programAttributes.color, 3, _gl.FLOAT, false, 0, 0);
      }
      state.disableUnusedAttributes();
      _gl.drawArrays(_gl.TRIANGLES, 0, object.count);
      object.count = 0;
    };
    this.renderBufferDirect = function(camera, fog, geometry, material, object, group) {
      state.setMaterial(material);
      var program = setProgram(camera, fog, material, object);
      var geometryProgram = geometry.id + '_' + program.id + '_' + (material.wireframe === true);
      var updateBuffers = false;
      if (geometryProgram !== _currentGeometryProgram) {
        _currentGeometryProgram = geometryProgram;
        updateBuffers = true;
      }
      if (object.morphTargetInfluences) {
        morphtargets.update(object, geometry, material, program);
        updateBuffers = true;
      }
      var index = geometry.index;
      var position = geometry.attributes.position;
      var rangeFactor = 1;
      if (material.wireframe === true) {
        index = geometries.getWireframeAttribute(geometry);
        rangeFactor = 2;
      }
      var attribute;
      var renderer = bufferRenderer;
      if (index !== null) {
        attribute = attributes.get(index);
        renderer = indexedBufferRenderer;
        renderer.setIndex(attribute);
      }
      if (updateBuffers) {
        setupVertexAttributes(material, program, geometry);
        if (index !== null) {
          _gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, attribute.buffer);
        }
      }
      var dataCount = 0;
      if (index !== null) {
        dataCount = index.count;
      } else if (position !== undefined) {
        dataCount = position.count;
      }
      var rangeStart = geometry.drawRange.start * rangeFactor;
      var rangeCount = geometry.drawRange.count * rangeFactor;
      var groupStart = group !== null ? group.start * rangeFactor : 0;
      var groupCount = group !== null ? group.count * rangeFactor : Infinity;
      var drawStart = Math.max(rangeStart, groupStart);
      var drawEnd = Math.min(dataCount, rangeStart + rangeCount, groupStart + groupCount) - 1;
      var drawCount = Math.max(0, drawEnd - drawStart + 1);
      if (drawCount === 0)
        return;
      if (object.isMesh) {
        if (material.wireframe === true) {
          state.setLineWidth(material.wireframeLinewidth * getTargetPixelRatio());
          renderer.setMode(_gl.LINES);
        } else {
          switch (object.drawMode) {
            case TrianglesDrawMode:
              renderer.setMode(_gl.TRIANGLES);
              break;
            case TriangleStripDrawMode:
              renderer.setMode(_gl.TRIANGLE_STRIP);
              break;
            case TriangleFanDrawMode:
              renderer.setMode(_gl.TRIANGLE_FAN);
              break;
          }
        }
      } else if (object.isLine) {
        var lineWidth = material.linewidth;
        if (lineWidth === undefined)
          lineWidth = 1;
        state.setLineWidth(lineWidth * getTargetPixelRatio());
        if (object.isLineSegments) {
          renderer.setMode(_gl.LINES);
        } else if (object.isLineLoop) {
          renderer.setMode(_gl.LINE_LOOP);
        } else {
          renderer.setMode(_gl.LINE_STRIP);
        }
      } else if (object.isPoints) {
        renderer.setMode(_gl.POINTS);
      }
      if (geometry && geometry.isInstancedBufferGeometry) {
        if (geometry.maxInstancedCount > 0) {
          renderer.renderInstances(geometry, drawStart, drawCount);
        }
      } else {
        renderer.render(drawStart, drawCount);
      }
    };
    function setupVertexAttributes(material, program, geometry, startIndex) {
      if (geometry && geometry.isInstancedBufferGeometry) {
        if (extensions.get('ANGLE_instanced_arrays') === null) {
          console.error('THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');
          return;
        }
      }
      if (startIndex === undefined)
        startIndex = 0;
      state.initAttributes();
      var geometryAttributes = geometry.attributes;
      var programAttributes = program.getAttributes();
      var materialDefaultAttributeValues = material.defaultAttributeValues;
      for (var name in programAttributes) {
        var programAttribute = programAttributes[name];
        if (programAttribute >= 0) {
          var geometryAttribute = geometryAttributes[name];
          if (geometryAttribute !== undefined) {
            var normalized = geometryAttribute.normalized;
            var size = geometryAttribute.itemSize;
            var attribute = attributes.get(geometryAttribute);
            if (attribute === undefined)
              continue;
            var buffer = attribute.buffer;
            var type = attribute.type;
            var bytesPerElement = attribute.bytesPerElement;
            if (geometryAttribute.isInterleavedBufferAttribute) {
              var data = geometryAttribute.data;
              var stride = data.stride;
              var offset = geometryAttribute.offset;
              if (data && data.isInstancedInterleavedBuffer) {
                state.enableAttributeAndDivisor(programAttribute, data.meshPerAttribute);
                if (geometry.maxInstancedCount === undefined) {
                  geometry.maxInstancedCount = data.meshPerAttribute * data.count;
                }
              } else {
                state.enableAttribute(programAttribute);
              }
              _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer);
              _gl.vertexAttribPointer(programAttribute, size, type, normalized, stride * bytesPerElement, (startIndex * stride + offset) * bytesPerElement);
            } else {
              if (geometryAttribute.isInstancedBufferAttribute) {
                state.enableAttributeAndDivisor(programAttribute, geometryAttribute.meshPerAttribute);
                if (geometry.maxInstancedCount === undefined) {
                  geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
                }
              } else {
                state.enableAttribute(programAttribute);
              }
              _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer);
              _gl.vertexAttribPointer(programAttribute, size, type, normalized, 0, startIndex * size * bytesPerElement);
            }
          } else if (materialDefaultAttributeValues !== undefined) {
            var value = materialDefaultAttributeValues[name];
            if (value !== undefined) {
              switch (value.length) {
                case 2:
                  _gl.vertexAttrib2fv(programAttribute, value);
                  break;
                case 3:
                  _gl.vertexAttrib3fv(programAttribute, value);
                  break;
                case 4:
                  _gl.vertexAttrib4fv(programAttribute, value);
                  break;
                default:
                  _gl.vertexAttrib1fv(programAttribute, value);
              }
            }
          }
        }
      }
      state.disableUnusedAttributes();
    }
    this.compile = function(scene, camera) {
      lightsArray.length = 0;
      shadowsArray.length = 0;
      scene.traverse(function(object) {
        if (object.isLight) {
          lightsArray.push(object);
          if (object.castShadow) {
            shadowsArray.push(object);
          }
        }
      });
      lights.setup(lightsArray, shadowsArray, camera);
      scene.traverse(function(object) {
        if (object.material) {
          if (Array.isArray(object.material)) {
            for (var i = 0; i < object.material.length; i++) {
              initMaterial(object.material[i], scene.fog, object);
            }
          } else {
            initMaterial(object.material, scene.fog, object);
          }
        }
      });
    };
    var isAnimating = false;
    var onAnimationFrame = null;
    function start() {
      if (isAnimating)
        return;
      var device = vr.getDevice();
      if (device && device.isPresenting) {
        device.requestAnimationFrame(loop);
      } else {
        window.requestAnimationFrame(loop);
      }
      isAnimating = true;
    }
    function loop(time) {
      if (onAnimationFrame !== null)
        onAnimationFrame(time);
      var device = vr.getDevice();
      if (device && device.isPresenting) {
        device.requestAnimationFrame(loop);
      } else {
        window.requestAnimationFrame(loop);
      }
    }
    this.animate = function(callback) {
      onAnimationFrame = callback;
      start();
    };
    this.render = function(scene, camera, renderTarget, forceClear) {
      if (!(camera && camera.isCamera)) {
        console.error('THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.');
        return;
      }
      if (_isContextLost)
        return;
      _currentGeometryProgram = '';
      _currentMaterialId = -1;
      _currentCamera = null;
      if (scene.autoUpdate === true)
        scene.updateMatrixWorld();
      if (camera.parent === null)
        camera.updateMatrixWorld();
      if (vr.enabled) {
        camera = vr.getCamera(camera);
      }
      _projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
      _frustum.setFromMatrix(_projScreenMatrix);
      lightsArray.length = 0;
      shadowsArray.length = 0;
      spritesArray.length = 0;
      flaresArray.length = 0;
      _localClippingEnabled = this.localClippingEnabled;
      _clippingEnabled = _clipping.init(this.clippingPlanes, _localClippingEnabled, camera);
      currentRenderList = renderLists.get(scene, camera);
      currentRenderList.init();
      projectObject(scene, camera, _this.sortObjects);
      if (_this.sortObjects === true) {
        currentRenderList.sort();
      }
      if (_clippingEnabled)
        _clipping.beginShadows();
      shadowMap.render(shadowsArray, scene, camera);
      lights.setup(lightsArray, shadowsArray, camera);
      if (_clippingEnabled)
        _clipping.endShadows();
      _infoRender.frame++;
      _infoRender.calls = 0;
      _infoRender.vertices = 0;
      _infoRender.faces = 0;
      _infoRender.points = 0;
      if (renderTarget === undefined) {
        renderTarget = null;
      }
      this.setRenderTarget(renderTarget);
      background.render(currentRenderList, scene, camera, forceClear);
      var opaqueObjects = currentRenderList.opaque;
      var transparentObjects = currentRenderList.transparent;
      if (scene.overrideMaterial) {
        var overrideMaterial = scene.overrideMaterial;
        if (opaqueObjects.length)
          renderObjects(opaqueObjects, scene, camera, overrideMaterial);
        if (transparentObjects.length)
          renderObjects(transparentObjects, scene, camera, overrideMaterial);
      } else {
        if (opaqueObjects.length)
          renderObjects(opaqueObjects, scene, camera);
        if (transparentObjects.length)
          renderObjects(transparentObjects, scene, camera);
      }
      spriteRenderer.render(spritesArray, scene, camera);
      flareRenderer.render(flaresArray, scene, camera, _currentViewport);
      if (renderTarget) {
        textures.updateRenderTargetMipmap(renderTarget);
      }
      state.buffers.depth.setTest(true);
      state.buffers.depth.setMask(true);
      state.buffers.color.setMask(true);
      state.setPolygonOffset(false);
      if (vr.enabled) {
        vr.submitFrame();
      }
    };
    function projectObject(object, camera, sortObjects) {
      if (object.visible === false)
        return;
      var visible = object.layers.test(camera.layers);
      if (visible) {
        if (object.isLight) {
          lightsArray.push(object);
          if (object.castShadow) {
            shadowsArray.push(object);
          }
        } else if (object.isSprite) {
          if (!object.frustumCulled || _frustum.intersectsSprite(object)) {
            spritesArray.push(object);
          }
        } else if (object.isLensFlare) {
          flaresArray.push(object);
        } else if (object.isImmediateRenderObject) {
          if (sortObjects) {
            _vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix);
          }
          currentRenderList.push(object, null, object.material, _vector3.z, null);
        } else if (object.isMesh || object.isLine || object.isPoints) {
          if (object.isSkinnedMesh) {
            object.skeleton.update();
          }
          if (!object.frustumCulled || _frustum.intersectsObject(object)) {
            if (sortObjects) {
              _vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix);
            }
            var geometry = objects.update(object);
            var material = object.material;
            if (Array.isArray(material)) {
              var groups = geometry.groups;
              for (var i = 0,
                  l = groups.length; i < l; i++) {
                var group = groups[i];
                var groupMaterial = material[group.materialIndex];
                if (groupMaterial && groupMaterial.visible) {
                  currentRenderList.push(object, geometry, groupMaterial, _vector3.z, group);
                }
              }
            } else if (material.visible) {
              currentRenderList.push(object, geometry, material, _vector3.z, null);
            }
          }
        }
      }
      var children = object.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        projectObject(children[i], camera, sortObjects);
      }
    }
    function renderObjects(renderList, scene, camera, overrideMaterial) {
      for (var i = 0,
          l = renderList.length; i < l; i++) {
        var renderItem = renderList[i];
        var object = renderItem.object;
        var geometry = renderItem.geometry;
        var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
        var group = renderItem.group;
        if (camera.isArrayCamera) {
          _currentArrayCamera = camera;
          var cameras = camera.cameras;
          for (var j = 0,
              jl = cameras.length; j < jl; j++) {
            var camera2 = cameras[j];
            if (object.layers.test(camera2.layers)) {
              var bounds = camera2.bounds;
              var x = bounds.x * _width;
              var y = bounds.y * _height;
              var width = bounds.z * _width;
              var height = bounds.w * _height;
              state.viewport(_currentViewport.set(x, y, width, height).multiplyScalar(_pixelRatio));
              renderObject(object, scene, camera2, geometry, material, group);
            }
          }
        } else {
          _currentArrayCamera = null;
          renderObject(object, scene, camera, geometry, material, group);
        }
      }
    }
    function renderObject(object, scene, camera, geometry, material, group) {
      object.onBeforeRender(_this, scene, camera, geometry, material, group);
      object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld);
      object.normalMatrix.getNormalMatrix(object.modelViewMatrix);
      if (object.isImmediateRenderObject) {
        state.setMaterial(material);
        var program = setProgram(camera, scene.fog, material, object);
        _currentGeometryProgram = '';
        renderObjectImmediate(object, program, material);
      } else {
        _this.renderBufferDirect(camera, scene.fog, geometry, material, object, group);
      }
      object.onAfterRender(_this, scene, camera, geometry, material, group);
    }
    function initMaterial(material, fog, object) {
      var materialProperties = properties.get(material);
      var parameters = programCache.getParameters(material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object);
      var code = programCache.getProgramCode(material, parameters);
      var program = materialProperties.program;
      var programChange = true;
      if (program === undefined) {
        material.addEventListener('dispose', onMaterialDispose);
      } else if (program.code !== code) {
        releaseMaterialProgramReference(material);
      } else if (parameters.shaderID !== undefined) {
        return;
      } else {
        programChange = false;
      }
      if (programChange) {
        if (parameters.shaderID) {
          var shader = ShaderLib[parameters.shaderID];
          materialProperties.shader = {
            name: material.type,
            uniforms: UniformsUtils.clone(shader.uniforms),
            vertexShader: shader.vertexShader,
            fragmentShader: shader.fragmentShader
          };
        } else {
          materialProperties.shader = {
            name: material.type,
            uniforms: material.uniforms,
            vertexShader: material.vertexShader,
            fragmentShader: material.fragmentShader
          };
        }
        material.onBeforeCompile(materialProperties.shader);
        program = programCache.acquireProgram(material, materialProperties.shader, parameters, code);
        materialProperties.program = program;
        material.program = program;
      }
      var programAttributes = program.getAttributes();
      if (material.morphTargets) {
        material.numSupportedMorphTargets = 0;
        for (var i = 0; i < _this.maxMorphTargets; i++) {
          if (programAttributes['morphTarget' + i] >= 0) {
            material.numSupportedMorphTargets++;
          }
        }
      }
      if (material.morphNormals) {
        material.numSupportedMorphNormals = 0;
        for (var i = 0; i < _this.maxMorphNormals; i++) {
          if (programAttributes['morphNormal' + i] >= 0) {
            material.numSupportedMorphNormals++;
          }
        }
      }
      var uniforms = materialProperties.shader.uniforms;
      if (!material.isShaderMaterial && !material.isRawShaderMaterial || material.clipping === true) {
        materialProperties.numClippingPlanes = _clipping.numPlanes;
        materialProperties.numIntersection = _clipping.numIntersection;
        uniforms.clippingPlanes = _clipping.uniform;
      }
      materialProperties.fog = fog;
      materialProperties.lightsHash = lights.state.hash;
      if (material.lights) {
        uniforms.ambientLightColor.value = lights.state.ambient;
        uniforms.directionalLights.value = lights.state.directional;
        uniforms.spotLights.value = lights.state.spot;
        uniforms.rectAreaLights.value = lights.state.rectArea;
        uniforms.pointLights.value = lights.state.point;
        uniforms.hemisphereLights.value = lights.state.hemi;
        uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
        uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
        uniforms.spotShadowMap.value = lights.state.spotShadowMap;
        uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
        uniforms.pointShadowMap.value = lights.state.pointShadowMap;
        uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
      }
      var progUniforms = materialProperties.program.getUniforms(),
          uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms);
      materialProperties.uniformsList = uniformsList;
    }
    function setProgram(camera, fog, material, object) {
      _usedTextureUnits = 0;
      var materialProperties = properties.get(material);
      if (_clippingEnabled) {
        if (_localClippingEnabled || camera !== _currentCamera) {
          var useCache = camera === _currentCamera && material.id === _currentMaterialId;
          _clipping.setState(material.clippingPlanes, material.clipIntersection, material.clipShadows, camera, materialProperties, useCache);
        }
      }
      if (material.needsUpdate === false) {
        if (materialProperties.program === undefined) {
          material.needsUpdate = true;
        } else if (material.fog && materialProperties.fog !== fog) {
          material.needsUpdate = true;
        } else if (material.lights && materialProperties.lightsHash !== lights.state.hash) {
          material.needsUpdate = true;
        } else if (materialProperties.numClippingPlanes !== undefined && (materialProperties.numClippingPlanes !== _clipping.numPlanes || materialProperties.numIntersection !== _clipping.numIntersection)) {
          material.needsUpdate = true;
        }
      }
      if (material.needsUpdate) {
        initMaterial(material, fog, object);
        material.needsUpdate = false;
      }
      var refreshProgram = false;
      var refreshMaterial = false;
      var refreshLights = false;
      var program = materialProperties.program,
          p_uniforms = program.getUniforms(),
          m_uniforms = materialProperties.shader.uniforms;
      if (state.useProgram(program.program)) {
        refreshProgram = true;
        refreshMaterial = true;
        refreshLights = true;
      }
      if (material.id !== _currentMaterialId) {
        _currentMaterialId = material.id;
        refreshMaterial = true;
      }
      if (refreshProgram || camera !== _currentCamera) {
        p_uniforms.setValue(_gl, 'projectionMatrix', camera.projectionMatrix);
        if (capabilities.logarithmicDepthBuffer) {
          p_uniforms.setValue(_gl, 'logDepthBufFC', 2.0 / (Math.log(camera.far + 1.0) / Math.LN2));
        }
        if (_currentCamera !== (_currentArrayCamera || camera)) {
          _currentCamera = (_currentArrayCamera || camera);
          refreshMaterial = true;
          refreshLights = true;
        }
        if (material.isShaderMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial || material.envMap) {
          var uCamPos = p_uniforms.map.cameraPosition;
          if (uCamPos !== undefined) {
            uCamPos.setValue(_gl, _vector3.setFromMatrixPosition(camera.matrixWorld));
          }
        }
        if (material.isMeshPhongMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial || material.skinning) {
          p_uniforms.setValue(_gl, 'viewMatrix', camera.matrixWorldInverse);
        }
      }
      if (material.skinning) {
        p_uniforms.setOptional(_gl, object, 'bindMatrix');
        p_uniforms.setOptional(_gl, object, 'bindMatrixInverse');
        var skeleton = object.skeleton;
        if (skeleton) {
          var bones = skeleton.bones;
          if (capabilities.floatVertexTextures) {
            if (skeleton.boneTexture === undefined) {
              var size = Math.sqrt(bones.length * 4);
              size = _Math.ceilPowerOfTwo(size);
              size = Math.max(size, 4);
              var boneMatrices = new Float32Array(size * size * 4);
              boneMatrices.set(skeleton.boneMatrices);
              var boneTexture = new DataTexture(boneMatrices, size, size, RGBAFormat, FloatType);
              skeleton.boneMatrices = boneMatrices;
              skeleton.boneTexture = boneTexture;
              skeleton.boneTextureSize = size;
            }
            p_uniforms.setValue(_gl, 'boneTexture', skeleton.boneTexture);
            p_uniforms.setValue(_gl, 'boneTextureSize', skeleton.boneTextureSize);
          } else {
            p_uniforms.setOptional(_gl, skeleton, 'boneMatrices');
          }
        }
      }
      if (refreshMaterial) {
        p_uniforms.setValue(_gl, 'toneMappingExposure', _this.toneMappingExposure);
        p_uniforms.setValue(_gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint);
        if (material.lights) {
          markUniformsLightsNeedsUpdate(m_uniforms, refreshLights);
        }
        if (fog && material.fog) {
          refreshUniformsFog(m_uniforms, fog);
        }
        if (material.isMeshBasicMaterial) {
          refreshUniformsCommon(m_uniforms, material);
        } else if (material.isMeshLambertMaterial) {
          refreshUniformsCommon(m_uniforms, material);
          refreshUniformsLambert(m_uniforms, material);
        } else if (material.isMeshPhongMaterial) {
          refreshUniformsCommon(m_uniforms, material);
          if (material.isMeshToonMaterial) {
            refreshUniformsToon(m_uniforms, material);
          } else {
            refreshUniformsPhong(m_uniforms, material);
          }
        } else if (material.isMeshStandardMaterial) {
          refreshUniformsCommon(m_uniforms, material);
          if (material.isMeshPhysicalMaterial) {
            refreshUniformsPhysical(m_uniforms, material);
          } else {
            refreshUniformsStandard(m_uniforms, material);
          }
        } else if (material.isMeshDepthMaterial) {
          refreshUniformsCommon(m_uniforms, material);
          refreshUniformsDepth(m_uniforms, material);
        } else if (material.isMeshDistanceMaterial) {
          refreshUniformsCommon(m_uniforms, material);
          refreshUniformsDistance(m_uniforms, material);
        } else if (material.isMeshNormalMaterial) {
          refreshUniformsCommon(m_uniforms, material);
          refreshUniformsNormal(m_uniforms, material);
        } else if (material.isLineBasicMaterial) {
          refreshUniformsLine(m_uniforms, material);
          if (material.isLineDashedMaterial) {
            refreshUniformsDash(m_uniforms, material);
          }
        } else if (material.isPointsMaterial) {
          refreshUniformsPoints(m_uniforms, material);
        } else if (material.isShadowMaterial) {
          m_uniforms.color.value = material.color;
          m_uniforms.opacity.value = material.opacity;
        }
        if (m_uniforms.ltcMat !== undefined)
          m_uniforms.ltcMat.value = UniformsLib.LTC_MAT_TEXTURE;
        if (m_uniforms.ltcMag !== undefined)
          m_uniforms.ltcMag.value = UniformsLib.LTC_MAG_TEXTURE;
        WebGLUniforms.upload(_gl, materialProperties.uniformsList, m_uniforms, _this);
      }
      p_uniforms.setValue(_gl, 'modelViewMatrix', object.modelViewMatrix);
      p_uniforms.setValue(_gl, 'normalMatrix', object.normalMatrix);
      p_uniforms.setValue(_gl, 'modelMatrix', object.matrixWorld);
      return program;
    }
    function refreshUniformsCommon(uniforms, material) {
      uniforms.opacity.value = material.opacity;
      if (material.color) {
        uniforms.diffuse.value = material.color;
      }
      if (material.emissive) {
        uniforms.emissive.value.copy(material.emissive).multiplyScalar(material.emissiveIntensity);
      }
      if (material.map) {
        uniforms.map.value = material.map;
      }
      if (material.alphaMap) {
        uniforms.alphaMap.value = material.alphaMap;
      }
      if (material.specularMap) {
        uniforms.specularMap.value = material.specularMap;
      }
      if (material.envMap) {
        uniforms.envMap.value = material.envMap;
        uniforms.flipEnvMap.value = (!(material.envMap && material.envMap.isCubeTexture)) ? 1 : -1;
        uniforms.reflectivity.value = material.reflectivity;
        uniforms.refractionRatio.value = material.refractionRatio;
      }
      if (material.lightMap) {
        uniforms.lightMap.value = material.lightMap;
        uniforms.lightMapIntensity.value = material.lightMapIntensity;
      }
      if (material.aoMap) {
        uniforms.aoMap.value = material.aoMap;
        uniforms.aoMapIntensity.value = material.aoMapIntensity;
      }
      var uvScaleMap;
      if (material.map) {
        uvScaleMap = material.map;
      } else if (material.specularMap) {
        uvScaleMap = material.specularMap;
      } else if (material.displacementMap) {
        uvScaleMap = material.displacementMap;
      } else if (material.normalMap) {
        uvScaleMap = material.normalMap;
      } else if (material.bumpMap) {
        uvScaleMap = material.bumpMap;
      } else if (material.roughnessMap) {
        uvScaleMap = material.roughnessMap;
      } else if (material.metalnessMap) {
        uvScaleMap = material.metalnessMap;
      } else if (material.alphaMap) {
        uvScaleMap = material.alphaMap;
      } else if (material.emissiveMap) {
        uvScaleMap = material.emissiveMap;
      }
      if (uvScaleMap !== undefined) {
        if (uvScaleMap.isWebGLRenderTarget) {
          uvScaleMap = uvScaleMap.texture;
        }
        if (uvScaleMap.matrixAutoUpdate === true) {
          var offset = uvScaleMap.offset;
          var repeat = uvScaleMap.repeat;
          var rotation = uvScaleMap.rotation;
          var center = uvScaleMap.center;
          uvScaleMap.matrix.setUvTransform(offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y);
        }
        uniforms.uvTransform.value.copy(uvScaleMap.matrix);
      }
    }
    function refreshUniformsLine(uniforms, material) {
      uniforms.diffuse.value = material.color;
      uniforms.opacity.value = material.opacity;
    }
    function refreshUniformsDash(uniforms, material) {
      uniforms.dashSize.value = material.dashSize;
      uniforms.totalSize.value = material.dashSize + material.gapSize;
      uniforms.scale.value = material.scale;
    }
    function refreshUniformsPoints(uniforms, material) {
      uniforms.diffuse.value = material.color;
      uniforms.opacity.value = material.opacity;
      uniforms.size.value = material.size * _pixelRatio;
      uniforms.scale.value = _height * 0.5;
      uniforms.map.value = material.map;
      if (material.map !== null) {
        if (material.map.matrixAutoUpdate === true) {
          var offset = material.map.offset;
          var repeat = material.map.repeat;
          var rotation = material.map.rotation;
          var center = material.map.center;
          material.map.matrix.setUvTransform(offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y);
        }
        uniforms.uvTransform.value.copy(material.map.matrix);
      }
    }
    function refreshUniformsFog(uniforms, fog) {
      uniforms.fogColor.value = fog.color;
      if (fog.isFog) {
        uniforms.fogNear.value = fog.near;
        uniforms.fogFar.value = fog.far;
      } else if (fog.isFogExp2) {
        uniforms.fogDensity.value = fog.density;
      }
    }
    function refreshUniformsLambert(uniforms, material) {
      if (material.emissiveMap) {
        uniforms.emissiveMap.value = material.emissiveMap;
      }
    }
    function refreshUniformsPhong(uniforms, material) {
      uniforms.specular.value = material.specular;
      uniforms.shininess.value = Math.max(material.shininess, 1e-4);
      if (material.emissiveMap) {
        uniforms.emissiveMap.value = material.emissiveMap;
      }
      if (material.bumpMap) {
        uniforms.bumpMap.value = material.bumpMap;
        uniforms.bumpScale.value = material.bumpScale;
      }
      if (material.normalMap) {
        uniforms.normalMap.value = material.normalMap;
        uniforms.normalScale.value.copy(material.normalScale);
      }
      if (material.displacementMap) {
        uniforms.displacementMap.value = material.displacementMap;
        uniforms.displacementScale.value = material.displacementScale;
        uniforms.displacementBias.value = material.displacementBias;
      }
    }
    function refreshUniformsToon(uniforms, material) {
      refreshUniformsPhong(uniforms, material);
      if (material.gradientMap) {
        uniforms.gradientMap.value = material.gradientMap;
      }
    }
    function refreshUniformsStandard(uniforms, material) {
      uniforms.roughness.value = material.roughness;
      uniforms.metalness.value = material.metalness;
      if (material.roughnessMap) {
        uniforms.roughnessMap.value = material.roughnessMap;
      }
      if (material.metalnessMap) {
        uniforms.metalnessMap.value = material.metalnessMap;
      }
      if (material.emissiveMap) {
        uniforms.emissiveMap.value = material.emissiveMap;
      }
      if (material.bumpMap) {
        uniforms.bumpMap.value = material.bumpMap;
        uniforms.bumpScale.value = material.bumpScale;
      }
      if (material.normalMap) {
        uniforms.normalMap.value = material.normalMap;
        uniforms.normalScale.value.copy(material.normalScale);
      }
      if (material.displacementMap) {
        uniforms.displacementMap.value = material.displacementMap;
        uniforms.displacementScale.value = material.displacementScale;
        uniforms.displacementBias.value = material.displacementBias;
      }
      if (material.envMap) {
        uniforms.envMapIntensity.value = material.envMapIntensity;
      }
    }
    function refreshUniformsPhysical(uniforms, material) {
      uniforms.clearCoat.value = material.clearCoat;
      uniforms.clearCoatRoughness.value = material.clearCoatRoughness;
      refreshUniformsStandard(uniforms, material);
    }
    function refreshUniformsDepth(uniforms, material) {
      if (material.displacementMap) {
        uniforms.displacementMap.value = material.displacementMap;
        uniforms.displacementScale.value = material.displacementScale;
        uniforms.displacementBias.value = material.displacementBias;
      }
    }
    function refreshUniformsDistance(uniforms, material) {
      if (material.displacementMap) {
        uniforms.displacementMap.value = material.displacementMap;
        uniforms.displacementScale.value = material.displacementScale;
        uniforms.displacementBias.value = material.displacementBias;
      }
      uniforms.referencePosition.value.copy(material.referencePosition);
      uniforms.nearDistance.value = material.nearDistance;
      uniforms.farDistance.value = material.farDistance;
    }
    function refreshUniformsNormal(uniforms, material) {
      if (material.bumpMap) {
        uniforms.bumpMap.value = material.bumpMap;
        uniforms.bumpScale.value = material.bumpScale;
      }
      if (material.normalMap) {
        uniforms.normalMap.value = material.normalMap;
        uniforms.normalScale.value.copy(material.normalScale);
      }
      if (material.displacementMap) {
        uniforms.displacementMap.value = material.displacementMap;
        uniforms.displacementScale.value = material.displacementScale;
        uniforms.displacementBias.value = material.displacementBias;
      }
    }
    function markUniformsLightsNeedsUpdate(uniforms, value) {
      uniforms.ambientLightColor.needsUpdate = value;
      uniforms.directionalLights.needsUpdate = value;
      uniforms.pointLights.needsUpdate = value;
      uniforms.spotLights.needsUpdate = value;
      uniforms.rectAreaLights.needsUpdate = value;
      uniforms.hemisphereLights.needsUpdate = value;
    }
    this.setFaceCulling = function(cullFace, frontFaceDirection) {
      state.setCullFace(cullFace);
      state.setFlipSided(frontFaceDirection === FrontFaceDirectionCW);
    };
    function allocTextureUnit() {
      var textureUnit = _usedTextureUnits;
      if (textureUnit >= capabilities.maxTextures) {
        console.warn('THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures);
      }
      _usedTextureUnits += 1;
      return textureUnit;
    }
    this.allocTextureUnit = allocTextureUnit;
    this.setTexture2D = (function() {
      var warned = false;
      return function setTexture2D(texture, slot) {
        if (texture && texture.isWebGLRenderTarget) {
          if (!warned) {
            console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead.");
            warned = true;
          }
          texture = texture.texture;
        }
        textures.setTexture2D(texture, slot);
      };
    }());
    this.setTexture = (function() {
      var warned = false;
      return function setTexture(texture, slot) {
        if (!warned) {
          console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead.");
          warned = true;
        }
        textures.setTexture2D(texture, slot);
      };
    }());
    this.setTextureCube = (function() {
      var warned = false;
      return function setTextureCube(texture, slot) {
        if (texture && texture.isWebGLRenderTargetCube) {
          if (!warned) {
            console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead.");
            warned = true;
          }
          texture = texture.texture;
        }
        if ((texture && texture.isCubeTexture) || (Array.isArray(texture.image) && texture.image.length === 6)) {
          textures.setTextureCube(texture, slot);
        } else {
          textures.setTextureCubeDynamic(texture, slot);
        }
      };
    }());
    this.getRenderTarget = function() {
      return _currentRenderTarget;
    };
    this.setRenderTarget = function(renderTarget) {
      _currentRenderTarget = renderTarget;
      if (renderTarget && properties.get(renderTarget).__webglFramebuffer === undefined) {
        textures.setupRenderTarget(renderTarget);
      }
      var framebuffer = null;
      var isCube = false;
      if (renderTarget) {
        var __webglFramebuffer = properties.get(renderTarget).__webglFramebuffer;
        if (renderTarget.isWebGLRenderTargetCube) {
          framebuffer = __webglFramebuffer[renderTarget.activeCubeFace];
          isCube = true;
        } else {
          framebuffer = __webglFramebuffer;
        }
        _currentViewport.copy(renderTarget.viewport);
        _currentScissor.copy(renderTarget.scissor);
        _currentScissorTest = renderTarget.scissorTest;
      } else {
        _currentViewport.copy(_viewport).multiplyScalar(_pixelRatio);
        _currentScissor.copy(_scissor).multiplyScalar(_pixelRatio);
        _currentScissorTest = _scissorTest;
      }
      if (_currentFramebuffer !== framebuffer) {
        _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
        _currentFramebuffer = framebuffer;
      }
      state.viewport(_currentViewport);
      state.scissor(_currentScissor);
      state.setScissorTest(_currentScissorTest);
      if (isCube) {
        var textureProperties = properties.get(renderTarget.texture);
        _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel);
      }
    };
    this.readRenderTargetPixels = function(renderTarget, x, y, width, height, buffer) {
      if (!(renderTarget && renderTarget.isWebGLRenderTarget)) {
        console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.');
        return;
      }
      var framebuffer = properties.get(renderTarget).__webglFramebuffer;
      if (framebuffer) {
        var restore = false;
        if (framebuffer !== _currentFramebuffer) {
          _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
          restore = true;
        }
        try {
          var texture = renderTarget.texture;
          var textureFormat = texture.format;
          var textureType = texture.type;
          if (textureFormat !== RGBAFormat && utils.convert(textureFormat) !== _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_FORMAT)) {
            console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.');
            return;
          }
          if (textureType !== UnsignedByteType && utils.convert(textureType) !== _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_TYPE) && !(textureType === FloatType && (extensions.get('OES_texture_float') || extensions.get('WEBGL_color_buffer_float'))) && !(textureType === HalfFloatType && extensions.get('EXT_color_buffer_half_float'))) {
            console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.');
            return;
          }
          if (_gl.checkFramebufferStatus(_gl.FRAMEBUFFER) === _gl.FRAMEBUFFER_COMPLETE) {
            if ((x >= 0 && x <= (renderTarget.width - width)) && (y >= 0 && y <= (renderTarget.height - height))) {
              _gl.readPixels(x, y, width, height, utils.convert(textureFormat), utils.convert(textureType), buffer);
            }
          } else {
            console.error('THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.');
          }
        } finally {
          if (restore) {
            _gl.bindFramebuffer(_gl.FRAMEBUFFER, _currentFramebuffer);
          }
        }
      }
    };
  }
  function FogExp2(color, density) {
    this.name = '';
    this.color = new Color(color);
    this.density = (density !== undefined) ? density : 0.00025;
  }
  FogExp2.prototype.isFogExp2 = true;
  FogExp2.prototype.clone = function() {
    return new FogExp2(this.color.getHex(), this.density);
  };
  FogExp2.prototype.toJSON = function() {
    return {
      type: 'FogExp2',
      color: this.color.getHex(),
      density: this.density
    };
  };
  function Fog(color, near, far) {
    this.name = '';
    this.color = new Color(color);
    this.near = (near !== undefined) ? near : 1;
    this.far = (far !== undefined) ? far : 1000;
  }
  Fog.prototype.isFog = true;
  Fog.prototype.clone = function() {
    return new Fog(this.color.getHex(), this.near, this.far);
  };
  Fog.prototype.toJSON = function() {
    return {
      type: 'Fog',
      color: this.color.getHex(),
      near: this.near,
      far: this.far
    };
  };
  function Scene() {
    Object3D.call(this);
    this.type = 'Scene';
    this.background = null;
    this.fog = null;
    this.overrideMaterial = null;
    this.autoUpdate = true;
  }
  Scene.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Scene,
    copy: function(source, recursive) {
      Object3D.prototype.copy.call(this, source, recursive);
      if (source.background !== null)
        this.background = source.background.clone();
      if (source.fog !== null)
        this.fog = source.fog.clone();
      if (source.overrideMaterial !== null)
        this.overrideMaterial = source.overrideMaterial.clone();
      this.autoUpdate = source.autoUpdate;
      this.matrixAutoUpdate = source.matrixAutoUpdate;
      return this;
    },
    toJSON: function(meta) {
      var data = Object3D.prototype.toJSON.call(this, meta);
      if (this.background !== null)
        data.object.background = this.background.toJSON(meta);
      if (this.fog !== null)
        data.object.fog = this.fog.toJSON();
      return data;
    }
  });
  function LensFlare(texture, size, distance, blending, color) {
    Object3D.call(this);
    this.lensFlares = [];
    this.positionScreen = new Vector3();
    this.customUpdateCallback = undefined;
    if (texture !== undefined) {
      this.add(texture, size, distance, blending, color);
    }
  }
  LensFlare.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: LensFlare,
    isLensFlare: true,
    copy: function(source) {
      Object3D.prototype.copy.call(this, source);
      this.positionScreen.copy(source.positionScreen);
      this.customUpdateCallback = source.customUpdateCallback;
      for (var i = 0,
          l = source.lensFlares.length; i < l; i++) {
        this.lensFlares.push(source.lensFlares[i]);
      }
      return this;
    },
    add: function(texture, size, distance, blending, color, opacity) {
      if (size === undefined)
        size = -1;
      if (distance === undefined)
        distance = 0;
      if (opacity === undefined)
        opacity = 1;
      if (color === undefined)
        color = new Color(0xffffff);
      if (blending === undefined)
        blending = NormalBlending;
      distance = Math.min(distance, Math.max(0, distance));
      this.lensFlares.push({
        texture: texture,
        size: size,
        distance: distance,
        x: 0,
        y: 0,
        z: 0,
        scale: 1,
        rotation: 0,
        opacity: opacity,
        color: color,
        blending: blending
      });
    },
    updateLensFlares: function() {
      var f,
          fl = this.lensFlares.length;
      var flare;
      var vecX = -this.positionScreen.x * 2;
      var vecY = -this.positionScreen.y * 2;
      for (f = 0; f < fl; f++) {
        flare = this.lensFlares[f];
        flare.x = this.positionScreen.x + vecX * flare.distance;
        flare.y = this.positionScreen.y + vecY * flare.distance;
        flare.wantedRotation = flare.x * Math.PI * 0.25;
        flare.rotation += (flare.wantedRotation - flare.rotation) * 0.25;
      }
    }
  });
  function SpriteMaterial(parameters) {
    Material.call(this);
    this.type = 'SpriteMaterial';
    this.color = new Color(0xffffff);
    this.map = null;
    this.rotation = 0;
    this.fog = false;
    this.lights = false;
    this.setValues(parameters);
  }
  SpriteMaterial.prototype = Object.create(Material.prototype);
  SpriteMaterial.prototype.constructor = SpriteMaterial;
  SpriteMaterial.prototype.isSpriteMaterial = true;
  SpriteMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.map = source.map;
    this.rotation = source.rotation;
    return this;
  };
  function Sprite(material) {
    Object3D.call(this);
    this.type = 'Sprite';
    this.material = (material !== undefined) ? material : new SpriteMaterial();
  }
  Sprite.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Sprite,
    isSprite: true,
    raycast: (function() {
      var intersectPoint = new Vector3();
      var worldPosition = new Vector3();
      var worldScale = new Vector3();
      return function raycast(raycaster, intersects) {
        worldPosition.setFromMatrixPosition(this.matrixWorld);
        raycaster.ray.closestPointToPoint(worldPosition, intersectPoint);
        worldScale.setFromMatrixScale(this.matrixWorld);
        var guessSizeSq = worldScale.x * worldScale.y / 4;
        if (worldPosition.distanceToSquared(intersectPoint) > guessSizeSq)
          return;
        var distance = raycaster.ray.origin.distanceTo(intersectPoint);
        if (distance < raycaster.near || distance > raycaster.far)
          return;
        intersects.push({
          distance: distance,
          point: intersectPoint.clone(),
          face: null,
          object: this
        });
      };
    }()),
    clone: function() {
      return new this.constructor(this.material).copy(this);
    }
  });
  function LOD() {
    Object3D.call(this);
    this.type = 'LOD';
    Object.defineProperties(this, {levels: {
        enumerable: true,
        value: []
      }});
  }
  LOD.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: LOD,
    copy: function(source) {
      Object3D.prototype.copy.call(this, source, false);
      var levels = source.levels;
      for (var i = 0,
          l = levels.length; i < l; i++) {
        var level = levels[i];
        this.addLevel(level.object.clone(), level.distance);
      }
      return this;
    },
    addLevel: function(object, distance) {
      if (distance === undefined)
        distance = 0;
      distance = Math.abs(distance);
      var levels = this.levels;
      for (var l = 0; l < levels.length; l++) {
        if (distance < levels[l].distance) {
          break;
        }
      }
      levels.splice(l, 0, {
        distance: distance,
        object: object
      });
      this.add(object);
    },
    getObjectForDistance: function(distance) {
      var levels = this.levels;
      for (var i = 1,
          l = levels.length; i < l; i++) {
        if (distance < levels[i].distance) {
          break;
        }
      }
      return levels[i - 1].object;
    },
    raycast: (function() {
      var matrixPosition = new Vector3();
      return function raycast(raycaster, intersects) {
        matrixPosition.setFromMatrixPosition(this.matrixWorld);
        var distance = raycaster.ray.origin.distanceTo(matrixPosition);
        this.getObjectForDistance(distance).raycast(raycaster, intersects);
      };
    }()),
    update: function() {
      var v1 = new Vector3();
      var v2 = new Vector3();
      return function update(camera) {
        var levels = this.levels;
        if (levels.length > 1) {
          v1.setFromMatrixPosition(camera.matrixWorld);
          v2.setFromMatrixPosition(this.matrixWorld);
          var distance = v1.distanceTo(v2);
          levels[0].object.visible = true;
          for (var i = 1,
              l = levels.length; i < l; i++) {
            if (distance >= levels[i].distance) {
              levels[i - 1].object.visible = false;
              levels[i].object.visible = true;
            } else {
              break;
            }
          }
          for (; i < l; i++) {
            levels[i].object.visible = false;
          }
        }
      };
    }(),
    toJSON: function(meta) {
      var data = Object3D.prototype.toJSON.call(this, meta);
      data.object.levels = [];
      var levels = this.levels;
      for (var i = 0,
          l = levels.length; i < l; i++) {
        var level = levels[i];
        data.object.levels.push({
          object: level.object.uuid,
          distance: level.distance
        });
      }
      return data;
    }
  });
  function Skeleton(bones, boneInverses) {
    bones = bones || [];
    this.bones = bones.slice(0);
    this.boneMatrices = new Float32Array(this.bones.length * 16);
    if (boneInverses === undefined) {
      this.calculateInverses();
    } else {
      if (this.bones.length === boneInverses.length) {
        this.boneInverses = boneInverses.slice(0);
      } else {
        console.warn('THREE.Skeleton boneInverses is the wrong length.');
        this.boneInverses = [];
        for (var i = 0,
            il = this.bones.length; i < il; i++) {
          this.boneInverses.push(new Matrix4());
        }
      }
    }
  }
  Object.assign(Skeleton.prototype, {
    calculateInverses: function() {
      this.boneInverses = [];
      for (var i = 0,
          il = this.bones.length; i < il; i++) {
        var inverse = new Matrix4();
        if (this.bones[i]) {
          inverse.getInverse(this.bones[i].matrixWorld);
        }
        this.boneInverses.push(inverse);
      }
    },
    pose: function() {
      var bone,
          i,
          il;
      for (i = 0, il = this.bones.length; i < il; i++) {
        bone = this.bones[i];
        if (bone) {
          bone.matrixWorld.getInverse(this.boneInverses[i]);
        }
      }
      for (i = 0, il = this.bones.length; i < il; i++) {
        bone = this.bones[i];
        if (bone) {
          if (bone.parent && bone.parent.isBone) {
            bone.matrix.getInverse(bone.parent.matrixWorld);
            bone.matrix.multiply(bone.matrixWorld);
          } else {
            bone.matrix.copy(bone.matrixWorld);
          }
          bone.matrix.decompose(bone.position, bone.quaternion, bone.scale);
        }
      }
    },
    update: (function() {
      var offsetMatrix = new Matrix4();
      var identityMatrix = new Matrix4();
      return function update() {
        var bones = this.bones;
        var boneInverses = this.boneInverses;
        var boneMatrices = this.boneMatrices;
        var boneTexture = this.boneTexture;
        for (var i = 0,
            il = bones.length; i < il; i++) {
          var matrix = bones[i] ? bones[i].matrixWorld : identityMatrix;
          offsetMatrix.multiplyMatrices(matrix, boneInverses[i]);
          offsetMatrix.toArray(boneMatrices, i * 16);
        }
        if (boneTexture !== undefined) {
          boneTexture.needsUpdate = true;
        }
      };
    })(),
    clone: function() {
      return new Skeleton(this.bones, this.boneInverses);
    }
  });
  function Bone() {
    Object3D.call(this);
    this.type = 'Bone';
  }
  Bone.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Bone,
    isBone: true
  });
  function SkinnedMesh(geometry, material) {
    Mesh.call(this, geometry, material);
    this.type = 'SkinnedMesh';
    this.bindMode = 'attached';
    this.bindMatrix = new Matrix4();
    this.bindMatrixInverse = new Matrix4();
    var bones = this.initBones();
    var skeleton = new Skeleton(bones);
    this.bind(skeleton, this.matrixWorld);
    this.normalizeSkinWeights();
  }
  SkinnedMesh.prototype = Object.assign(Object.create(Mesh.prototype), {
    constructor: SkinnedMesh,
    isSkinnedMesh: true,
    initBones: function() {
      var bones = [],
          bone,
          gbone;
      var i,
          il;
      if (this.geometry && this.geometry.bones !== undefined) {
        for (i = 0, il = this.geometry.bones.length; i < il; i++) {
          gbone = this.geometry.bones[i];
          bone = new Bone();
          bones.push(bone);
          bone.name = gbone.name;
          bone.position.fromArray(gbone.pos);
          bone.quaternion.fromArray(gbone.rotq);
          if (gbone.scl !== undefined)
            bone.scale.fromArray(gbone.scl);
        }
        for (i = 0, il = this.geometry.bones.length; i < il; i++) {
          gbone = this.geometry.bones[i];
          if ((gbone.parent !== -1) && (gbone.parent !== null) && (bones[gbone.parent] !== undefined)) {
            bones[gbone.parent].add(bones[i]);
          } else {
            this.add(bones[i]);
          }
        }
      }
      this.updateMatrixWorld(true);
      return bones;
    },
    bind: function(skeleton, bindMatrix) {
      this.skeleton = skeleton;
      if (bindMatrix === undefined) {
        this.updateMatrixWorld(true);
        this.skeleton.calculateInverses();
        bindMatrix = this.matrixWorld;
      }
      this.bindMatrix.copy(bindMatrix);
      this.bindMatrixInverse.getInverse(bindMatrix);
    },
    pose: function() {
      this.skeleton.pose();
    },
    normalizeSkinWeights: function() {
      var scale,
          i;
      if (this.geometry && this.geometry.isGeometry) {
        for (i = 0; i < this.geometry.skinWeights.length; i++) {
          var sw = this.geometry.skinWeights[i];
          scale = 1.0 / sw.manhattanLength();
          if (scale !== Infinity) {
            sw.multiplyScalar(scale);
          } else {
            sw.set(1, 0, 0, 0);
          }
        }
      } else if (this.geometry && this.geometry.isBufferGeometry) {
        var vec = new Vector4();
        var skinWeight = this.geometry.attributes.skinWeight;
        for (i = 0; i < skinWeight.count; i++) {
          vec.x = skinWeight.getX(i);
          vec.y = skinWeight.getY(i);
          vec.z = skinWeight.getZ(i);
          vec.w = skinWeight.getW(i);
          scale = 1.0 / vec.manhattanLength();
          if (scale !== Infinity) {
            vec.multiplyScalar(scale);
          } else {
            vec.set(1, 0, 0, 0);
          }
          skinWeight.setXYZW(i, vec.x, vec.y, vec.z, vec.w);
        }
      }
    },
    updateMatrixWorld: function(force) {
      Mesh.prototype.updateMatrixWorld.call(this, force);
      if (this.bindMode === 'attached') {
        this.bindMatrixInverse.getInverse(this.matrixWorld);
      } else if (this.bindMode === 'detached') {
        this.bindMatrixInverse.getInverse(this.bindMatrix);
      } else {
        console.warn('THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode);
      }
    },
    clone: function() {
      return new this.constructor(this.geometry, this.material).copy(this);
    }
  });
  function LineBasicMaterial(parameters) {
    Material.call(this);
    this.type = 'LineBasicMaterial';
    this.color = new Color(0xffffff);
    this.linewidth = 1;
    this.linecap = 'round';
    this.linejoin = 'round';
    this.lights = false;
    this.setValues(parameters);
  }
  LineBasicMaterial.prototype = Object.create(Material.prototype);
  LineBasicMaterial.prototype.constructor = LineBasicMaterial;
  LineBasicMaterial.prototype.isLineBasicMaterial = true;
  LineBasicMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.linewidth = source.linewidth;
    this.linecap = source.linecap;
    this.linejoin = source.linejoin;
    return this;
  };
  function Line(geometry, material, mode) {
    if (mode === 1) {
      console.warn('THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.');
      return new LineSegments(geometry, material);
    }
    Object3D.call(this);
    this.type = 'Line';
    this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
    this.material = material !== undefined ? material : new LineBasicMaterial({color: Math.random() * 0xffffff});
  }
  Line.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Line,
    isLine: true,
    raycast: (function() {
      var inverseMatrix = new Matrix4();
      var ray = new Ray();
      var sphere = new Sphere();
      return function raycast(raycaster, intersects) {
        var precision = raycaster.linePrecision;
        var precisionSq = precision * precision;
        var geometry = this.geometry;
        var matrixWorld = this.matrixWorld;
        if (geometry.boundingSphere === null)
          geometry.computeBoundingSphere();
        sphere.copy(geometry.boundingSphere);
        sphere.applyMatrix4(matrixWorld);
        if (raycaster.ray.intersectsSphere(sphere) === false)
          return;
        inverseMatrix.getInverse(matrixWorld);
        ray.copy(raycaster.ray).applyMatrix4(inverseMatrix);
        var vStart = new Vector3();
        var vEnd = new Vector3();
        var interSegment = new Vector3();
        var interRay = new Vector3();
        var step = (this && this.isLineSegments) ? 2 : 1;
        if (geometry.isBufferGeometry) {
          var index = geometry.index;
          var attributes = geometry.attributes;
          var positions = attributes.position.array;
          if (index !== null) {
            var indices = index.array;
            for (var i = 0,
                l = indices.length - 1; i < l; i += step) {
              var a = indices[i];
              var b = indices[i + 1];
              vStart.fromArray(positions, a * 3);
              vEnd.fromArray(positions, b * 3);
              var distSq = ray.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
              if (distSq > precisionSq)
                continue;
              interRay.applyMatrix4(this.matrixWorld);
              var distance = raycaster.ray.origin.distanceTo(interRay);
              if (distance < raycaster.near || distance > raycaster.far)
                continue;
              intersects.push({
                distance: distance,
                point: interSegment.clone().applyMatrix4(this.matrixWorld),
                index: i,
                face: null,
                faceIndex: null,
                object: this
              });
            }
          } else {
            for (var i = 0,
                l = positions.length / 3 - 1; i < l; i += step) {
              vStart.fromArray(positions, 3 * i);
              vEnd.fromArray(positions, 3 * i + 3);
              var distSq = ray.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
              if (distSq > precisionSq)
                continue;
              interRay.applyMatrix4(this.matrixWorld);
              var distance = raycaster.ray.origin.distanceTo(interRay);
              if (distance < raycaster.near || distance > raycaster.far)
                continue;
              intersects.push({
                distance: distance,
                point: interSegment.clone().applyMatrix4(this.matrixWorld),
                index: i,
                face: null,
                faceIndex: null,
                object: this
              });
            }
          }
        } else if (geometry.isGeometry) {
          var vertices = geometry.vertices;
          var nbVertices = vertices.length;
          for (var i = 0; i < nbVertices - 1; i += step) {
            var distSq = ray.distanceSqToSegment(vertices[i], vertices[i + 1], interRay, interSegment);
            if (distSq > precisionSq)
              continue;
            interRay.applyMatrix4(this.matrixWorld);
            var distance = raycaster.ray.origin.distanceTo(interRay);
            if (distance < raycaster.near || distance > raycaster.far)
              continue;
            intersects.push({
              distance: distance,
              point: interSegment.clone().applyMatrix4(this.matrixWorld),
              index: i,
              face: null,
              faceIndex: null,
              object: this
            });
          }
        }
      };
    }()),
    clone: function() {
      return new this.constructor(this.geometry, this.material).copy(this);
    }
  });
  function LineSegments(geometry, material) {
    Line.call(this, geometry, material);
    this.type = 'LineSegments';
  }
  LineSegments.prototype = Object.assign(Object.create(Line.prototype), {
    constructor: LineSegments,
    isLineSegments: true
  });
  function LineLoop(geometry, material) {
    Line.call(this, geometry, material);
    this.type = 'LineLoop';
  }
  LineLoop.prototype = Object.assign(Object.create(Line.prototype), {
    constructor: LineLoop,
    isLineLoop: true
  });
  function PointsMaterial(parameters) {
    Material.call(this);
    this.type = 'PointsMaterial';
    this.color = new Color(0xffffff);
    this.map = null;
    this.size = 1;
    this.sizeAttenuation = true;
    this.lights = false;
    this.setValues(parameters);
  }
  PointsMaterial.prototype = Object.create(Material.prototype);
  PointsMaterial.prototype.constructor = PointsMaterial;
  PointsMaterial.prototype.isPointsMaterial = true;
  PointsMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.map = source.map;
    this.size = source.size;
    this.sizeAttenuation = source.sizeAttenuation;
    return this;
  };
  function Points(geometry, material) {
    Object3D.call(this);
    this.type = 'Points';
    this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
    this.material = material !== undefined ? material : new PointsMaterial({color: Math.random() * 0xffffff});
  }
  Points.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Points,
    isPoints: true,
    raycast: (function() {
      var inverseMatrix = new Matrix4();
      var ray = new Ray();
      var sphere = new Sphere();
      return function raycast(raycaster, intersects) {
        var object = this;
        var geometry = this.geometry;
        var matrixWorld = this.matrixWorld;
        var threshold = raycaster.params.Points.threshold;
        if (geometry.boundingSphere === null)
          geometry.computeBoundingSphere();
        sphere.copy(geometry.boundingSphere);
        sphere.applyMatrix4(matrixWorld);
        sphere.radius += threshold;
        if (raycaster.ray.intersectsSphere(sphere) === false)
          return;
        inverseMatrix.getInverse(matrixWorld);
        ray.copy(raycaster.ray).applyMatrix4(inverseMatrix);
        var localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3);
        var localThresholdSq = localThreshold * localThreshold;
        var position = new Vector3();
        function testPoint(point, index) {
          var rayPointDistanceSq = ray.distanceSqToPoint(point);
          if (rayPointDistanceSq < localThresholdSq) {
            var intersectPoint = ray.closestPointToPoint(point);
            intersectPoint.applyMatrix4(matrixWorld);
            var distance = raycaster.ray.origin.distanceTo(intersectPoint);
            if (distance < raycaster.near || distance > raycaster.far)
              return;
            intersects.push({
              distance: distance,
              distanceToRay: Math.sqrt(rayPointDistanceSq),
              point: intersectPoint.clone(),
              index: index,
              face: null,
              object: object
            });
          }
        }
        if (geometry.isBufferGeometry) {
          var index = geometry.index;
          var attributes = geometry.attributes;
          var positions = attributes.position.array;
          if (index !== null) {
            var indices = index.array;
            for (var i = 0,
                il = indices.length; i < il; i++) {
              var a = indices[i];
              position.fromArray(positions, a * 3);
              testPoint(position, a);
            }
          } else {
            for (var i = 0,
                l = positions.length / 3; i < l; i++) {
              position.fromArray(positions, i * 3);
              testPoint(position, i);
            }
          }
        } else {
          var vertices = geometry.vertices;
          for (var i = 0,
              l = vertices.length; i < l; i++) {
            testPoint(vertices[i], i);
          }
        }
      };
    }()),
    clone: function() {
      return new this.constructor(this.geometry, this.material).copy(this);
    }
  });
  function Group() {
    Object3D.call(this);
    this.type = 'Group';
  }
  Group.prototype = Object.assign(Object.create(Object3D.prototype), {constructor: Group});
  function VideoTexture(video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
    Texture.call(this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
    this.generateMipmaps = false;
    var scope = this;
    function update() {
      var video = scope.image;
      if (video.readyState >= video.HAVE_CURRENT_DATA) {
        scope.needsUpdate = true;
      }
      requestAnimationFrame(update);
    }
    requestAnimationFrame(update);
  }
  VideoTexture.prototype = Object.create(Texture.prototype);
  VideoTexture.prototype.constructor = VideoTexture;
  function CompressedTexture(mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding) {
    Texture.call(this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
    this.image = {
      width: width,
      height: height
    };
    this.mipmaps = mipmaps;
    this.flipY = false;
    this.generateMipmaps = false;
  }
  CompressedTexture.prototype = Object.create(Texture.prototype);
  CompressedTexture.prototype.constructor = CompressedTexture;
  CompressedTexture.prototype.isCompressedTexture = true;
  function DepthTexture(width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format) {
    format = format !== undefined ? format : DepthFormat;
    if (format !== DepthFormat && format !== DepthStencilFormat) {
      throw new Error('DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat');
    }
    if (type === undefined && format === DepthFormat)
      type = UnsignedShortType;
    if (type === undefined && format === DepthStencilFormat)
      type = UnsignedInt248Type;
    Texture.call(this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
    this.image = {
      width: width,
      height: height
    };
    this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
    this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
    this.flipY = false;
    this.generateMipmaps = false;
  }
  DepthTexture.prototype = Object.create(Texture.prototype);
  DepthTexture.prototype.constructor = DepthTexture;
  DepthTexture.prototype.isDepthTexture = true;
  function WireframeGeometry(geometry) {
    BufferGeometry.call(this);
    this.type = 'WireframeGeometry';
    var vertices = [];
    var i,
        j,
        l,
        o,
        ol;
    var edge = [0, 0],
        edges = {},
        e,
        edge1,
        edge2;
    var key,
        keys = ['a', 'b', 'c'];
    var vertex;
    if (geometry && geometry.isGeometry) {
      var faces = geometry.faces;
      for (i = 0, l = faces.length; i < l; i++) {
        var face = faces[i];
        for (j = 0; j < 3; j++) {
          edge1 = face[keys[j]];
          edge2 = face[keys[(j + 1) % 3]];
          edge[0] = Math.min(edge1, edge2);
          edge[1] = Math.max(edge1, edge2);
          key = edge[0] + ',' + edge[1];
          if (edges[key] === undefined) {
            edges[key] = {
              index1: edge[0],
              index2: edge[1]
            };
          }
        }
      }
      for (key in edges) {
        e = edges[key];
        vertex = geometry.vertices[e.index1];
        vertices.push(vertex.x, vertex.y, vertex.z);
        vertex = geometry.vertices[e.index2];
        vertices.push(vertex.x, vertex.y, vertex.z);
      }
    } else if (geometry && geometry.isBufferGeometry) {
      var position,
          indices,
          groups;
      var group,
          start,
          count;
      var index1,
          index2;
      vertex = new Vector3();
      if (geometry.index !== null) {
        position = geometry.attributes.position;
        indices = geometry.index;
        groups = geometry.groups;
        if (groups.length === 0) {
          groups = [{
            start: 0,
            count: indices.count,
            materialIndex: 0
          }];
        }
        for (o = 0, ol = groups.length; o < ol; ++o) {
          group = groups[o];
          start = group.start;
          count = group.count;
          for (i = start, l = (start + count); i < l; i += 3) {
            for (j = 0; j < 3; j++) {
              edge1 = indices.getX(i + j);
              edge2 = indices.getX(i + (j + 1) % 3);
              edge[0] = Math.min(edge1, edge2);
              edge[1] = Math.max(edge1, edge2);
              key = edge[0] + ',' + edge[1];
              if (edges[key] === undefined) {
                edges[key] = {
                  index1: edge[0],
                  index2: edge[1]
                };
              }
            }
          }
        }
        for (key in edges) {
          e = edges[key];
          vertex.fromBufferAttribute(position, e.index1);
          vertices.push(vertex.x, vertex.y, vertex.z);
          vertex.fromBufferAttribute(position, e.index2);
          vertices.push(vertex.x, vertex.y, vertex.z);
        }
      } else {
        position = geometry.attributes.position;
        for (i = 0, l = (position.count / 3); i < l; i++) {
          for (j = 0; j < 3; j++) {
            index1 = 3 * i + j;
            vertex.fromBufferAttribute(position, index1);
            vertices.push(vertex.x, vertex.y, vertex.z);
            index2 = 3 * i + ((j + 1) % 3);
            vertex.fromBufferAttribute(position, index2);
            vertices.push(vertex.x, vertex.y, vertex.z);
          }
        }
      }
    }
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
  }
  WireframeGeometry.prototype = Object.create(BufferGeometry.prototype);
  WireframeGeometry.prototype.constructor = WireframeGeometry;
  function ParametricGeometry(func, slices, stacks) {
    Geometry.call(this);
    this.type = 'ParametricGeometry';
    this.parameters = {
      func: func,
      slices: slices,
      stacks: stacks
    };
    this.fromBufferGeometry(new ParametricBufferGeometry(func, slices, stacks));
    this.mergeVertices();
  }
  ParametricGeometry.prototype = Object.create(Geometry.prototype);
  ParametricGeometry.prototype.constructor = ParametricGeometry;
  function ParametricBufferGeometry(func, slices, stacks) {
    BufferGeometry.call(this);
    this.type = 'ParametricBufferGeometry';
    this.parameters = {
      func: func,
      slices: slices,
      stacks: stacks
    };
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    var EPS = 0.00001;
    var normal = new Vector3();
    var p0 = new Vector3(),
        p1 = new Vector3();
    var pu = new Vector3(),
        pv = new Vector3();
    var i,
        j;
    var sliceCount = slices + 1;
    for (i = 0; i <= stacks; i++) {
      var v = i / stacks;
      for (j = 0; j <= slices; j++) {
        var u = j / slices;
        p0 = func(u, v, p0);
        vertices.push(p0.x, p0.y, p0.z);
        if (u - EPS >= 0) {
          p1 = func(u - EPS, v, p1);
          pu.subVectors(p0, p1);
        } else {
          p1 = func(u + EPS, v, p1);
          pu.subVectors(p1, p0);
        }
        if (v - EPS >= 0) {
          p1 = func(u, v - EPS, p1);
          pv.subVectors(p0, p1);
        } else {
          p1 = func(u, v + EPS, p1);
          pv.subVectors(p1, p0);
        }
        normal.crossVectors(pu, pv).normalize();
        normals.push(normal.x, normal.y, normal.z);
        uvs.push(u, v);
      }
    }
    for (i = 0; i < stacks; i++) {
      for (j = 0; j < slices; j++) {
        var a = i * sliceCount + j;
        var b = i * sliceCount + j + 1;
        var c = (i + 1) * sliceCount + j + 1;
        var d = (i + 1) * sliceCount + j;
        indices.push(a, b, d);
        indices.push(b, c, d);
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
  }
  ParametricBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
  function PolyhedronGeometry(vertices, indices, radius, detail) {
    Geometry.call(this);
    this.type = 'PolyhedronGeometry';
    this.parameters = {
      vertices: vertices,
      indices: indices,
      radius: radius,
      detail: detail
    };
    this.fromBufferGeometry(new PolyhedronBufferGeometry(vertices, indices, radius, detail));
    this.mergeVertices();
  }
  PolyhedronGeometry.prototype = Object.create(Geometry.prototype);
  PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
  function PolyhedronBufferGeometry(vertices, indices, radius, detail) {
    BufferGeometry.call(this);
    this.type = 'PolyhedronBufferGeometry';
    this.parameters = {
      vertices: vertices,
      indices: indices,
      radius: radius,
      detail: detail
    };
    radius = radius || 1;
    detail = detail || 0;
    var vertexBuffer = [];
    var uvBuffer = [];
    subdivide(detail);
    appplyRadius(radius);
    generateUVs();
    this.addAttribute('position', new Float32BufferAttribute(vertexBuffer, 3));
    this.addAttribute('normal', new Float32BufferAttribute(vertexBuffer.slice(), 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvBuffer, 2));
    if (detail === 0) {
      this.computeVertexNormals();
    } else {
      this.normalizeNormals();
    }
    function subdivide(detail) {
      var a = new Vector3();
      var b = new Vector3();
      var c = new Vector3();
      for (var i = 0; i < indices.length; i += 3) {
        getVertexByIndex(indices[i + 0], a);
        getVertexByIndex(indices[i + 1], b);
        getVertexByIndex(indices[i + 2], c);
        subdivideFace(a, b, c, detail);
      }
    }
    function subdivideFace(a, b, c, detail) {
      var cols = Math.pow(2, detail);
      var v = [];
      var i,
          j;
      for (i = 0; i <= cols; i++) {
        v[i] = [];
        var aj = a.clone().lerp(c, i / cols);
        var bj = b.clone().lerp(c, i / cols);
        var rows = cols - i;
        for (j = 0; j <= rows; j++) {
          if (j === 0 && i === cols) {
            v[i][j] = aj;
          } else {
            v[i][j] = aj.clone().lerp(bj, j / rows);
          }
        }
      }
      for (i = 0; i < cols; i++) {
        for (j = 0; j < 2 * (cols - i) - 1; j++) {
          var k = Math.floor(j / 2);
          if (j % 2 === 0) {
            pushVertex(v[i][k + 1]);
            pushVertex(v[i + 1][k]);
            pushVertex(v[i][k]);
          } else {
            pushVertex(v[i][k + 1]);
            pushVertex(v[i + 1][k + 1]);
            pushVertex(v[i + 1][k]);
          }
        }
      }
    }
    function appplyRadius(radius) {
      var vertex = new Vector3();
      for (var i = 0; i < vertexBuffer.length; i += 3) {
        vertex.x = vertexBuffer[i + 0];
        vertex.y = vertexBuffer[i + 1];
        vertex.z = vertexBuffer[i + 2];
        vertex.normalize().multiplyScalar(radius);
        vertexBuffer[i + 0] = vertex.x;
        vertexBuffer[i + 1] = vertex.y;
        vertexBuffer[i + 2] = vertex.z;
      }
    }
    function generateUVs() {
      var vertex = new Vector3();
      for (var i = 0; i < vertexBuffer.length; i += 3) {
        vertex.x = vertexBuffer[i + 0];
        vertex.y = vertexBuffer[i + 1];
        vertex.z = vertexBuffer[i + 2];
        var u = azimuth(vertex) / 2 / Math.PI + 0.5;
        var v = inclination(vertex) / Math.PI + 0.5;
        uvBuffer.push(u, 1 - v);
      }
      correctUVs();
      correctSeam();
    }
    function correctSeam() {
      for (var i = 0; i < uvBuffer.length; i += 6) {
        var x0 = uvBuffer[i + 0];
        var x1 = uvBuffer[i + 2];
        var x2 = uvBuffer[i + 4];
        var max = Math.max(x0, x1, x2);
        var min = Math.min(x0, x1, x2);
        if (max > 0.9 && min < 0.1) {
          if (x0 < 0.2)
            uvBuffer[i + 0] += 1;
          if (x1 < 0.2)
            uvBuffer[i + 2] += 1;
          if (x2 < 0.2)
            uvBuffer[i + 4] += 1;
        }
      }
    }
    function pushVertex(vertex) {
      vertexBuffer.push(vertex.x, vertex.y, vertex.z);
    }
    function getVertexByIndex(index, vertex) {
      var stride = index * 3;
      vertex.x = vertices[stride + 0];
      vertex.y = vertices[stride + 1];
      vertex.z = vertices[stride + 2];
    }
    function correctUVs() {
      var a = new Vector3();
      var b = new Vector3();
      var c = new Vector3();
      var centroid = new Vector3();
      var uvA = new Vector2();
      var uvB = new Vector2();
      var uvC = new Vector2();
      for (var i = 0,
          j = 0; i < vertexBuffer.length; i += 9, j += 6) {
        a.set(vertexBuffer[i + 0], vertexBuffer[i + 1], vertexBuffer[i + 2]);
        b.set(vertexBuffer[i + 3], vertexBuffer[i + 4], vertexBuffer[i + 5]);
        c.set(vertexBuffer[i + 6], vertexBuffer[i + 7], vertexBuffer[i + 8]);
        uvA.set(uvBuffer[j + 0], uvBuffer[j + 1]);
        uvB.set(uvBuffer[j + 2], uvBuffer[j + 3]);
        uvC.set(uvBuffer[j + 4], uvBuffer[j + 5]);
        centroid.copy(a).add(b).add(c).divideScalar(3);
        var azi = azimuth(centroid);
        correctUV(uvA, j + 0, a, azi);
        correctUV(uvB, j + 2, b, azi);
        correctUV(uvC, j + 4, c, azi);
      }
    }
    function correctUV(uv, stride, vector, azimuth) {
      if ((azimuth < 0) && (uv.x === 1)) {
        uvBuffer[stride] = uv.x - 1;
      }
      if ((vector.x === 0) && (vector.z === 0)) {
        uvBuffer[stride] = azimuth / 2 / Math.PI + 0.5;
      }
    }
    function azimuth(vector) {
      return Math.atan2(vector.z, -vector.x);
    }
    function inclination(vector) {
      return Math.atan2(-vector.y, Math.sqrt((vector.x * vector.x) + (vector.z * vector.z)));
    }
  }
  PolyhedronBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
  function TetrahedronGeometry(radius, detail) {
    Geometry.call(this);
    this.type = 'TetrahedronGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
    this.fromBufferGeometry(new TetrahedronBufferGeometry(radius, detail));
    this.mergeVertices();
  }
  TetrahedronGeometry.prototype = Object.create(Geometry.prototype);
  TetrahedronGeometry.prototype.constructor = TetrahedronGeometry;
  function TetrahedronBufferGeometry(radius, detail) {
    var vertices = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1];
    var indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1];
    PolyhedronBufferGeometry.call(this, vertices, indices, radius, detail);
    this.type = 'TetrahedronBufferGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
  }
  TetrahedronBufferGeometry.prototype = Object.create(PolyhedronBufferGeometry.prototype);
  TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;
  function OctahedronGeometry(radius, detail) {
    Geometry.call(this);
    this.type = 'OctahedronGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
    this.fromBufferGeometry(new OctahedronBufferGeometry(radius, detail));
    this.mergeVertices();
  }
  OctahedronGeometry.prototype = Object.create(Geometry.prototype);
  OctahedronGeometry.prototype.constructor = OctahedronGeometry;
  function OctahedronBufferGeometry(radius, detail) {
    var vertices = [1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1];
    var indices = [0, 2, 4, 0, 4, 3, 0, 3, 5, 0, 5, 2, 1, 2, 5, 1, 5, 3, 1, 3, 4, 1, 4, 2];
    PolyhedronBufferGeometry.call(this, vertices, indices, radius, detail);
    this.type = 'OctahedronBufferGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
  }
  OctahedronBufferGeometry.prototype = Object.create(PolyhedronBufferGeometry.prototype);
  OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;
  function IcosahedronGeometry(radius, detail) {
    Geometry.call(this);
    this.type = 'IcosahedronGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
    this.fromBufferGeometry(new IcosahedronBufferGeometry(radius, detail));
    this.mergeVertices();
  }
  IcosahedronGeometry.prototype = Object.create(Geometry.prototype);
  IcosahedronGeometry.prototype.constructor = IcosahedronGeometry;
  function IcosahedronBufferGeometry(radius, detail) {
    var t = (1 + Math.sqrt(5)) / 2;
    var vertices = [-1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0, 0, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, t, 0, -1, t, 0, 1, -t, 0, -1, -t, 0, 1];
    var indices = [0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1];
    PolyhedronBufferGeometry.call(this, vertices, indices, radius, detail);
    this.type = 'IcosahedronBufferGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
  }
  IcosahedronBufferGeometry.prototype = Object.create(PolyhedronBufferGeometry.prototype);
  IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;
  function DodecahedronGeometry(radius, detail) {
    Geometry.call(this);
    this.type = 'DodecahedronGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
    this.fromBufferGeometry(new DodecahedronBufferGeometry(radius, detail));
    this.mergeVertices();
  }
  DodecahedronGeometry.prototype = Object.create(Geometry.prototype);
  DodecahedronGeometry.prototype.constructor = DodecahedronGeometry;
  function DodecahedronBufferGeometry(radius, detail) {
    var t = (1 + Math.sqrt(5)) / 2;
    var r = 1 / t;
    var vertices = [-1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 0, -r, -t, 0, -r, t, 0, r, -t, 0, r, t, -r, -t, 0, -r, t, 0, r, -t, 0, r, t, 0, -t, 0, -r, t, 0, -r, -t, 0, r, t, 0, r];
    var indices = [3, 11, 7, 3, 7, 15, 3, 15, 13, 7, 19, 17, 7, 17, 6, 7, 6, 15, 17, 4, 8, 17, 8, 10, 17, 10, 6, 8, 0, 16, 8, 16, 2, 8, 2, 10, 0, 12, 1, 0, 1, 18, 0, 18, 16, 6, 10, 2, 6, 2, 13, 6, 13, 15, 2, 16, 18, 2, 18, 3, 2, 3, 13, 18, 1, 9, 18, 9, 11, 18, 11, 3, 4, 14, 12, 4, 12, 0, 4, 0, 8, 11, 9, 5, 11, 5, 19, 11, 19, 7, 19, 5, 14, 19, 14, 4, 19, 4, 17, 1, 12, 14, 1, 14, 5, 1, 5, 9];
    PolyhedronBufferGeometry.call(this, vertices, indices, radius, detail);
    this.type = 'DodecahedronBufferGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
  }
  DodecahedronBufferGeometry.prototype = Object.create(PolyhedronBufferGeometry.prototype);
  DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;
  function TubeGeometry(path, tubularSegments, radius, radialSegments, closed, taper) {
    Geometry.call(this);
    this.type = 'TubeGeometry';
    this.parameters = {
      path: path,
      tubularSegments: tubularSegments,
      radius: radius,
      radialSegments: radialSegments,
      closed: closed
    };
    if (taper !== undefined)
      console.warn('THREE.TubeGeometry: taper has been removed.');
    var bufferGeometry = new TubeBufferGeometry(path, tubularSegments, radius, radialSegments, closed);
    this.tangents = bufferGeometry.tangents;
    this.normals = bufferGeometry.normals;
    this.binormals = bufferGeometry.binormals;
    this.fromBufferGeometry(bufferGeometry);
    this.mergeVertices();
  }
  TubeGeometry.prototype = Object.create(Geometry.prototype);
  TubeGeometry.prototype.constructor = TubeGeometry;
  function TubeBufferGeometry(path, tubularSegments, radius, radialSegments, closed) {
    BufferGeometry.call(this);
    this.type = 'TubeBufferGeometry';
    this.parameters = {
      path: path,
      tubularSegments: tubularSegments,
      radius: radius,
      radialSegments: radialSegments,
      closed: closed
    };
    tubularSegments = tubularSegments || 64;
    radius = radius || 1;
    radialSegments = radialSegments || 8;
    closed = closed || false;
    var frames = path.computeFrenetFrames(tubularSegments, closed);
    this.tangents = frames.tangents;
    this.normals = frames.normals;
    this.binormals = frames.binormals;
    var vertex = new Vector3();
    var normal = new Vector3();
    var uv = new Vector2();
    var P = new Vector3();
    var i,
        j;
    var vertices = [];
    var normals = [];
    var uvs = [];
    var indices = [];
    generateBufferData();
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
    function generateBufferData() {
      for (i = 0; i < tubularSegments; i++) {
        generateSegment(i);
      }
      generateSegment((closed === false) ? tubularSegments : 0);
      generateUVs();
      generateIndices();
    }
    function generateSegment(i) {
      P = path.getPointAt(i / tubularSegments, P);
      var N = frames.normals[i];
      var B = frames.binormals[i];
      for (j = 0; j <= radialSegments; j++) {
        var v = j / radialSegments * Math.PI * 2;
        var sin = Math.sin(v);
        var cos = -Math.cos(v);
        normal.x = (cos * N.x + sin * B.x);
        normal.y = (cos * N.y + sin * B.y);
        normal.z = (cos * N.z + sin * B.z);
        normal.normalize();
        normals.push(normal.x, normal.y, normal.z);
        vertex.x = P.x + radius * normal.x;
        vertex.y = P.y + radius * normal.y;
        vertex.z = P.z + radius * normal.z;
        vertices.push(vertex.x, vertex.y, vertex.z);
      }
    }
    function generateIndices() {
      for (j = 1; j <= tubularSegments; j++) {
        for (i = 1; i <= radialSegments; i++) {
          var a = (radialSegments + 1) * (j - 1) + (i - 1);
          var b = (radialSegments + 1) * j + (i - 1);
          var c = (radialSegments + 1) * j + i;
          var d = (radialSegments + 1) * (j - 1) + i;
          indices.push(a, b, d);
          indices.push(b, c, d);
        }
      }
    }
    function generateUVs() {
      for (i = 0; i <= tubularSegments; i++) {
        for (j = 0; j <= radialSegments; j++) {
          uv.x = i / tubularSegments;
          uv.y = j / radialSegments;
          uvs.push(uv.x, uv.y);
        }
      }
    }
  }
  TubeBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
  function TorusKnotGeometry(radius, tube, tubularSegments, radialSegments, p, q, heightScale) {
    Geometry.call(this);
    this.type = 'TorusKnotGeometry';
    this.parameters = {
      radius: radius,
      tube: tube,
      tubularSegments: tubularSegments,
      radialSegments: radialSegments,
      p: p,
      q: q
    };
    if (heightScale !== undefined)
      console.warn('THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.');
    this.fromBufferGeometry(new TorusKnotBufferGeometry(radius, tube, tubularSegments, radialSegments, p, q));
    this.mergeVertices();
  }
  TorusKnotGeometry.prototype = Object.create(Geometry.prototype);
  TorusKnotGeometry.prototype.constructor = TorusKnotGeometry;
  function TorusKnotBufferGeometry(radius, tube, tubularSegments, radialSegments, p, q) {
    BufferGeometry.call(this);
    this.type = 'TorusKnotBufferGeometry';
    this.parameters = {
      radius: radius,
      tube: tube,
      tubularSegments: tubularSegments,
      radialSegments: radialSegments,
      p: p,
      q: q
    };
    radius = radius || 1;
    tube = tube || 0.4;
    tubularSegments = Math.floor(tubularSegments) || 64;
    radialSegments = Math.floor(radialSegments) || 8;
    p = p || 2;
    q = q || 3;
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    var i,
        j;
    var vertex = new Vector3();
    var normal = new Vector3();
    var P1 = new Vector3();
    var P2 = new Vector3();
    var B = new Vector3();
    var T = new Vector3();
    var N = new Vector3();
    for (i = 0; i <= tubularSegments; ++i) {
      var u = i / tubularSegments * p * Math.PI * 2;
      calculatePositionOnCurve(u, p, q, radius, P1);
      calculatePositionOnCurve(u + 0.01, p, q, radius, P2);
      T.subVectors(P2, P1);
      N.addVectors(P2, P1);
      B.crossVectors(T, N);
      N.crossVectors(B, T);
      B.normalize();
      N.normalize();
      for (j = 0; j <= radialSegments; ++j) {
        var v = j / radialSegments * Math.PI * 2;
        var cx = -tube * Math.cos(v);
        var cy = tube * Math.sin(v);
        vertex.x = P1.x + (cx * N.x + cy * B.x);
        vertex.y = P1.y + (cx * N.y + cy * B.y);
        vertex.z = P1.z + (cx * N.z + cy * B.z);
        vertices.push(vertex.x, vertex.y, vertex.z);
        normal.subVectors(vertex, P1).normalize();
        normals.push(normal.x, normal.y, normal.z);
        uvs.push(i / tubularSegments);
        uvs.push(j / radialSegments);
      }
    }
    for (j = 1; j <= tubularSegments; j++) {
      for (i = 1; i <= radialSegments; i++) {
        var a = (radialSegments + 1) * (j - 1) + (i - 1);
        var b = (radialSegments + 1) * j + (i - 1);
        var c = (radialSegments + 1) * j + i;
        var d = (radialSegments + 1) * (j - 1) + i;
        indices.push(a, b, d);
        indices.push(b, c, d);
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
    function calculatePositionOnCurve(u, p, q, radius, position) {
      var cu = Math.cos(u);
      var su = Math.sin(u);
      var quOverP = q / p * u;
      var cs = Math.cos(quOverP);
      position.x = radius * (2 + cs) * 0.5 * cu;
      position.y = radius * (2 + cs) * su * 0.5;
      position.z = radius * Math.sin(quOverP) * 0.5;
    }
  }
  TorusKnotBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;
  function TorusGeometry(radius, tube, radialSegments, tubularSegments, arc) {
    Geometry.call(this);
    this.type = 'TorusGeometry';
    this.parameters = {
      radius: radius,
      tube: tube,
      radialSegments: radialSegments,
      tubularSegments: tubularSegments,
      arc: arc
    };
    this.fromBufferGeometry(new TorusBufferGeometry(radius, tube, radialSegments, tubularSegments, arc));
    this.mergeVertices();
  }
  TorusGeometry.prototype = Object.create(Geometry.prototype);
  TorusGeometry.prototype.constructor = TorusGeometry;
  function TorusBufferGeometry(radius, tube, radialSegments, tubularSegments, arc) {
    BufferGeometry.call(this);
    this.type = 'TorusBufferGeometry';
    this.parameters = {
      radius: radius,
      tube: tube,
      radialSegments: radialSegments,
      tubularSegments: tubularSegments,
      arc: arc
    };
    radius = radius || 1;
    tube = tube || 0.4;
    radialSegments = Math.floor(radialSegments) || 8;
    tubularSegments = Math.floor(tubularSegments) || 6;
    arc = arc || Math.PI * 2;
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    var center = new Vector3();
    var vertex = new Vector3();
    var normal = new Vector3();
    var j,
        i;
    for (j = 0; j <= radialSegments; j++) {
      for (i = 0; i <= tubularSegments; i++) {
        var u = i / tubularSegments * arc;
        var v = j / radialSegments * Math.PI * 2;
        vertex.x = (radius + tube * Math.cos(v)) * Math.cos(u);
        vertex.y = (radius + tube * Math.cos(v)) * Math.sin(u);
        vertex.z = tube * Math.sin(v);
        vertices.push(vertex.x, vertex.y, vertex.z);
        center.x = radius * Math.cos(u);
        center.y = radius * Math.sin(u);
        normal.subVectors(vertex, center).normalize();
        normals.push(normal.x, normal.y, normal.z);
        uvs.push(i / tubularSegments);
        uvs.push(j / radialSegments);
      }
    }
    for (j = 1; j <= radialSegments; j++) {
      for (i = 1; i <= tubularSegments; i++) {
        var a = (tubularSegments + 1) * j + i - 1;
        var b = (tubularSegments + 1) * (j - 1) + i - 1;
        var c = (tubularSegments + 1) * (j - 1) + i;
        var d = (tubularSegments + 1) * j + i;
        indices.push(a, b, d);
        indices.push(b, c, d);
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
  }
  TorusBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  TorusBufferGeometry.prototype.constructor = TorusBufferGeometry;
  var ShapeUtils = {
    area: function(contour) {
      var n = contour.length;
      var a = 0.0;
      for (var p = n - 1,
          q = 0; q < n; p = q++) {
        a += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
      }
      return a * 0.5;
    },
    triangulate: (function() {
      function snip(contour, u, v, w, n, verts) {
        var p;
        var ax,
            ay,
            bx,
            by;
        var cx,
            cy,
            px,
            py;
        ax = contour[verts[u]].x;
        ay = contour[verts[u]].y;
        bx = contour[verts[v]].x;
        by = contour[verts[v]].y;
        cx = contour[verts[w]].x;
        cy = contour[verts[w]].y;
        if ((bx - ax) * (cy - ay) - (by - ay) * (cx - ax) <= 0)
          return false;
        var aX,
            aY,
            bX,
            bY,
            cX,
            cY;
        var apx,
            apy,
            bpx,
            bpy,
            cpx,
            cpy;
        var cCROSSap,
            bCROSScp,
            aCROSSbp;
        aX = cx - bx;
        aY = cy - by;
        bX = ax - cx;
        bY = ay - cy;
        cX = bx - ax;
        cY = by - ay;
        for (p = 0; p < n; p++) {
          px = contour[verts[p]].x;
          py = contour[verts[p]].y;
          if (((px === ax) && (py === ay)) || ((px === bx) && (py === by)) || ((px === cx) && (py === cy)))
            continue;
          apx = px - ax;
          apy = py - ay;
          bpx = px - bx;
          bpy = py - by;
          cpx = px - cx;
          cpy = py - cy;
          aCROSSbp = aX * bpy - aY * bpx;
          cCROSSap = cX * apy - cY * apx;
          bCROSScp = bX * cpy - bY * cpx;
          if ((aCROSSbp >= -Number.EPSILON) && (bCROSScp >= -Number.EPSILON) && (cCROSSap >= -Number.EPSILON))
            return false;
        }
        return true;
      }
      return function triangulate(contour, indices) {
        var n = contour.length;
        if (n < 3)
          return null;
        var result = [],
            verts = [],
            vertIndices = [];
        var u,
            v,
            w;
        if (ShapeUtils.area(contour) > 0.0) {
          for (v = 0; v < n; v++)
            verts[v] = v;
        } else {
          for (v = 0; v < n; v++)
            verts[v] = (n - 1) - v;
        }
        var nv = n;
        var count = 2 * nv;
        for (v = nv - 1; nv > 2; ) {
          if ((count--) <= 0) {
            console.warn('THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()');
            if (indices)
              return vertIndices;
            return result;
          }
          u = v;
          if (nv <= u)
            u = 0;
          v = u + 1;
          if (nv <= v)
            v = 0;
          w = v + 1;
          if (nv <= w)
            w = 0;
          if (snip(contour, u, v, w, nv, verts)) {
            var a,
                b,
                c,
                s,
                t;
            a = verts[u];
            b = verts[v];
            c = verts[w];
            result.push([contour[a], contour[b], contour[c]]);
            vertIndices.push([verts[u], verts[v], verts[w]]);
            for (s = v, t = v + 1; t < nv; s++, t++) {
              verts[s] = verts[t];
            }
            nv--;
            count = 2 * nv;
          }
        }
        if (indices)
          return vertIndices;
        return result;
      };
    })(),
    triangulateShape: function(contour, holes) {
      function removeDupEndPts(points) {
        var l = points.length;
        if (l > 2 && points[l - 1].equals(points[0])) {
          points.pop();
        }
      }
      removeDupEndPts(contour);
      holes.forEach(removeDupEndPts);
      function point_in_segment_2D_colin(inSegPt1, inSegPt2, inOtherPt) {
        if (inSegPt1.x !== inSegPt2.x) {
          if (inSegPt1.x < inSegPt2.x) {
            return ((inSegPt1.x <= inOtherPt.x) && (inOtherPt.x <= inSegPt2.x));
          } else {
            return ((inSegPt2.x <= inOtherPt.x) && (inOtherPt.x <= inSegPt1.x));
          }
        } else {
          if (inSegPt1.y < inSegPt2.y) {
            return ((inSegPt1.y <= inOtherPt.y) && (inOtherPt.y <= inSegPt2.y));
          } else {
            return ((inSegPt2.y <= inOtherPt.y) && (inOtherPt.y <= inSegPt1.y));
          }
        }
      }
      function intersect_segments_2D(inSeg1Pt1, inSeg1Pt2, inSeg2Pt1, inSeg2Pt2, inExcludeAdjacentSegs) {
        var seg1dx = inSeg1Pt2.x - inSeg1Pt1.x,
            seg1dy = inSeg1Pt2.y - inSeg1Pt1.y;
        var seg2dx = inSeg2Pt2.x - inSeg2Pt1.x,
            seg2dy = inSeg2Pt2.y - inSeg2Pt1.y;
        var seg1seg2dx = inSeg1Pt1.x - inSeg2Pt1.x;
        var seg1seg2dy = inSeg1Pt1.y - inSeg2Pt1.y;
        var limit = seg1dy * seg2dx - seg1dx * seg2dy;
        var perpSeg1 = seg1dy * seg1seg2dx - seg1dx * seg1seg2dy;
        if (Math.abs(limit) > Number.EPSILON) {
          var perpSeg2;
          if (limit > 0) {
            if ((perpSeg1 < 0) || (perpSeg1 > limit))
              return [];
            perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
            if ((perpSeg2 < 0) || (perpSeg2 > limit))
              return [];
          } else {
            if ((perpSeg1 > 0) || (perpSeg1 < limit))
              return [];
            perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
            if ((perpSeg2 > 0) || (perpSeg2 < limit))
              return [];
          }
          if (perpSeg2 === 0) {
            if ((inExcludeAdjacentSegs) && ((perpSeg1 === 0) || (perpSeg1 === limit)))
              return [];
            return [inSeg1Pt1];
          }
          if (perpSeg2 === limit) {
            if ((inExcludeAdjacentSegs) && ((perpSeg1 === 0) || (perpSeg1 === limit)))
              return [];
            return [inSeg1Pt2];
          }
          if (perpSeg1 === 0)
            return [inSeg2Pt1];
          if (perpSeg1 === limit)
            return [inSeg2Pt2];
          var factorSeg1 = perpSeg2 / limit;
          return [{
            x: inSeg1Pt1.x + factorSeg1 * seg1dx,
            y: inSeg1Pt1.y + factorSeg1 * seg1dy
          }];
        } else {
          if ((perpSeg1 !== 0) || (seg2dy * seg1seg2dx !== seg2dx * seg1seg2dy))
            return [];
          var seg1Pt = ((seg1dx === 0) && (seg1dy === 0));
          var seg2Pt = ((seg2dx === 0) && (seg2dy === 0));
          if (seg1Pt && seg2Pt) {
            if ((inSeg1Pt1.x !== inSeg2Pt1.x) || (inSeg1Pt1.y !== inSeg2Pt1.y))
              return [];
            return [inSeg1Pt1];
          }
          if (seg1Pt) {
            if (!point_in_segment_2D_colin(inSeg2Pt1, inSeg2Pt2, inSeg1Pt1))
              return [];
            return [inSeg1Pt1];
          }
          if (seg2Pt) {
            if (!point_in_segment_2D_colin(inSeg1Pt1, inSeg1Pt2, inSeg2Pt1))
              return [];
            return [inSeg2Pt1];
          }
          var seg1min,
              seg1max,
              seg1minVal,
              seg1maxVal;
          var seg2min,
              seg2max,
              seg2minVal,
              seg2maxVal;
          if (seg1dx !== 0) {
            if (inSeg1Pt1.x < inSeg1Pt2.x) {
              seg1min = inSeg1Pt1;
              seg1minVal = inSeg1Pt1.x;
              seg1max = inSeg1Pt2;
              seg1maxVal = inSeg1Pt2.x;
            } else {
              seg1min = inSeg1Pt2;
              seg1minVal = inSeg1Pt2.x;
              seg1max = inSeg1Pt1;
              seg1maxVal = inSeg1Pt1.x;
            }
            if (inSeg2Pt1.x < inSeg2Pt2.x) {
              seg2min = inSeg2Pt1;
              seg2minVal = inSeg2Pt1.x;
              seg2max = inSeg2Pt2;
              seg2maxVal = inSeg2Pt2.x;
            } else {
              seg2min = inSeg2Pt2;
              seg2minVal = inSeg2Pt2.x;
              seg2max = inSeg2Pt1;
              seg2maxVal = inSeg2Pt1.x;
            }
          } else {
            if (inSeg1Pt1.y < inSeg1Pt2.y) {
              seg1min = inSeg1Pt1;
              seg1minVal = inSeg1Pt1.y;
              seg1max = inSeg1Pt2;
              seg1maxVal = inSeg1Pt2.y;
            } else {
              seg1min = inSeg1Pt2;
              seg1minVal = inSeg1Pt2.y;
              seg1max = inSeg1Pt1;
              seg1maxVal = inSeg1Pt1.y;
            }
            if (inSeg2Pt1.y < inSeg2Pt2.y) {
              seg2min = inSeg2Pt1;
              seg2minVal = inSeg2Pt1.y;
              seg2max = inSeg2Pt2;
              seg2maxVal = inSeg2Pt2.y;
            } else {
              seg2min = inSeg2Pt2;
              seg2minVal = inSeg2Pt2.y;
              seg2max = inSeg2Pt1;
              seg2maxVal = inSeg2Pt1.y;
            }
          }
          if (seg1minVal <= seg2minVal) {
            if (seg1maxVal < seg2minVal)
              return [];
            if (seg1maxVal === seg2minVal) {
              if (inExcludeAdjacentSegs)
                return [];
              return [seg2min];
            }
            if (seg1maxVal <= seg2maxVal)
              return [seg2min, seg1max];
            return [seg2min, seg2max];
          } else {
            if (seg1minVal > seg2maxVal)
              return [];
            if (seg1minVal === seg2maxVal) {
              if (inExcludeAdjacentSegs)
                return [];
              return [seg1min];
            }
            if (seg1maxVal <= seg2maxVal)
              return [seg1min, seg1max];
            return [seg1min, seg2max];
          }
        }
      }
      function isPointInsideAngle(inVertex, inLegFromPt, inLegToPt, inOtherPt) {
        var legFromPtX = inLegFromPt.x - inVertex.x,
            legFromPtY = inLegFromPt.y - inVertex.y;
        var legToPtX = inLegToPt.x - inVertex.x,
            legToPtY = inLegToPt.y - inVertex.y;
        var otherPtX = inOtherPt.x - inVertex.x,
            otherPtY = inOtherPt.y - inVertex.y;
        var from2toAngle = legFromPtX * legToPtY - legFromPtY * legToPtX;
        var from2otherAngle = legFromPtX * otherPtY - legFromPtY * otherPtX;
        if (Math.abs(from2toAngle) > Number.EPSILON) {
          var other2toAngle = otherPtX * legToPtY - otherPtY * legToPtX;
          if (from2toAngle > 0) {
            return ((from2otherAngle >= 0) && (other2toAngle >= 0));
          } else {
            return ((from2otherAngle >= 0) || (other2toAngle >= 0));
          }
        } else {
          return (from2otherAngle > 0);
        }
      }
      function removeHoles(contour, holes) {
        var shape = contour.concat();
        var hole;
        function isCutLineInsideAngles(inShapeIdx, inHoleIdx) {
          var lastShapeIdx = shape.length - 1;
          var prevShapeIdx = inShapeIdx - 1;
          if (prevShapeIdx < 0)
            prevShapeIdx = lastShapeIdx;
          var nextShapeIdx = inShapeIdx + 1;
          if (nextShapeIdx > lastShapeIdx)
            nextShapeIdx = 0;
          var insideAngle = isPointInsideAngle(shape[inShapeIdx], shape[prevShapeIdx], shape[nextShapeIdx], hole[inHoleIdx]);
          if (!insideAngle) {
            return false;
          }
          var lastHoleIdx = hole.length - 1;
          var prevHoleIdx = inHoleIdx - 1;
          if (prevHoleIdx < 0)
            prevHoleIdx = lastHoleIdx;
          var nextHoleIdx = inHoleIdx + 1;
          if (nextHoleIdx > lastHoleIdx)
            nextHoleIdx = 0;
          insideAngle = isPointInsideAngle(hole[inHoleIdx], hole[prevHoleIdx], hole[nextHoleIdx], shape[inShapeIdx]);
          if (!insideAngle) {
            return false;
          }
          return true;
        }
        function intersectsShapeEdge(inShapePt, inHolePt) {
          var sIdx,
              nextIdx,
              intersection;
          for (sIdx = 0; sIdx < shape.length; sIdx++) {
            nextIdx = sIdx + 1;
            nextIdx %= shape.length;
            intersection = intersect_segments_2D(inShapePt, inHolePt, shape[sIdx], shape[nextIdx], true);
            if (intersection.length > 0)
              return true;
          }
          return false;
        }
        var indepHoles = [];
        function intersectsHoleEdge(inShapePt, inHolePt) {
          var ihIdx,
              chkHole,
              hIdx,
              nextIdx,
              intersection;
          for (ihIdx = 0; ihIdx < indepHoles.length; ihIdx++) {
            chkHole = holes[indepHoles[ihIdx]];
            for (hIdx = 0; hIdx < chkHole.length; hIdx++) {
              nextIdx = hIdx + 1;
              nextIdx %= chkHole.length;
              intersection = intersect_segments_2D(inShapePt, inHolePt, chkHole[hIdx], chkHole[nextIdx], true);
              if (intersection.length > 0)
                return true;
            }
          }
          return false;
        }
        var holeIndex,
            shapeIndex,
            shapePt,
            holePt,
            holeIdx,
            cutKey,
            failedCuts = [],
            tmpShape1,
            tmpShape2,
            tmpHole1,
            tmpHole2;
        for (var h = 0,
            hl = holes.length; h < hl; h++) {
          indepHoles.push(h);
        }
        var minShapeIndex = 0;
        var counter = indepHoles.length * 2;
        while (indepHoles.length > 0) {
          counter--;
          if (counter < 0) {
            console.log('THREE.ShapeUtils: Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!');
            break;
          }
          for (shapeIndex = minShapeIndex; shapeIndex < shape.length; shapeIndex++) {
            shapePt = shape[shapeIndex];
            holeIndex = -1;
            for (var h = 0; h < indepHoles.length; h++) {
              holeIdx = indepHoles[h];
              cutKey = shapePt.x + ':' + shapePt.y + ':' + holeIdx;
              if (failedCuts[cutKey] !== undefined)
                continue;
              hole = holes[holeIdx];
              for (var h2 = 0; h2 < hole.length; h2++) {
                holePt = hole[h2];
                if (!isCutLineInsideAngles(shapeIndex, h2))
                  continue;
                if (intersectsShapeEdge(shapePt, holePt))
                  continue;
                if (intersectsHoleEdge(shapePt, holePt))
                  continue;
                holeIndex = h2;
                indepHoles.splice(h, 1);
                tmpShape1 = shape.slice(0, shapeIndex + 1);
                tmpShape2 = shape.slice(shapeIndex);
                tmpHole1 = hole.slice(holeIndex);
                tmpHole2 = hole.slice(0, holeIndex + 1);
                shape = tmpShape1.concat(tmpHole1).concat(tmpHole2).concat(tmpShape2);
                minShapeIndex = shapeIndex;
                break;
              }
              if (holeIndex >= 0)
                break;
              failedCuts[cutKey] = true;
            }
            if (holeIndex >= 0)
              break;
          }
        }
        return shape;
      }
      var i,
          il,
          f,
          face,
          key,
          index,
          allPointsMap = {};
      var allpoints = contour.concat();
      for (var h = 0,
          hl = holes.length; h < hl; h++) {
        Array.prototype.push.apply(allpoints, holes[h]);
      }
      for (i = 0, il = allpoints.length; i < il; i++) {
        key = allpoints[i].x + ':' + allpoints[i].y;
        if (allPointsMap[key] !== undefined) {
          console.warn('THREE.ShapeUtils: Duplicate point', key, i);
        }
        allPointsMap[key] = i;
      }
      var shapeWithoutHoles = removeHoles(contour, holes);
      var triangles = ShapeUtils.triangulate(shapeWithoutHoles, false);
      for (i = 0, il = triangles.length; i < il; i++) {
        face = triangles[i];
        for (f = 0; f < 3; f++) {
          key = face[f].x + ':' + face[f].y;
          index = allPointsMap[key];
          if (index !== undefined) {
            face[f] = index;
          }
        }
      }
      return triangles.concat();
    },
    isClockWise: function(pts) {
      return ShapeUtils.area(pts) < 0;
    }
  };
  function ExtrudeGeometry(shapes, options) {
    Geometry.call(this);
    this.type = 'ExtrudeGeometry';
    this.parameters = {
      shapes: shapes,
      options: options
    };
    this.fromBufferGeometry(new ExtrudeBufferGeometry(shapes, options));
    this.mergeVertices();
  }
  ExtrudeGeometry.prototype = Object.create(Geometry.prototype);
  ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
  function ExtrudeBufferGeometry(shapes, options) {
    if (typeof(shapes) === "undefined") {
      return;
    }
    BufferGeometry.call(this);
    this.type = 'ExtrudeBufferGeometry';
    shapes = Array.isArray(shapes) ? shapes : [shapes];
    this.addShapeList(shapes, options);
    this.computeVertexNormals();
  }
  ExtrudeBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
  ExtrudeBufferGeometry.prototype.getArrays = function() {
    var positionAttribute = this.getAttribute("position");
    var verticesArray = positionAttribute ? Array.prototype.slice.call(positionAttribute.array) : [];
    var uvAttribute = this.getAttribute("uv");
    var uvArray = uvAttribute ? Array.prototype.slice.call(uvAttribute.array) : [];
    var IndexAttribute = this.index;
    var indicesArray = IndexAttribute ? Array.prototype.slice.call(IndexAttribute.array) : [];
    return {
      position: verticesArray,
      uv: uvArray,
      index: indicesArray
    };
  };
  ExtrudeBufferGeometry.prototype.addShapeList = function(shapes, options) {
    var sl = shapes.length;
    options.arrays = this.getArrays();
    for (var s = 0; s < sl; s++) {
      var shape = shapes[s];
      this.addShape(shape, options);
    }
    this.setIndex(options.arrays.index);
    this.addAttribute('position', new Float32BufferAttribute(options.arrays.position, 3));
    this.addAttribute('uv', new Float32BufferAttribute(options.arrays.uv, 2));
  };
  ExtrudeBufferGeometry.prototype.addShape = function(shape, options) {
    var arrays = options.arrays ? options.arrays : this.getArrays();
    var verticesArray = arrays.position;
    var indicesArray = arrays.index;
    var uvArray = arrays.uv;
    var placeholder = [];
    var amount = options.amount !== undefined ? options.amount : 100;
    var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
    var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
    var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
    var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
    var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
    var steps = options.steps !== undefined ? options.steps : 1;
    var extrudePath = options.extrudePath;
    var extrudePts,
        extrudeByPath = false;
    var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : ExtrudeGeometry.WorldUVGenerator;
    var splineTube,
        binormal,
        normal,
        position2;
    if (extrudePath) {
      extrudePts = extrudePath.getSpacedPoints(steps);
      extrudeByPath = true;
      bevelEnabled = false;
      splineTube = options.frames !== undefined ? options.frames : extrudePath.computeFrenetFrames(steps, false);
      binormal = new Vector3();
      normal = new Vector3();
      position2 = new Vector3();
    }
    if (!bevelEnabled) {
      bevelSegments = 0;
      bevelThickness = 0;
      bevelSize = 0;
    }
    var ahole,
        h,
        hl;
    var scope = this;
    var shapePoints = shape.extractPoints(curveSegments);
    var vertices = shapePoints.shape;
    var holes = shapePoints.holes;
    var reverse = !ShapeUtils.isClockWise(vertices);
    if (reverse) {
      vertices = vertices.reverse();
      for (h = 0, hl = holes.length; h < hl; h++) {
        ahole = holes[h];
        if (ShapeUtils.isClockWise(ahole)) {
          holes[h] = ahole.reverse();
        }
      }
    }
    var faces = ShapeUtils.triangulateShape(vertices, holes);
    var contour = vertices;
    for (h = 0, hl = holes.length; h < hl; h++) {
      ahole = holes[h];
      vertices = vertices.concat(ahole);
    }
    function scalePt2(pt, vec, size) {
      if (!vec)
        console.error("THREE.ExtrudeGeometry: vec does not exist");
      return vec.clone().multiplyScalar(size).add(pt);
    }
    var b,
        bs,
        t,
        z,
        vert,
        vlen = vertices.length,
        face,
        flen = faces.length;
    function getBevelVec(inPt, inPrev, inNext) {
      var v_trans_x,
          v_trans_y,
          shrink_by;
      var v_prev_x = inPt.x - inPrev.x,
          v_prev_y = inPt.y - inPrev.y;
      var v_next_x = inNext.x - inPt.x,
          v_next_y = inNext.y - inPt.y;
      var v_prev_lensq = (v_prev_x * v_prev_x + v_prev_y * v_prev_y);
      var collinear0 = (v_prev_x * v_next_y - v_prev_y * v_next_x);
      if (Math.abs(collinear0) > Number.EPSILON) {
        var v_prev_len = Math.sqrt(v_prev_lensq);
        var v_next_len = Math.sqrt(v_next_x * v_next_x + v_next_y * v_next_y);
        var ptPrevShift_x = (inPrev.x - v_prev_y / v_prev_len);
        var ptPrevShift_y = (inPrev.y + v_prev_x / v_prev_len);
        var ptNextShift_x = (inNext.x - v_next_y / v_next_len);
        var ptNextShift_y = (inNext.y + v_next_x / v_next_len);
        var sf = ((ptNextShift_x - ptPrevShift_x) * v_next_y - (ptNextShift_y - ptPrevShift_y) * v_next_x) / (v_prev_x * v_next_y - v_prev_y * v_next_x);
        v_trans_x = (ptPrevShift_x + v_prev_x * sf - inPt.x);
        v_trans_y = (ptPrevShift_y + v_prev_y * sf - inPt.y);
        var v_trans_lensq = (v_trans_x * v_trans_x + v_trans_y * v_trans_y);
        if (v_trans_lensq <= 2) {
          return new Vector2(v_trans_x, v_trans_y);
        } else {
          shrink_by = Math.sqrt(v_trans_lensq / 2);
        }
      } else {
        var direction_eq = false;
        if (v_prev_x > Number.EPSILON) {
          if (v_next_x > Number.EPSILON) {
            direction_eq = true;
          }
        } else {
          if (v_prev_x < -Number.EPSILON) {
            if (v_next_x < -Number.EPSILON) {
              direction_eq = true;
            }
          } else {
            if (Math.sign(v_prev_y) === Math.sign(v_next_y)) {
              direction_eq = true;
            }
          }
        }
        if (direction_eq) {
          v_trans_x = -v_prev_y;
          v_trans_y = v_prev_x;
          shrink_by = Math.sqrt(v_prev_lensq);
        } else {
          v_trans_x = v_prev_x;
          v_trans_y = v_prev_y;
          shrink_by = Math.sqrt(v_prev_lensq / 2);
        }
      }
      return new Vector2(v_trans_x / shrink_by, v_trans_y / shrink_by);
    }
    var contourMovements = [];
    for (var i = 0,
        il = contour.length,
        j = il - 1,
        k = i + 1; i < il; i++, j++, k++) {
      if (j === il)
        j = 0;
      if (k === il)
        k = 0;
      contourMovements[i] = getBevelVec(contour[i], contour[j], contour[k]);
    }
    var holesMovements = [],
        oneHoleMovements,
        verticesMovements = contourMovements.concat();
    for (h = 0, hl = holes.length; h < hl; h++) {
      ahole = holes[h];
      oneHoleMovements = [];
      for (i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
        if (j === il)
          j = 0;
        if (k === il)
          k = 0;
        oneHoleMovements[i] = getBevelVec(ahole[i], ahole[j], ahole[k]);
      }
      holesMovements.push(oneHoleMovements);
      verticesMovements = verticesMovements.concat(oneHoleMovements);
    }
    for (b = 0; b < bevelSegments; b++) {
      t = b / bevelSegments;
      z = bevelThickness * Math.cos(t * Math.PI / 2);
      bs = bevelSize * Math.sin(t * Math.PI / 2);
      for (i = 0, il = contour.length; i < il; i++) {
        vert = scalePt2(contour[i], contourMovements[i], bs);
        v(vert.x, vert.y, -z);
      }
      for (h = 0, hl = holes.length; h < hl; h++) {
        ahole = holes[h];
        oneHoleMovements = holesMovements[h];
        for (i = 0, il = ahole.length; i < il; i++) {
          vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
          v(vert.x, vert.y, -z);
        }
      }
    }
    bs = bevelSize;
    for (i = 0; i < vlen; i++) {
      vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
      if (!extrudeByPath) {
        v(vert.x, vert.y, 0);
      } else {
        normal.copy(splineTube.normals[0]).multiplyScalar(vert.x);
        binormal.copy(splineTube.binormals[0]).multiplyScalar(vert.y);
        position2.copy(extrudePts[0]).add(normal).add(binormal);
        v(position2.x, position2.y, position2.z);
      }
    }
    var s;
    for (s = 1; s <= steps; s++) {
      for (i = 0; i < vlen; i++) {
        vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
        if (!extrudeByPath) {
          v(vert.x, vert.y, amount / steps * s);
        } else {
          normal.copy(splineTube.normals[s]).multiplyScalar(vert.x);
          binormal.copy(splineTube.binormals[s]).multiplyScalar(vert.y);
          position2.copy(extrudePts[s]).add(normal).add(binormal);
          v(position2.x, position2.y, position2.z);
        }
      }
    }
    for (b = bevelSegments - 1; b >= 0; b--) {
      t = b / bevelSegments;
      z = bevelThickness * Math.cos(t * Math.PI / 2);
      bs = bevelSize * Math.sin(t * Math.PI / 2);
      for (i = 0, il = contour.length; i < il; i++) {
        vert = scalePt2(contour[i], contourMovements[i], bs);
        v(vert.x, vert.y, amount + z);
      }
      for (h = 0, hl = holes.length; h < hl; h++) {
        ahole = holes[h];
        oneHoleMovements = holesMovements[h];
        for (i = 0, il = ahole.length; i < il; i++) {
          vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
          if (!extrudeByPath) {
            v(vert.x, vert.y, amount + z);
          } else {
            v(vert.x, vert.y + extrudePts[steps - 1].y, extrudePts[steps - 1].x + z);
          }
        }
      }
    }
    buildLidFaces();
    buildSideFaces();
    function buildLidFaces() {
      var start = verticesArray.length / 3;
      if (bevelEnabled) {
        var layer = 0;
        var offset = vlen * layer;
        for (i = 0; i < flen; i++) {
          face = faces[i];
          f3(face[2] + offset, face[1] + offset, face[0] + offset);
        }
        layer = steps + bevelSegments * 2;
        offset = vlen * layer;
        for (i = 0; i < flen; i++) {
          face = faces[i];
          f3(face[0] + offset, face[1] + offset, face[2] + offset);
        }
      } else {
        for (i = 0; i < flen; i++) {
          face = faces[i];
          f3(face[2], face[1], face[0]);
        }
        for (i = 0; i < flen; i++) {
          face = faces[i];
          f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
        }
      }
      scope.addGroup(start, verticesArray.length / 3 - start, options.material !== undefined ? options.material : 0);
    }
    function buildSideFaces() {
      var start = verticesArray.length / 3;
      var layeroffset = 0;
      sidewalls(contour, layeroffset);
      layeroffset += contour.length;
      for (h = 0, hl = holes.length; h < hl; h++) {
        ahole = holes[h];
        sidewalls(ahole, layeroffset);
        layeroffset += ahole.length;
      }
      scope.addGroup(start, verticesArray.length / 3 - start, options.extrudeMaterial !== undefined ? options.extrudeMaterial : 1);
    }
    function sidewalls(contour, layeroffset) {
      var j,
          k;
      i = contour.length;
      while (--i >= 0) {
        j = i;
        k = i - 1;
        if (k < 0)
          k = contour.length - 1;
        var s = 0,
            sl = steps + bevelSegments * 2;
        for (s = 0; s < sl; s++) {
          var slen1 = vlen * s;
          var slen2 = vlen * (s + 1);
          var a = layeroffset + j + slen1,
              b = layeroffset + k + slen1,
              c = layeroffset + k + slen2,
              d = layeroffset + j + slen2;
          f4(a, b, c, d);
        }
      }
    }
    function v(x, y, z) {
      placeholder.push(x);
      placeholder.push(y);
      placeholder.push(z);
    }
    function f3(a, b, c) {
      addVertex(a);
      addVertex(b);
      addVertex(c);
      var nextIndex = verticesArray.length / 3;
      var uvs = uvgen.generateTopUV(scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1);
      addUV(uvs[0]);
      addUV(uvs[1]);
      addUV(uvs[2]);
    }
    function f4(a, b, c, d) {
      addVertex(a);
      addVertex(b);
      addVertex(d);
      addVertex(b);
      addVertex(c);
      addVertex(d);
      var nextIndex = verticesArray.length / 3;
      var uvs = uvgen.generateSideWallUV(scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1);
      addUV(uvs[0]);
      addUV(uvs[1]);
      addUV(uvs[3]);
      addUV(uvs[1]);
      addUV(uvs[2]);
      addUV(uvs[3]);
    }
    function addVertex(index) {
      indicesArray.push(verticesArray.length / 3);
      verticesArray.push(placeholder[index * 3 + 0]);
      verticesArray.push(placeholder[index * 3 + 1]);
      verticesArray.push(placeholder[index * 3 + 2]);
    }
    function addUV(vector2) {
      uvArray.push(vector2.x);
      uvArray.push(vector2.y);
    }
    if (!options.arrays) {
      this.setIndex(indicesArray);
      this.addAttribute('position', new Float32BufferAttribute(verticesArray, 3));
      this.addAttribute('uv', new Float32BufferAttribute(options.arrays.uv, 2));
    }
  };
  ExtrudeGeometry.WorldUVGenerator = {
    generateTopUV: function(geometry, vertices, indexA, indexB, indexC) {
      var a_x = vertices[indexA * 3];
      var a_y = vertices[indexA * 3 + 1];
      var b_x = vertices[indexB * 3];
      var b_y = vertices[indexB * 3 + 1];
      var c_x = vertices[indexC * 3];
      var c_y = vertices[indexC * 3 + 1];
      return [new Vector2(a_x, a_y), new Vector2(b_x, b_y), new Vector2(c_x, c_y)];
    },
    generateSideWallUV: function(geometry, vertices, indexA, indexB, indexC, indexD) {
      var a_x = vertices[indexA * 3];
      var a_y = vertices[indexA * 3 + 1];
      var a_z = vertices[indexA * 3 + 2];
      var b_x = vertices[indexB * 3];
      var b_y = vertices[indexB * 3 + 1];
      var b_z = vertices[indexB * 3 + 2];
      var c_x = vertices[indexC * 3];
      var c_y = vertices[indexC * 3 + 1];
      var c_z = vertices[indexC * 3 + 2];
      var d_x = vertices[indexD * 3];
      var d_y = vertices[indexD * 3 + 1];
      var d_z = vertices[indexD * 3 + 2];
      if (Math.abs(a_y - b_y) < 0.01) {
        return [new Vector2(a_x, 1 - a_z), new Vector2(b_x, 1 - b_z), new Vector2(c_x, 1 - c_z), new Vector2(d_x, 1 - d_z)];
      } else {
        return [new Vector2(a_y, 1 - a_z), new Vector2(b_y, 1 - b_z), new Vector2(c_y, 1 - c_z), new Vector2(d_y, 1 - d_z)];
      }
    }
  };
  function TextGeometry(text, parameters) {
    Geometry.call(this);
    this.type = 'TextGeometry';
    this.parameters = {
      text: text,
      parameters: parameters
    };
    this.fromBufferGeometry(new TextBufferGeometry(text, parameters));
    this.mergeVertices();
  }
  TextGeometry.prototype = Object.create(Geometry.prototype);
  TextGeometry.prototype.constructor = TextGeometry;
  function TextBufferGeometry(text, parameters) {
    parameters = parameters || {};
    var font = parameters.font;
    if (!(font && font.isFont)) {
      console.error('THREE.TextGeometry: font parameter is not an instance of THREE.Font.');
      return new Geometry();
    }
    var shapes = font.generateShapes(text, parameters.size, parameters.curveSegments);
    parameters.amount = parameters.height !== undefined ? parameters.height : 50;
    if (parameters.bevelThickness === undefined)
      parameters.bevelThickness = 10;
    if (parameters.bevelSize === undefined)
      parameters.bevelSize = 8;
    if (parameters.bevelEnabled === undefined)
      parameters.bevelEnabled = false;
    ExtrudeBufferGeometry.call(this, shapes, parameters);
    this.type = 'TextBufferGeometry';
  }
  TextBufferGeometry.prototype = Object.create(ExtrudeBufferGeometry.prototype);
  TextBufferGeometry.prototype.constructor = TextBufferGeometry;
  function SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) {
    Geometry.call(this);
    this.type = 'SphereGeometry';
    this.parameters = {
      radius: radius,
      widthSegments: widthSegments,
      heightSegments: heightSegments,
      phiStart: phiStart,
      phiLength: phiLength,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    this.fromBufferGeometry(new SphereBufferGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength));
    this.mergeVertices();
  }
  SphereGeometry.prototype = Object.create(Geometry.prototype);
  SphereGeometry.prototype.constructor = SphereGeometry;
  function SphereBufferGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) {
    BufferGeometry.call(this);
    this.type = 'SphereBufferGeometry';
    this.parameters = {
      radius: radius,
      widthSegments: widthSegments,
      heightSegments: heightSegments,
      phiStart: phiStart,
      phiLength: phiLength,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    radius = radius || 1;
    widthSegments = Math.max(3, Math.floor(widthSegments) || 8);
    heightSegments = Math.max(2, Math.floor(heightSegments) || 6);
    phiStart = phiStart !== undefined ? phiStart : 0;
    phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
    thetaStart = thetaStart !== undefined ? thetaStart : 0;
    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
    var thetaEnd = thetaStart + thetaLength;
    var ix,
        iy;
    var index = 0;
    var grid = [];
    var vertex = new Vector3();
    var normal = new Vector3();
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    for (iy = 0; iy <= heightSegments; iy++) {
      var verticesRow = [];
      var v = iy / heightSegments;
      for (ix = 0; ix <= widthSegments; ix++) {
        var u = ix / widthSegments;
        vertex.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
        vertex.y = radius * Math.cos(thetaStart + v * thetaLength);
        vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
        vertices.push(vertex.x, vertex.y, vertex.z);
        normal.set(vertex.x, vertex.y, vertex.z).normalize();
        normals.push(normal.x, normal.y, normal.z);
        uvs.push(u, 1 - v);
        verticesRow.push(index++);
      }
      grid.push(verticesRow);
    }
    for (iy = 0; iy < heightSegments; iy++) {
      for (ix = 0; ix < widthSegments; ix++) {
        var a = grid[iy][ix + 1];
        var b = grid[iy][ix];
        var c = grid[iy + 1][ix];
        var d = grid[iy + 1][ix + 1];
        if (iy !== 0 || thetaStart > 0)
          indices.push(a, b, d);
        if (iy !== heightSegments - 1 || thetaEnd < Math.PI)
          indices.push(b, c, d);
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
  }
  SphereBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  SphereBufferGeometry.prototype.constructor = SphereBufferGeometry;
  function RingGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) {
    Geometry.call(this);
    this.type = 'RingGeometry';
    this.parameters = {
      innerRadius: innerRadius,
      outerRadius: outerRadius,
      thetaSegments: thetaSegments,
      phiSegments: phiSegments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    this.fromBufferGeometry(new RingBufferGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength));
    this.mergeVertices();
  }
  RingGeometry.prototype = Object.create(Geometry.prototype);
  RingGeometry.prototype.constructor = RingGeometry;
  function RingBufferGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) {
    BufferGeometry.call(this);
    this.type = 'RingBufferGeometry';
    this.parameters = {
      innerRadius: innerRadius,
      outerRadius: outerRadius,
      thetaSegments: thetaSegments,
      phiSegments: phiSegments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    innerRadius = innerRadius || 0.5;
    outerRadius = outerRadius || 1;
    thetaStart = thetaStart !== undefined ? thetaStart : 0;
    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
    thetaSegments = thetaSegments !== undefined ? Math.max(3, thetaSegments) : 8;
    phiSegments = phiSegments !== undefined ? Math.max(1, phiSegments) : 1;
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    var segment;
    var radius = innerRadius;
    var radiusStep = ((outerRadius - innerRadius) / phiSegments);
    var vertex = new Vector3();
    var uv = new Vector2();
    var j,
        i;
    for (j = 0; j <= phiSegments; j++) {
      for (i = 0; i <= thetaSegments; i++) {
        segment = thetaStart + i / thetaSegments * thetaLength;
        vertex.x = radius * Math.cos(segment);
        vertex.y = radius * Math.sin(segment);
        vertices.push(vertex.x, vertex.y, vertex.z);
        normals.push(0, 0, 1);
        uv.x = (vertex.x / outerRadius + 1) / 2;
        uv.y = (vertex.y / outerRadius + 1) / 2;
        uvs.push(uv.x, uv.y);
      }
      radius += radiusStep;
    }
    for (j = 0; j < phiSegments; j++) {
      var thetaSegmentLevel = j * (thetaSegments + 1);
      for (i = 0; i < thetaSegments; i++) {
        segment = i + thetaSegmentLevel;
        var a = segment;
        var b = segment + thetaSegments + 1;
        var c = segment + thetaSegments + 2;
        var d = segment + 1;
        indices.push(a, b, d);
        indices.push(b, c, d);
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
  }
  RingBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  RingBufferGeometry.prototype.constructor = RingBufferGeometry;
  function LatheGeometry(points, segments, phiStart, phiLength) {
    Geometry.call(this);
    this.type = 'LatheGeometry';
    this.parameters = {
      points: points,
      segments: segments,
      phiStart: phiStart,
      phiLength: phiLength
    };
    this.fromBufferGeometry(new LatheBufferGeometry(points, segments, phiStart, phiLength));
    this.mergeVertices();
  }
  LatheGeometry.prototype = Object.create(Geometry.prototype);
  LatheGeometry.prototype.constructor = LatheGeometry;
  function LatheBufferGeometry(points, segments, phiStart, phiLength) {
    BufferGeometry.call(this);
    this.type = 'LatheBufferGeometry';
    this.parameters = {
      points: points,
      segments: segments,
      phiStart: phiStart,
      phiLength: phiLength
    };
    segments = Math.floor(segments) || 12;
    phiStart = phiStart || 0;
    phiLength = phiLength || Math.PI * 2;
    phiLength = _Math.clamp(phiLength, 0, Math.PI * 2);
    var indices = [];
    var vertices = [];
    var uvs = [];
    var base;
    var inverseSegments = 1.0 / segments;
    var vertex = new Vector3();
    var uv = new Vector2();
    var i,
        j;
    for (i = 0; i <= segments; i++) {
      var phi = phiStart + i * inverseSegments * phiLength;
      var sin = Math.sin(phi);
      var cos = Math.cos(phi);
      for (j = 0; j <= (points.length - 1); j++) {
        vertex.x = points[j].x * sin;
        vertex.y = points[j].y;
        vertex.z = points[j].x * cos;
        vertices.push(vertex.x, vertex.y, vertex.z);
        uv.x = i / segments;
        uv.y = j / (points.length - 1);
        uvs.push(uv.x, uv.y);
      }
    }
    for (i = 0; i < segments; i++) {
      for (j = 0; j < (points.length - 1); j++) {
        base = j + i * points.length;
        var a = base;
        var b = base + points.length;
        var c = base + points.length + 1;
        var d = base + 1;
        indices.push(a, b, d);
        indices.push(b, c, d);
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
    this.computeVertexNormals();
    if (phiLength === Math.PI * 2) {
      var normals = this.attributes.normal.array;
      var n1 = new Vector3();
      var n2 = new Vector3();
      var n = new Vector3();
      base = segments * points.length * 3;
      for (i = 0, j = 0; i < points.length; i++, j += 3) {
        n1.x = normals[j + 0];
        n1.y = normals[j + 1];
        n1.z = normals[j + 2];
        n2.x = normals[base + j + 0];
        n2.y = normals[base + j + 1];
        n2.z = normals[base + j + 2];
        n.addVectors(n1, n2).normalize();
        normals[j + 0] = normals[base + j + 0] = n.x;
        normals[j + 1] = normals[base + j + 1] = n.y;
        normals[j + 2] = normals[base + j + 2] = n.z;
      }
    }
  }
  LatheBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
  function ShapeGeometry(shapes, curveSegments) {
    Geometry.call(this);
    this.type = 'ShapeGeometry';
    if (typeof curveSegments === 'object') {
      console.warn('THREE.ShapeGeometry: Options parameter has been removed.');
      curveSegments = curveSegments.curveSegments;
    }
    this.parameters = {
      shapes: shapes,
      curveSegments: curveSegments
    };
    this.fromBufferGeometry(new ShapeBufferGeometry(shapes, curveSegments));
    this.mergeVertices();
  }
  ShapeGeometry.prototype = Object.create(Geometry.prototype);
  ShapeGeometry.prototype.constructor = ShapeGeometry;
  function ShapeBufferGeometry(shapes, curveSegments) {
    BufferGeometry.call(this);
    this.type = 'ShapeBufferGeometry';
    this.parameters = {
      shapes: shapes,
      curveSegments: curveSegments
    };
    curveSegments = curveSegments || 12;
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    var groupStart = 0;
    var groupCount = 0;
    if (Array.isArray(shapes) === false) {
      addShape(shapes);
    } else {
      for (var i = 0; i < shapes.length; i++) {
        addShape(shapes[i]);
        this.addGroup(groupStart, groupCount, i);
        groupStart += groupCount;
        groupCount = 0;
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
    function addShape(shape) {
      var i,
          l,
          shapeHole;
      var indexOffset = vertices.length / 3;
      var points = shape.extractPoints(curveSegments);
      var shapeVertices = points.shape;
      var shapeHoles = points.holes;
      if (ShapeUtils.isClockWise(shapeVertices) === false) {
        shapeVertices = shapeVertices.reverse();
        for (i = 0, l = shapeHoles.length; i < l; i++) {
          shapeHole = shapeHoles[i];
          if (ShapeUtils.isClockWise(shapeHole) === true) {
            shapeHoles[i] = shapeHole.reverse();
          }
        }
      }
      var faces = ShapeUtils.triangulateShape(shapeVertices, shapeHoles);
      for (i = 0, l = shapeHoles.length; i < l; i++) {
        shapeHole = shapeHoles[i];
        shapeVertices = shapeVertices.concat(shapeHole);
      }
      for (i = 0, l = shapeVertices.length; i < l; i++) {
        var vertex = shapeVertices[i];
        vertices.push(vertex.x, vertex.y, 0);
        normals.push(0, 0, 1);
        uvs.push(vertex.x, vertex.y);
      }
      for (i = 0, l = faces.length; i < l; i++) {
        var face = faces[i];
        var a = face[0] + indexOffset;
        var b = face[1] + indexOffset;
        var c = face[2] + indexOffset;
        indices.push(a, b, c);
        groupCount += 3;
      }
    }
  }
  ShapeBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;
  function EdgesGeometry(geometry, thresholdAngle) {
    BufferGeometry.call(this);
    this.type = 'EdgesGeometry';
    this.parameters = {thresholdAngle: thresholdAngle};
    thresholdAngle = (thresholdAngle !== undefined) ? thresholdAngle : 1;
    var vertices = [];
    var thresholdDot = Math.cos(_Math.DEG2RAD * thresholdAngle);
    var edge = [0, 0],
        edges = {},
        edge1,
        edge2;
    var key,
        keys = ['a', 'b', 'c'];
    var geometry2;
    if (geometry.isBufferGeometry) {
      geometry2 = new Geometry();
      geometry2.fromBufferGeometry(geometry);
    } else {
      geometry2 = geometry.clone();
    }
    geometry2.mergeVertices();
    geometry2.computeFaceNormals();
    var sourceVertices = geometry2.vertices;
    var faces = geometry2.faces;
    for (var i = 0,
        l = faces.length; i < l; i++) {
      var face = faces[i];
      for (var j = 0; j < 3; j++) {
        edge1 = face[keys[j]];
        edge2 = face[keys[(j + 1) % 3]];
        edge[0] = Math.min(edge1, edge2);
        edge[1] = Math.max(edge1, edge2);
        key = edge[0] + ',' + edge[1];
        if (edges[key] === undefined) {
          edges[key] = {
            index1: edge[0],
            index2: edge[1],
            face1: i,
            face2: undefined
          };
        } else {
          edges[key].face2 = i;
        }
      }
    }
    for (key in edges) {
      var e = edges[key];
      if (e.face2 === undefined || faces[e.face1].normal.dot(faces[e.face2].normal) <= thresholdDot) {
        var vertex = sourceVertices[e.index1];
        vertices.push(vertex.x, vertex.y, vertex.z);
        vertex = sourceVertices[e.index2];
        vertices.push(vertex.x, vertex.y, vertex.z);
      }
    }
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
  }
  EdgesGeometry.prototype = Object.create(BufferGeometry.prototype);
  EdgesGeometry.prototype.constructor = EdgesGeometry;
  function CylinderGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
    Geometry.call(this);
    this.type = 'CylinderGeometry';
    this.parameters = {
      radiusTop: radiusTop,
      radiusBottom: radiusBottom,
      height: height,
      radialSegments: radialSegments,
      heightSegments: heightSegments,
      openEnded: openEnded,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    this.fromBufferGeometry(new CylinderBufferGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
    this.mergeVertices();
  }
  CylinderGeometry.prototype = Object.create(Geometry.prototype);
  CylinderGeometry.prototype.constructor = CylinderGeometry;
  function CylinderBufferGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
    BufferGeometry.call(this);
    this.type = 'CylinderBufferGeometry';
    this.parameters = {
      radiusTop: radiusTop,
      radiusBottom: radiusBottom,
      height: height,
      radialSegments: radialSegments,
      heightSegments: heightSegments,
      openEnded: openEnded,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    var scope = this;
    radiusTop = radiusTop !== undefined ? radiusTop : 1;
    radiusBottom = radiusBottom !== undefined ? radiusBottom : 1;
    height = height || 1;
    radialSegments = Math.floor(radialSegments) || 8;
    heightSegments = Math.floor(heightSegments) || 1;
    openEnded = openEnded !== undefined ? openEnded : false;
    thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    var index = 0;
    var indexArray = [];
    var halfHeight = height / 2;
    var groupStart = 0;
    generateTorso();
    if (openEnded === false) {
      if (radiusTop > 0)
        generateCap(true);
      if (radiusBottom > 0)
        generateCap(false);
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
    function generateTorso() {
      var x,
          y;
      var normal = new Vector3();
      var vertex = new Vector3();
      var groupCount = 0;
      var slope = (radiusBottom - radiusTop) / height;
      for (y = 0; y <= heightSegments; y++) {
        var indexRow = [];
        var v = y / heightSegments;
        var radius = v * (radiusBottom - radiusTop) + radiusTop;
        for (x = 0; x <= radialSegments; x++) {
          var u = x / radialSegments;
          var theta = u * thetaLength + thetaStart;
          var sinTheta = Math.sin(theta);
          var cosTheta = Math.cos(theta);
          vertex.x = radius * sinTheta;
          vertex.y = -v * height + halfHeight;
          vertex.z = radius * cosTheta;
          vertices.push(vertex.x, vertex.y, vertex.z);
          normal.set(sinTheta, slope, cosTheta).normalize();
          normals.push(normal.x, normal.y, normal.z);
          uvs.push(u, 1 - v);
          indexRow.push(index++);
        }
        indexArray.push(indexRow);
      }
      for (x = 0; x < radialSegments; x++) {
        for (y = 0; y < heightSegments; y++) {
          var a = indexArray[y][x];
          var b = indexArray[y + 1][x];
          var c = indexArray[y + 1][x + 1];
          var d = indexArray[y][x + 1];
          indices.push(a, b, d);
          indices.push(b, c, d);
          groupCount += 6;
        }
      }
      scope.addGroup(groupStart, groupCount, 0);
      groupStart += groupCount;
    }
    function generateCap(top) {
      var x,
          centerIndexStart,
          centerIndexEnd;
      var uv = new Vector2();
      var vertex = new Vector3();
      var groupCount = 0;
      var radius = (top === true) ? radiusTop : radiusBottom;
      var sign = (top === true) ? 1 : -1;
      centerIndexStart = index;
      for (x = 1; x <= radialSegments; x++) {
        vertices.push(0, halfHeight * sign, 0);
        normals.push(0, sign, 0);
        uvs.push(0.5, 0.5);
        index++;
      }
      centerIndexEnd = index;
      for (x = 0; x <= radialSegments; x++) {
        var u = x / radialSegments;
        var theta = u * thetaLength + thetaStart;
        var cosTheta = Math.cos(theta);
        var sinTheta = Math.sin(theta);
        vertex.x = radius * sinTheta;
        vertex.y = halfHeight * sign;
        vertex.z = radius * cosTheta;
        vertices.push(vertex.x, vertex.y, vertex.z);
        normals.push(0, sign, 0);
        uv.x = (cosTheta * 0.5) + 0.5;
        uv.y = (sinTheta * 0.5 * sign) + 0.5;
        uvs.push(uv.x, uv.y);
        index++;
      }
      for (x = 0; x < radialSegments; x++) {
        var c = centerIndexStart + x;
        var i = centerIndexEnd + x;
        if (top === true) {
          indices.push(i, i + 1, c);
        } else {
          indices.push(i + 1, i, c);
        }
        groupCount += 3;
      }
      scope.addGroup(groupStart, groupCount, top === true ? 1 : 2);
      groupStart += groupCount;
    }
  }
  CylinderBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;
  function ConeGeometry(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
    CylinderGeometry.call(this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength);
    this.type = 'ConeGeometry';
    this.parameters = {
      radius: radius,
      height: height,
      radialSegments: radialSegments,
      heightSegments: heightSegments,
      openEnded: openEnded,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
  }
  ConeGeometry.prototype = Object.create(CylinderGeometry.prototype);
  ConeGeometry.prototype.constructor = ConeGeometry;
  function ConeBufferGeometry(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
    CylinderBufferGeometry.call(this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength);
    this.type = 'ConeBufferGeometry';
    this.parameters = {
      radius: radius,
      height: height,
      radialSegments: radialSegments,
      heightSegments: heightSegments,
      openEnded: openEnded,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
  }
  ConeBufferGeometry.prototype = Object.create(CylinderBufferGeometry.prototype);
  ConeBufferGeometry.prototype.constructor = ConeBufferGeometry;
  function CircleGeometry(radius, segments, thetaStart, thetaLength) {
    Geometry.call(this);
    this.type = 'CircleGeometry';
    this.parameters = {
      radius: radius,
      segments: segments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    this.fromBufferGeometry(new CircleBufferGeometry(radius, segments, thetaStart, thetaLength));
    this.mergeVertices();
  }
  CircleGeometry.prototype = Object.create(Geometry.prototype);
  CircleGeometry.prototype.constructor = CircleGeometry;
  function CircleBufferGeometry(radius, segments, thetaStart, thetaLength) {
    BufferGeometry.call(this);
    this.type = 'CircleBufferGeometry';
    this.parameters = {
      radius: radius,
      segments: segments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    radius = radius || 1;
    segments = segments !== undefined ? Math.max(3, segments) : 8;
    thetaStart = thetaStart !== undefined ? thetaStart : 0;
    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
    var indices = [];
    var vertices = [];
    var normals = [];
    var uvs = [];
    var i,
        s;
    var vertex = new Vector3();
    var uv = new Vector2();
    vertices.push(0, 0, 0);
    normals.push(0, 0, 1);
    uvs.push(0.5, 0.5);
    for (s = 0, i = 3; s <= segments; s++, i += 3) {
      var segment = thetaStart + s / segments * thetaLength;
      vertex.x = radius * Math.cos(segment);
      vertex.y = radius * Math.sin(segment);
      vertices.push(vertex.x, vertex.y, vertex.z);
      normals.push(0, 0, 1);
      uv.x = (vertices[i] / radius + 1) / 2;
      uv.y = (vertices[i + 1] / radius + 1) / 2;
      uvs.push(uv.x, uv.y);
    }
    for (i = 1; i <= segments; i++) {
      indices.push(i, i + 1, 0);
    }
    this.setIndex(indices);
    this.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    this.addAttribute('normal', new Float32BufferAttribute(normals, 3));
    this.addAttribute('uv', new Float32BufferAttribute(uvs, 2));
  }
  CircleBufferGeometry.prototype = Object.create(BufferGeometry.prototype);
  CircleBufferGeometry.prototype.constructor = CircleBufferGeometry;
  var Geometries = Object.freeze({
    WireframeGeometry: WireframeGeometry,
    ParametricGeometry: ParametricGeometry,
    ParametricBufferGeometry: ParametricBufferGeometry,
    TetrahedronGeometry: TetrahedronGeometry,
    TetrahedronBufferGeometry: TetrahedronBufferGeometry,
    OctahedronGeometry: OctahedronGeometry,
    OctahedronBufferGeometry: OctahedronBufferGeometry,
    IcosahedronGeometry: IcosahedronGeometry,
    IcosahedronBufferGeometry: IcosahedronBufferGeometry,
    DodecahedronGeometry: DodecahedronGeometry,
    DodecahedronBufferGeometry: DodecahedronBufferGeometry,
    PolyhedronGeometry: PolyhedronGeometry,
    PolyhedronBufferGeometry: PolyhedronBufferGeometry,
    TubeGeometry: TubeGeometry,
    TubeBufferGeometry: TubeBufferGeometry,
    TorusKnotGeometry: TorusKnotGeometry,
    TorusKnotBufferGeometry: TorusKnotBufferGeometry,
    TorusGeometry: TorusGeometry,
    TorusBufferGeometry: TorusBufferGeometry,
    TextGeometry: TextGeometry,
    TextBufferGeometry: TextBufferGeometry,
    SphereGeometry: SphereGeometry,
    SphereBufferGeometry: SphereBufferGeometry,
    RingGeometry: RingGeometry,
    RingBufferGeometry: RingBufferGeometry,
    PlaneGeometry: PlaneGeometry,
    PlaneBufferGeometry: PlaneBufferGeometry,
    LatheGeometry: LatheGeometry,
    LatheBufferGeometry: LatheBufferGeometry,
    ShapeGeometry: ShapeGeometry,
    ShapeBufferGeometry: ShapeBufferGeometry,
    ExtrudeGeometry: ExtrudeGeometry,
    ExtrudeBufferGeometry: ExtrudeBufferGeometry,
    EdgesGeometry: EdgesGeometry,
    ConeGeometry: ConeGeometry,
    ConeBufferGeometry: ConeBufferGeometry,
    CylinderGeometry: CylinderGeometry,
    CylinderBufferGeometry: CylinderBufferGeometry,
    CircleGeometry: CircleGeometry,
    CircleBufferGeometry: CircleBufferGeometry,
    BoxGeometry: BoxGeometry,
    BoxBufferGeometry: BoxBufferGeometry
  });
  function ShadowMaterial(parameters) {
    Material.call(this);
    this.type = 'ShadowMaterial';
    this.color = new Color(0x000000);
    this.opacity = 1.0;
    this.lights = true;
    this.transparent = true;
    this.setValues(parameters);
  }
  ShadowMaterial.prototype = Object.create(Material.prototype);
  ShadowMaterial.prototype.constructor = ShadowMaterial;
  ShadowMaterial.prototype.isShadowMaterial = true;
  function RawShaderMaterial(parameters) {
    ShaderMaterial.call(this, parameters);
    this.type = 'RawShaderMaterial';
  }
  RawShaderMaterial.prototype = Object.create(ShaderMaterial.prototype);
  RawShaderMaterial.prototype.constructor = RawShaderMaterial;
  RawShaderMaterial.prototype.isRawShaderMaterial = true;
  function MeshStandardMaterial(parameters) {
    Material.call(this);
    this.defines = {'STANDARD': ''};
    this.type = 'MeshStandardMaterial';
    this.color = new Color(0xffffff);
    this.roughness = 0.5;
    this.metalness = 0.5;
    this.map = null;
    this.lightMap = null;
    this.lightMapIntensity = 1.0;
    this.aoMap = null;
    this.aoMapIntensity = 1.0;
    this.emissive = new Color(0x000000);
    this.emissiveIntensity = 1.0;
    this.emissiveMap = null;
    this.bumpMap = null;
    this.bumpScale = 1;
    this.normalMap = null;
    this.normalScale = new Vector2(1, 1);
    this.displacementMap = null;
    this.displacementScale = 1;
    this.displacementBias = 0;
    this.roughnessMap = null;
    this.metalnessMap = null;
    this.alphaMap = null;
    this.envMap = null;
    this.envMapIntensity = 1.0;
    this.refractionRatio = 0.98;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.setValues(parameters);
  }
  MeshStandardMaterial.prototype = Object.create(Material.prototype);
  MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
  MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
  MeshStandardMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.defines = {'STANDARD': ''};
    this.color.copy(source.color);
    this.roughness = source.roughness;
    this.metalness = source.metalness;
    this.map = source.map;
    this.lightMap = source.lightMap;
    this.lightMapIntensity = source.lightMapIntensity;
    this.aoMap = source.aoMap;
    this.aoMapIntensity = source.aoMapIntensity;
    this.emissive.copy(source.emissive);
    this.emissiveMap = source.emissiveMap;
    this.emissiveIntensity = source.emissiveIntensity;
    this.bumpMap = source.bumpMap;
    this.bumpScale = source.bumpScale;
    this.normalMap = source.normalMap;
    this.normalScale.copy(source.normalScale);
    this.displacementMap = source.displacementMap;
    this.displacementScale = source.displacementScale;
    this.displacementBias = source.displacementBias;
    this.roughnessMap = source.roughnessMap;
    this.metalnessMap = source.metalnessMap;
    this.alphaMap = source.alphaMap;
    this.envMap = source.envMap;
    this.envMapIntensity = source.envMapIntensity;
    this.refractionRatio = source.refractionRatio;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.wireframeLinecap = source.wireframeLinecap;
    this.wireframeLinejoin = source.wireframeLinejoin;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    return this;
  };
  function MeshPhysicalMaterial(parameters) {
    MeshStandardMaterial.call(this);
    this.defines = {'PHYSICAL': ''};
    this.type = 'MeshPhysicalMaterial';
    this.reflectivity = 0.5;
    this.clearCoat = 0.0;
    this.clearCoatRoughness = 0.0;
    this.setValues(parameters);
  }
  MeshPhysicalMaterial.prototype = Object.create(MeshStandardMaterial.prototype);
  MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
  MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
  MeshPhysicalMaterial.prototype.copy = function(source) {
    MeshStandardMaterial.prototype.copy.call(this, source);
    this.defines = {'PHYSICAL': ''};
    this.reflectivity = source.reflectivity;
    this.clearCoat = source.clearCoat;
    this.clearCoatRoughness = source.clearCoatRoughness;
    return this;
  };
  function MeshPhongMaterial(parameters) {
    Material.call(this);
    this.type = 'MeshPhongMaterial';
    this.color = new Color(0xffffff);
    this.specular = new Color(0x111111);
    this.shininess = 30;
    this.map = null;
    this.lightMap = null;
    this.lightMapIntensity = 1.0;
    this.aoMap = null;
    this.aoMapIntensity = 1.0;
    this.emissive = new Color(0x000000);
    this.emissiveIntensity = 1.0;
    this.emissiveMap = null;
    this.bumpMap = null;
    this.bumpScale = 1;
    this.normalMap = null;
    this.normalScale = new Vector2(1, 1);
    this.displacementMap = null;
    this.displacementScale = 1;
    this.displacementBias = 0;
    this.specularMap = null;
    this.alphaMap = null;
    this.envMap = null;
    this.combine = MultiplyOperation;
    this.reflectivity = 1;
    this.refractionRatio = 0.98;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.setValues(parameters);
  }
  MeshPhongMaterial.prototype = Object.create(Material.prototype);
  MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
  MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
  MeshPhongMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.specular.copy(source.specular);
    this.shininess = source.shininess;
    this.map = source.map;
    this.lightMap = source.lightMap;
    this.lightMapIntensity = source.lightMapIntensity;
    this.aoMap = source.aoMap;
    this.aoMapIntensity = source.aoMapIntensity;
    this.emissive.copy(source.emissive);
    this.emissiveMap = source.emissiveMap;
    this.emissiveIntensity = source.emissiveIntensity;
    this.bumpMap = source.bumpMap;
    this.bumpScale = source.bumpScale;
    this.normalMap = source.normalMap;
    this.normalScale.copy(source.normalScale);
    this.displacementMap = source.displacementMap;
    this.displacementScale = source.displacementScale;
    this.displacementBias = source.displacementBias;
    this.specularMap = source.specularMap;
    this.alphaMap = source.alphaMap;
    this.envMap = source.envMap;
    this.combine = source.combine;
    this.reflectivity = source.reflectivity;
    this.refractionRatio = source.refractionRatio;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.wireframeLinecap = source.wireframeLinecap;
    this.wireframeLinejoin = source.wireframeLinejoin;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    return this;
  };
  function MeshToonMaterial(parameters) {
    MeshPhongMaterial.call(this);
    this.defines = {'TOON': ''};
    this.type = 'MeshToonMaterial';
    this.gradientMap = null;
    this.setValues(parameters);
  }
  MeshToonMaterial.prototype = Object.create(MeshPhongMaterial.prototype);
  MeshToonMaterial.prototype.constructor = MeshToonMaterial;
  MeshToonMaterial.prototype.isMeshToonMaterial = true;
  MeshToonMaterial.prototype.copy = function(source) {
    MeshPhongMaterial.prototype.copy.call(this, source);
    this.gradientMap = source.gradientMap;
    return this;
  };
  function MeshNormalMaterial(parameters) {
    Material.call(this);
    this.type = 'MeshNormalMaterial';
    this.bumpMap = null;
    this.bumpScale = 1;
    this.normalMap = null;
    this.normalScale = new Vector2(1, 1);
    this.displacementMap = null;
    this.displacementScale = 1;
    this.displacementBias = 0;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.fog = false;
    this.lights = false;
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.setValues(parameters);
  }
  MeshNormalMaterial.prototype = Object.create(Material.prototype);
  MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
  MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
  MeshNormalMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.bumpMap = source.bumpMap;
    this.bumpScale = source.bumpScale;
    this.normalMap = source.normalMap;
    this.normalScale.copy(source.normalScale);
    this.displacementMap = source.displacementMap;
    this.displacementScale = source.displacementScale;
    this.displacementBias = source.displacementBias;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    return this;
  };
  function MeshLambertMaterial(parameters) {
    Material.call(this);
    this.type = 'MeshLambertMaterial';
    this.color = new Color(0xffffff);
    this.map = null;
    this.lightMap = null;
    this.lightMapIntensity = 1.0;
    this.aoMap = null;
    this.aoMapIntensity = 1.0;
    this.emissive = new Color(0x000000);
    this.emissiveIntensity = 1.0;
    this.emissiveMap = null;
    this.specularMap = null;
    this.alphaMap = null;
    this.envMap = null;
    this.combine = MultiplyOperation;
    this.reflectivity = 1;
    this.refractionRatio = 0.98;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.setValues(parameters);
  }
  MeshLambertMaterial.prototype = Object.create(Material.prototype);
  MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
  MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
  MeshLambertMaterial.prototype.copy = function(source) {
    Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.map = source.map;
    this.lightMap = source.lightMap;
    this.lightMapIntensity = source.lightMapIntensity;
    this.aoMap = source.aoMap;
    this.aoMapIntensity = source.aoMapIntensity;
    this.emissive.copy(source.emissive);
    this.emissiveMap = source.emissiveMap;
    this.emissiveIntensity = source.emissiveIntensity;
    this.specularMap = source.specularMap;
    this.alphaMap = source.alphaMap;
    this.envMap = source.envMap;
    this.combine = source.combine;
    this.reflectivity = source.reflectivity;
    this.refractionRatio = source.refractionRatio;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.wireframeLinecap = source.wireframeLinecap;
    this.wireframeLinejoin = source.wireframeLinejoin;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    return this;
  };
  function LineDashedMaterial(parameters) {
    LineBasicMaterial.call(this);
    this.type = 'LineDashedMaterial';
    this.scale = 1;
    this.dashSize = 3;
    this.gapSize = 1;
    this.setValues(parameters);
  }
  LineDashedMaterial.prototype = Object.create(LineBasicMaterial.prototype);
  LineDashedMaterial.prototype.constructor = LineDashedMaterial;
  LineDashedMaterial.prototype.isLineDashedMaterial = true;
  LineDashedMaterial.prototype.copy = function(source) {
    LineBasicMaterial.prototype.copy.call(this, source);
    this.scale = source.scale;
    this.dashSize = source.dashSize;
    this.gapSize = source.gapSize;
    return this;
  };
  var Materials = Object.freeze({
    ShadowMaterial: ShadowMaterial,
    SpriteMaterial: SpriteMaterial,
    RawShaderMaterial: RawShaderMaterial,
    ShaderMaterial: ShaderMaterial,
    PointsMaterial: PointsMaterial,
    MeshPhysicalMaterial: MeshPhysicalMaterial,
    MeshStandardMaterial: MeshStandardMaterial,
    MeshPhongMaterial: MeshPhongMaterial,
    MeshToonMaterial: MeshToonMaterial,
    MeshNormalMaterial: MeshNormalMaterial,
    MeshLambertMaterial: MeshLambertMaterial,
    MeshDepthMaterial: MeshDepthMaterial,
    MeshDistanceMaterial: MeshDistanceMaterial,
    MeshBasicMaterial: MeshBasicMaterial,
    LineDashedMaterial: LineDashedMaterial,
    LineBasicMaterial: LineBasicMaterial,
    Material: Material
  });
  var Cache = {
    enabled: false,
    files: {},
    add: function(key, file) {
      if (this.enabled === false)
        return;
      this.files[key] = file;
    },
    get: function(key) {
      if (this.enabled === false)
        return;
      return this.files[key];
    },
    remove: function(key) {
      delete this.files[key];
    },
    clear: function() {
      this.files = {};
    }
  };
  function LoadingManager(onLoad, onProgress, onError) {
    var scope = this;
    var isLoading = false;
    var itemsLoaded = 0;
    var itemsTotal = 0;
    var urlModifier = undefined;
    this.onStart = undefined;
    this.onLoad = onLoad;
    this.onProgress = onProgress;
    this.onError = onError;
    this.itemStart = function(url) {
      itemsTotal++;
      if (isLoading === false) {
        if (scope.onStart !== undefined) {
          scope.onStart(url, itemsLoaded, itemsTotal);
        }
      }
      isLoading = true;
    };
    this.itemEnd = function(url) {
      itemsLoaded++;
      if (scope.onProgress !== undefined) {
        scope.onProgress(url, itemsLoaded, itemsTotal);
      }
      if (itemsLoaded === itemsTotal) {
        isLoading = false;
        if (scope.onLoad !== undefined) {
          scope.onLoad();
        }
      }
    };
    this.itemError = function(url) {
      if (scope.onError !== undefined) {
        scope.onError(url);
      }
    };
    this.resolveURL = function(url) {
      if (urlModifier) {
        return urlModifier(url);
      }
      return url;
    };
    this.setURLModifier = function(transform) {
      urlModifier = transform;
    };
  }
  var DefaultLoadingManager = new LoadingManager();
  var loading = {};
  function FileLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
  }
  Object.assign(FileLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      if (url === undefined)
        url = '';
      if (this.path !== undefined)
        url = this.path + url;
      url = this.manager.resolveURL(url);
      var scope = this;
      var cached = Cache.get(url);
      if (cached !== undefined) {
        scope.manager.itemStart(url);
        setTimeout(function() {
          if (onLoad)
            onLoad(cached);
          scope.manager.itemEnd(url);
        }, 0);
        return cached;
      }
      if (loading[url] !== undefined) {
        loading[url].push({
          onLoad: onLoad,
          onProgress: onProgress,
          onError: onError
        });
        return;
      }
      var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
      var dataUriRegexResult = url.match(dataUriRegex);
      if (dataUriRegexResult) {
        var mimeType = dataUriRegexResult[1];
        var isBase64 = !!dataUriRegexResult[2];
        var data = dataUriRegexResult[3];
        data = window.decodeURIComponent(data);
        if (isBase64)
          data = window.atob(data);
        try {
          var response;
          var responseType = (this.responseType || '').toLowerCase();
          switch (responseType) {
            case 'arraybuffer':
            case 'blob':
              var view = new Uint8Array(data.length);
              for (var i = 0; i < data.length; i++) {
                view[i] = data.charCodeAt(i);
              }
              if (responseType === 'blob') {
                response = new Blob([view.buffer], {type: mimeType});
              } else {
                response = view.buffer;
              }
              break;
            case 'document':
              var parser = new DOMParser();
              response = parser.parseFromString(data, mimeType);
              break;
            case 'json':
              response = JSON.parse(data);
              break;
            default:
              response = data;
              break;
          }
          window.setTimeout(function() {
            if (onLoad)
              onLoad(response);
            scope.manager.itemEnd(url);
          }, 0);
        } catch (error) {
          window.setTimeout(function() {
            if (onError)
              onError(error);
            scope.manager.itemEnd(url);
            scope.manager.itemError(url);
          }, 0);
        }
      } else {
        loading[url] = [];
        loading[url].push({
          onLoad: onLoad,
          onProgress: onProgress,
          onError: onError
        });
        var request = new XMLHttpRequest();
        request.open('GET', url, true);
        request.addEventListener('load', function(event) {
          var response = event.target.response;
          Cache.add(url, response);
          var callbacks = loading[url];
          delete loading[url];
          if (this.status === 200) {
            for (var i = 0,
                il = callbacks.length; i < il; i++) {
              var callback = callbacks[i];
              if (callback.onLoad)
                callback.onLoad(response);
            }
            scope.manager.itemEnd(url);
          } else if (this.status === 0) {
            console.warn('THREE.FileLoader: HTTP Status 0 received.');
            for (var i = 0,
                il = callbacks.length; i < il; i++) {
              var callback = callbacks[i];
              if (callback.onLoad)
                callback.onLoad(response);
            }
            scope.manager.itemEnd(url);
          } else {
            for (var i = 0,
                il = callbacks.length; i < il; i++) {
              var callback = callbacks[i];
              if (callback.onError)
                callback.onError(event);
            }
            scope.manager.itemEnd(url);
            scope.manager.itemError(url);
          }
        }, false);
        request.addEventListener('progress', function(event) {
          var callbacks = loading[url];
          for (var i = 0,
              il = callbacks.length; i < il; i++) {
            var callback = callbacks[i];
            if (callback.onProgress)
              callback.onProgress(event);
          }
        }, false);
        request.addEventListener('error', function(event) {
          var callbacks = loading[url];
          delete loading[url];
          for (var i = 0,
              il = callbacks.length; i < il; i++) {
            var callback = callbacks[i];
            if (callback.onError)
              callback.onError(event);
          }
          scope.manager.itemEnd(url);
          scope.manager.itemError(url);
        }, false);
        if (this.responseType !== undefined)
          request.responseType = this.responseType;
        if (this.withCredentials !== undefined)
          request.withCredentials = this.withCredentials;
        if (request.overrideMimeType)
          request.overrideMimeType(this.mimeType !== undefined ? this.mimeType : 'text/plain');
        for (var header in this.requestHeader) {
          request.setRequestHeader(header, this.requestHeader[header]);
        }
        request.send(null);
      }
      scope.manager.itemStart(url);
      return request;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    },
    setResponseType: function(value) {
      this.responseType = value;
      return this;
    },
    setWithCredentials: function(value) {
      this.withCredentials = value;
      return this;
    },
    setMimeType: function(value) {
      this.mimeType = value;
      return this;
    },
    setRequestHeader: function(value) {
      this.requestHeader = value;
      return this;
    }
  });
  function CompressedTextureLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
    this._parser = null;
  }
  Object.assign(CompressedTextureLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var images = [];
      var texture = new CompressedTexture();
      texture.image = images;
      var loader = new FileLoader(this.manager);
      loader.setPath(this.path);
      loader.setResponseType('arraybuffer');
      function loadTexture(i) {
        loader.load(url[i], function(buffer) {
          var texDatas = scope._parser(buffer, true);
          images[i] = {
            width: texDatas.width,
            height: texDatas.height,
            format: texDatas.format,
            mipmaps: texDatas.mipmaps
          };
          loaded += 1;
          if (loaded === 6) {
            if (texDatas.mipmapCount === 1)
              texture.minFilter = LinearFilter;
            texture.format = texDatas.format;
            texture.needsUpdate = true;
            if (onLoad)
              onLoad(texture);
          }
        }, onProgress, onError);
      }
      if (Array.isArray(url)) {
        var loaded = 0;
        for (var i = 0,
            il = url.length; i < il; ++i) {
          loadTexture(i);
        }
      } else {
        loader.load(url, function(buffer) {
          var texDatas = scope._parser(buffer, true);
          if (texDatas.isCubemap) {
            var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
            for (var f = 0; f < faces; f++) {
              images[f] = {mipmaps: []};
              for (var i = 0; i < texDatas.mipmapCount; i++) {
                images[f].mipmaps.push(texDatas.mipmaps[f * texDatas.mipmapCount + i]);
                images[f].format = texDatas.format;
                images[f].width = texDatas.width;
                images[f].height = texDatas.height;
              }
            }
          } else {
            texture.image.width = texDatas.width;
            texture.image.height = texDatas.height;
            texture.mipmaps = texDatas.mipmaps;
          }
          if (texDatas.mipmapCount === 1) {
            texture.minFilter = LinearFilter;
          }
          texture.format = texDatas.format;
          texture.needsUpdate = true;
          if (onLoad)
            onLoad(texture);
        }, onProgress, onError);
      }
      return texture;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  function DataTextureLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
    this._parser = null;
  }
  Object.assign(DataTextureLoader.prototype, {load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var texture = new DataTexture();
      var loader = new FileLoader(this.manager);
      loader.setResponseType('arraybuffer');
      loader.load(url, function(buffer) {
        var texData = scope._parser(buffer);
        if (!texData)
          return;
        if (undefined !== texData.image) {
          texture.image = texData.image;
        } else if (undefined !== texData.data) {
          texture.image.width = texData.width;
          texture.image.height = texData.height;
          texture.image.data = texData.data;
        }
        texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping;
        texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping;
        texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter;
        texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter;
        texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
        if (undefined !== texData.format) {
          texture.format = texData.format;
        }
        if (undefined !== texData.type) {
          texture.type = texData.type;
        }
        if (undefined !== texData.mipmaps) {
          texture.mipmaps = texData.mipmaps;
        }
        if (1 === texData.mipmapCount) {
          texture.minFilter = LinearFilter;
        }
        texture.needsUpdate = true;
        if (onLoad)
          onLoad(texture, texData);
      }, onProgress, onError);
      return texture;
    }});
  function ImageLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
  }
  Object.assign(ImageLoader.prototype, {
    crossOrigin: 'Anonymous',
    load: function(url, onLoad, onProgress, onError) {
      if (url === undefined)
        url = '';
      if (this.path !== undefined)
        url = this.path + url;
      url = this.manager.resolveURL(url);
      var scope = this;
      var cached = Cache.get(url);
      if (cached !== undefined) {
        scope.manager.itemStart(url);
        setTimeout(function() {
          if (onLoad)
            onLoad(cached);
          scope.manager.itemEnd(url);
        }, 0);
        return cached;
      }
      var image = document.createElementNS('http://www.w3.org/1999/xhtml', 'img');
      image.addEventListener('load', function() {
        Cache.add(url, this);
        if (onLoad)
          onLoad(this);
        scope.manager.itemEnd(url);
      }, false);
      image.addEventListener('error', function(event) {
        if (onError)
          onError(event);
        scope.manager.itemEnd(url);
        scope.manager.itemError(url);
      }, false);
      if (url.substr(0, 5) !== 'data:') {
        if (this.crossOrigin !== undefined)
          image.crossOrigin = this.crossOrigin;
      }
      scope.manager.itemStart(url);
      image.src = url;
      return image;
    },
    setCrossOrigin: function(value) {
      this.crossOrigin = value;
      return this;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  function CubeTextureLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
  }
  Object.assign(CubeTextureLoader.prototype, {
    crossOrigin: 'Anonymous',
    load: function(urls, onLoad, onProgress, onError) {
      var texture = new CubeTexture();
      var loader = new ImageLoader(this.manager);
      loader.setCrossOrigin(this.crossOrigin);
      loader.setPath(this.path);
      var loaded = 0;
      function loadTexture(i) {
        loader.load(urls[i], function(image) {
          texture.images[i] = image;
          loaded++;
          if (loaded === 6) {
            texture.needsUpdate = true;
            if (onLoad)
              onLoad(texture);
          }
        }, undefined, onError);
      }
      for (var i = 0; i < urls.length; ++i) {
        loadTexture(i);
      }
      return texture;
    },
    setCrossOrigin: function(value) {
      this.crossOrigin = value;
      return this;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  function TextureLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
  }
  Object.assign(TextureLoader.prototype, {
    crossOrigin: 'Anonymous',
    load: function(url, onLoad, onProgress, onError) {
      var loader = new ImageLoader(this.manager);
      loader.setCrossOrigin(this.crossOrigin);
      loader.setPath(this.path);
      var texture = new Texture();
      texture.image = loader.load(url, function() {
        var isJPEG = url.search(/\.(jpg|jpeg)$/) > 0 || url.search(/^data\:image\/jpeg/) === 0;
        texture.format = isJPEG ? RGBFormat : RGBAFormat;
        texture.needsUpdate = true;
        if (onLoad !== undefined) {
          onLoad(texture);
        }
      }, onProgress, onError);
      return texture;
    },
    setCrossOrigin: function(value) {
      this.crossOrigin = value;
      return this;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  function Light(color, intensity) {
    Object3D.call(this);
    this.type = 'Light';
    this.color = new Color(color);
    this.intensity = intensity !== undefined ? intensity : 1;
    this.receiveShadow = undefined;
  }
  Light.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Light,
    isLight: true,
    copy: function(source) {
      Object3D.prototype.copy.call(this, source);
      this.color.copy(source.color);
      this.intensity = source.intensity;
      return this;
    },
    toJSON: function(meta) {
      var data = Object3D.prototype.toJSON.call(this, meta);
      data.object.color = this.color.getHex();
      data.object.intensity = this.intensity;
      if (this.groundColor !== undefined)
        data.object.groundColor = this.groundColor.getHex();
      if (this.distance !== undefined)
        data.object.distance = this.distance;
      if (this.angle !== undefined)
        data.object.angle = this.angle;
      if (this.decay !== undefined)
        data.object.decay = this.decay;
      if (this.penumbra !== undefined)
        data.object.penumbra = this.penumbra;
      if (this.shadow !== undefined)
        data.object.shadow = this.shadow.toJSON();
      return data;
    }
  });
  function HemisphereLight(skyColor, groundColor, intensity) {
    Light.call(this, skyColor, intensity);
    this.type = 'HemisphereLight';
    this.castShadow = undefined;
    this.position.copy(Object3D.DefaultUp);
    this.updateMatrix();
    this.groundColor = new Color(groundColor);
  }
  HemisphereLight.prototype = Object.assign(Object.create(Light.prototype), {
    constructor: HemisphereLight,
    isHemisphereLight: true,
    copy: function(source) {
      Light.prototype.copy.call(this, source);
      this.groundColor.copy(source.groundColor);
      return this;
    }
  });
  function LightShadow(camera) {
    this.camera = camera;
    this.bias = 0;
    this.radius = 1;
    this.mapSize = new Vector2(512, 512);
    this.map = null;
    this.matrix = new Matrix4();
  }
  Object.assign(LightShadow.prototype, {
    copy: function(source) {
      this.camera = source.camera.clone();
      this.bias = source.bias;
      this.radius = source.radius;
      this.mapSize.copy(source.mapSize);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    toJSON: function() {
      var object = {};
      if (this.bias !== 0)
        object.bias = this.bias;
      if (this.radius !== 1)
        object.radius = this.radius;
      if (this.mapSize.x !== 512 || this.mapSize.y !== 512)
        object.mapSize = this.mapSize.toArray();
      object.camera = this.camera.toJSON(false).object;
      delete object.camera.matrix;
      return object;
    }
  });
  function SpotLightShadow() {
    LightShadow.call(this, new PerspectiveCamera(50, 1, 0.5, 500));
  }
  SpotLightShadow.prototype = Object.assign(Object.create(LightShadow.prototype), {
    constructor: SpotLightShadow,
    isSpotLightShadow: true,
    update: function(light) {
      var camera = this.camera;
      var fov = _Math.RAD2DEG * 2 * light.angle;
      var aspect = this.mapSize.width / this.mapSize.height;
      var far = light.distance || camera.far;
      if (fov !== camera.fov || aspect !== camera.aspect || far !== camera.far) {
        camera.fov = fov;
        camera.aspect = aspect;
        camera.far = far;
        camera.updateProjectionMatrix();
      }
    }
  });
  function SpotLight(color, intensity, distance, angle, penumbra, decay) {
    Light.call(this, color, intensity);
    this.type = 'SpotLight';
    this.position.copy(Object3D.DefaultUp);
    this.updateMatrix();
    this.target = new Object3D();
    Object.defineProperty(this, 'power', {
      get: function() {
        return this.intensity * Math.PI;
      },
      set: function(power) {
        this.intensity = power / Math.PI;
      }
    });
    this.distance = (distance !== undefined) ? distance : 0;
    this.angle = (angle !== undefined) ? angle : Math.PI / 3;
    this.penumbra = (penumbra !== undefined) ? penumbra : 0;
    this.decay = (decay !== undefined) ? decay : 1;
    this.shadow = new SpotLightShadow();
  }
  SpotLight.prototype = Object.assign(Object.create(Light.prototype), {
    constructor: SpotLight,
    isSpotLight: true,
    copy: function(source) {
      Light.prototype.copy.call(this, source);
      this.distance = source.distance;
      this.angle = source.angle;
      this.penumbra = source.penumbra;
      this.decay = source.decay;
      this.target = source.target.clone();
      this.shadow = source.shadow.clone();
      return this;
    }
  });
  function PointLight(color, intensity, distance, decay) {
    Light.call(this, color, intensity);
    this.type = 'PointLight';
    Object.defineProperty(this, 'power', {
      get: function() {
        return this.intensity * 4 * Math.PI;
      },
      set: function(power) {
        this.intensity = power / (4 * Math.PI);
      }
    });
    this.distance = (distance !== undefined) ? distance : 0;
    this.decay = (decay !== undefined) ? decay : 1;
    this.shadow = new LightShadow(new PerspectiveCamera(90, 1, 0.5, 500));
  }
  PointLight.prototype = Object.assign(Object.create(Light.prototype), {
    constructor: PointLight,
    isPointLight: true,
    copy: function(source) {
      Light.prototype.copy.call(this, source);
      this.distance = source.distance;
      this.decay = source.decay;
      this.shadow = source.shadow.clone();
      return this;
    }
  });
  function DirectionalLightShadow() {
    LightShadow.call(this, new OrthographicCamera(-5, 5, 5, -5, 0.5, 500));
  }
  DirectionalLightShadow.prototype = Object.assign(Object.create(LightShadow.prototype), {constructor: DirectionalLightShadow});
  function DirectionalLight(color, intensity) {
    Light.call(this, color, intensity);
    this.type = 'DirectionalLight';
    this.position.copy(Object3D.DefaultUp);
    this.updateMatrix();
    this.target = new Object3D();
    this.shadow = new DirectionalLightShadow();
  }
  DirectionalLight.prototype = Object.assign(Object.create(Light.prototype), {
    constructor: DirectionalLight,
    isDirectionalLight: true,
    copy: function(source) {
      Light.prototype.copy.call(this, source);
      this.target = source.target.clone();
      this.shadow = source.shadow.clone();
      return this;
    }
  });
  function AmbientLight(color, intensity) {
    Light.call(this, color, intensity);
    this.type = 'AmbientLight';
    this.castShadow = undefined;
  }
  AmbientLight.prototype = Object.assign(Object.create(Light.prototype), {
    constructor: AmbientLight,
    isAmbientLight: true
  });
  function RectAreaLight(color, intensity, width, height) {
    Light.call(this, color, intensity);
    this.type = 'RectAreaLight';
    this.position.set(0, 1, 0);
    this.updateMatrix();
    this.width = (width !== undefined) ? width : 10;
    this.height = (height !== undefined) ? height : 10;
  }
  RectAreaLight.prototype = Object.assign(Object.create(Light.prototype), {
    constructor: RectAreaLight,
    isRectAreaLight: true,
    copy: function(source) {
      Light.prototype.copy.call(this, source);
      this.width = source.width;
      this.height = source.height;
      return this;
    },
    toJSON: function(meta) {
      var data = Light.prototype.toJSON.call(this, meta);
      data.object.width = this.width;
      data.object.height = this.height;
      return data;
    }
  });
  var AnimationUtils = {
    arraySlice: function(array, from, to) {
      if (AnimationUtils.isTypedArray(array)) {
        return new array.constructor(array.subarray(from, to !== undefined ? to : array.length));
      }
      return array.slice(from, to);
    },
    convertArray: function(array, type, forceClone) {
      if (!array || !forceClone && array.constructor === type)
        return array;
      if (typeof type.BYTES_PER_ELEMENT === 'number') {
        return new type(array);
      }
      return Array.prototype.slice.call(array);
    },
    isTypedArray: function(object) {
      return ArrayBuffer.isView(object) && !(object instanceof DataView);
    },
    getKeyframeOrder: function(times) {
      function compareTime(i, j) {
        return times[i] - times[j];
      }
      var n = times.length;
      var result = new Array(n);
      for (var i = 0; i !== n; ++i)
        result[i] = i;
      result.sort(compareTime);
      return result;
    },
    sortedArray: function(values, stride, order) {
      var nValues = values.length;
      var result = new values.constructor(nValues);
      for (var i = 0,
          dstOffset = 0; dstOffset !== nValues; ++i) {
        var srcOffset = order[i] * stride;
        for (var j = 0; j !== stride; ++j) {
          result[dstOffset++] = values[srcOffset + j];
        }
      }
      return result;
    },
    flattenJSON: function(jsonKeys, times, values, valuePropertyName) {
      var i = 1,
          key = jsonKeys[0];
      while (key !== undefined && key[valuePropertyName] === undefined) {
        key = jsonKeys[i++];
      }
      if (key === undefined)
        return;
      var value = key[valuePropertyName];
      if (value === undefined)
        return;
      if (Array.isArray(value)) {
        do {
          value = key[valuePropertyName];
          if (value !== undefined) {
            times.push(key.time);
            values.push.apply(values, value);
          }
          key = jsonKeys[i++];
        } while (key !== undefined);
      } else if (value.toArray !== undefined) {
        do {
          value = key[valuePropertyName];
          if (value !== undefined) {
            times.push(key.time);
            value.toArray(values, values.length);
          }
          key = jsonKeys[i++];
        } while (key !== undefined);
      } else {
        do {
          value = key[valuePropertyName];
          if (value !== undefined) {
            times.push(key.time);
            values.push(value);
          }
          key = jsonKeys[i++];
        } while (key !== undefined);
      }
    }
  };
  function Interpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    this.parameterPositions = parameterPositions;
    this._cachedIndex = 0;
    this.resultBuffer = resultBuffer !== undefined ? resultBuffer : new sampleValues.constructor(sampleSize);
    this.sampleValues = sampleValues;
    this.valueSize = sampleSize;
  }
  Object.assign(Interpolant.prototype, {
    evaluate: function(t) {
      var pp = this.parameterPositions,
          i1 = this._cachedIndex,
          t1 = pp[i1],
          t0 = pp[i1 - 1];
      validate_interval: {
        seek: {
          var right;
          linear_scan: {
            forward_scan: if (!(t < t1)) {
              for (var giveUpAt = i1 + 2; ; ) {
                if (t1 === undefined) {
                  if (t < t0)
                    break forward_scan;
                  i1 = pp.length;
                  this._cachedIndex = i1;
                  return this.afterEnd_(i1 - 1, t, t0);
                }
                if (i1 === giveUpAt)
                  break;
                t0 = t1;
                t1 = pp[++i1];
                if (t < t1) {
                  break seek;
                }
              }
              right = pp.length;
              break linear_scan;
            }
            if (!(t >= t0)) {
              var t1global = pp[1];
              if (t < t1global) {
                i1 = 2;
                t0 = t1global;
              }
              for (var giveUpAt = i1 - 2; ; ) {
                if (t0 === undefined) {
                  this._cachedIndex = 0;
                  return this.beforeStart_(0, t, t1);
                }
                if (i1 === giveUpAt)
                  break;
                t1 = t0;
                t0 = pp[--i1 - 1];
                if (t >= t0) {
                  break seek;
                }
              }
              right = i1;
              i1 = 0;
              break linear_scan;
            }
            break validate_interval;
          }
          while (i1 < right) {
            var mid = (i1 + right) >>> 1;
            if (t < pp[mid]) {
              right = mid;
            } else {
              i1 = mid + 1;
            }
          }
          t1 = pp[i1];
          t0 = pp[i1 - 1];
          if (t0 === undefined) {
            this._cachedIndex = 0;
            return this.beforeStart_(0, t, t1);
          }
          if (t1 === undefined) {
            i1 = pp.length;
            this._cachedIndex = i1;
            return this.afterEnd_(i1 - 1, t0, t);
          }
        }
        this._cachedIndex = i1;
        this.intervalChanged_(i1, t0, t1);
      }
      return this.interpolate_(i1, t0, t, t1);
    },
    settings: null,
    DefaultSettings_: {},
    getSettings_: function() {
      return this.settings || this.DefaultSettings_;
    },
    copySampleValue_: function(index) {
      var result = this.resultBuffer,
          values = this.sampleValues,
          stride = this.valueSize,
          offset = index * stride;
      for (var i = 0; i !== stride; ++i) {
        result[i] = values[offset + i];
      }
      return result;
    },
    interpolate_: function() {
      throw new Error('call to abstract method');
    },
    intervalChanged_: function() {}
  });
  Object.assign(Interpolant.prototype, {
    beforeStart_: Interpolant.prototype.copySampleValue_,
    afterEnd_: Interpolant.prototype.copySampleValue_
  });
  function CubicInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
    this._weightPrev = -0;
    this._offsetPrev = -0;
    this._weightNext = -0;
    this._offsetNext = -0;
  }
  CubicInterpolant.prototype = Object.assign(Object.create(Interpolant.prototype), {
    constructor: CubicInterpolant,
    DefaultSettings_: {
      endingStart: ZeroCurvatureEnding,
      endingEnd: ZeroCurvatureEnding
    },
    intervalChanged_: function(i1, t0, t1) {
      var pp = this.parameterPositions,
          iPrev = i1 - 2,
          iNext = i1 + 1,
          tPrev = pp[iPrev],
          tNext = pp[iNext];
      if (tPrev === undefined) {
        switch (this.getSettings_().endingStart) {
          case ZeroSlopeEnding:
            iPrev = i1;
            tPrev = 2 * t0 - t1;
            break;
          case WrapAroundEnding:
            iPrev = pp.length - 2;
            tPrev = t0 + pp[iPrev] - pp[iPrev + 1];
            break;
          default:
            iPrev = i1;
            tPrev = t1;
        }
      }
      if (tNext === undefined) {
        switch (this.getSettings_().endingEnd) {
          case ZeroSlopeEnding:
            iNext = i1;
            tNext = 2 * t1 - t0;
            break;
          case WrapAroundEnding:
            iNext = 1;
            tNext = t1 + pp[1] - pp[0];
            break;
          default:
            iNext = i1 - 1;
            tNext = t0;
        }
      }
      var halfDt = (t1 - t0) * 0.5,
          stride = this.valueSize;
      this._weightPrev = halfDt / (t0 - tPrev);
      this._weightNext = halfDt / (tNext - t1);
      this._offsetPrev = iPrev * stride;
      this._offsetNext = iNext * stride;
    },
    interpolate_: function(i1, t0, t, t1) {
      var result = this.resultBuffer,
          values = this.sampleValues,
          stride = this.valueSize,
          o1 = i1 * stride,
          o0 = o1 - stride,
          oP = this._offsetPrev,
          oN = this._offsetNext,
          wP = this._weightPrev,
          wN = this._weightNext,
          p = (t - t0) / (t1 - t0),
          pp = p * p,
          ppp = pp * p;
      var sP = -wP * ppp + 2 * wP * pp - wP * p;
      var s0 = (1 + wP) * ppp + (-1.5 - 2 * wP) * pp + (-0.5 + wP) * p + 1;
      var s1 = (-1 - wN) * ppp + (1.5 + wN) * pp + 0.5 * p;
      var sN = wN * ppp - wN * pp;
      for (var i = 0; i !== stride; ++i) {
        result[i] = sP * values[oP + i] + s0 * values[o0 + i] + s1 * values[o1 + i] + sN * values[oN + i];
      }
      return result;
    }
  });
  function LinearInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
  }
  LinearInterpolant.prototype = Object.assign(Object.create(Interpolant.prototype), {
    constructor: LinearInterpolant,
    interpolate_: function(i1, t0, t, t1) {
      var result = this.resultBuffer,
          values = this.sampleValues,
          stride = this.valueSize,
          offset1 = i1 * stride,
          offset0 = offset1 - stride,
          weight1 = (t - t0) / (t1 - t0),
          weight0 = 1 - weight1;
      for (var i = 0; i !== stride; ++i) {
        result[i] = values[offset0 + i] * weight0 + values[offset1 + i] * weight1;
      }
      return result;
    }
  });
  function DiscreteInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
  }
  DiscreteInterpolant.prototype = Object.assign(Object.create(Interpolant.prototype), {
    constructor: DiscreteInterpolant,
    interpolate_: function(i1) {
      return this.copySampleValue_(i1 - 1);
    }
  });
  var KeyframeTrackPrototype;
  KeyframeTrackPrototype = {
    TimeBufferType: Float32Array,
    ValueBufferType: Float32Array,
    DefaultInterpolation: InterpolateLinear,
    InterpolantFactoryMethodDiscrete: function(result) {
      return new DiscreteInterpolant(this.times, this.values, this.getValueSize(), result);
    },
    InterpolantFactoryMethodLinear: function(result) {
      return new LinearInterpolant(this.times, this.values, this.getValueSize(), result);
    },
    InterpolantFactoryMethodSmooth: function(result) {
      return new CubicInterpolant(this.times, this.values, this.getValueSize(), result);
    },
    setInterpolation: function(interpolation) {
      var factoryMethod;
      switch (interpolation) {
        case InterpolateDiscrete:
          factoryMethod = this.InterpolantFactoryMethodDiscrete;
          break;
        case InterpolateLinear:
          factoryMethod = this.InterpolantFactoryMethodLinear;
          break;
        case InterpolateSmooth:
          factoryMethod = this.InterpolantFactoryMethodSmooth;
          break;
      }
      if (factoryMethod === undefined) {
        var message = "unsupported interpolation for " + this.ValueTypeName + " keyframe track named " + this.name;
        if (this.createInterpolant === undefined) {
          if (interpolation !== this.DefaultInterpolation) {
            this.setInterpolation(this.DefaultInterpolation);
          } else {
            throw new Error(message);
          }
        }
        console.warn('THREE.KeyframeTrackPrototype:', message);
        return;
      }
      this.createInterpolant = factoryMethod;
    },
    getInterpolation: function() {
      switch (this.createInterpolant) {
        case this.InterpolantFactoryMethodDiscrete:
          return InterpolateDiscrete;
        case this.InterpolantFactoryMethodLinear:
          return InterpolateLinear;
        case this.InterpolantFactoryMethodSmooth:
          return InterpolateSmooth;
      }
    },
    getValueSize: function() {
      return this.values.length / this.times.length;
    },
    shift: function(timeOffset) {
      if (timeOffset !== 0.0) {
        var times = this.times;
        for (var i = 0,
            n = times.length; i !== n; ++i) {
          times[i] += timeOffset;
        }
      }
      return this;
    },
    scale: function(timeScale) {
      if (timeScale !== 1.0) {
        var times = this.times;
        for (var i = 0,
            n = times.length; i !== n; ++i) {
          times[i] *= timeScale;
        }
      }
      return this;
    },
    trim: function(startTime, endTime) {
      var times = this.times,
          nKeys = times.length,
          from = 0,
          to = nKeys - 1;
      while (from !== nKeys && times[from] < startTime)
        ++from;
      while (to !== -1 && times[to] > endTime)
        --to;
      ++to;
      if (from !== 0 || to !== nKeys) {
        if (from >= to)
          to = Math.max(to, 1), from = to - 1;
        var stride = this.getValueSize();
        this.times = AnimationUtils.arraySlice(times, from, to);
        this.values = AnimationUtils.arraySlice(this.values, from * stride, to * stride);
      }
      return this;
    },
    validate: function() {
      var valid = true;
      var valueSize = this.getValueSize();
      if (valueSize - Math.floor(valueSize) !== 0) {
        console.error('THREE.KeyframeTrackPrototype: Invalid value size in track.', this);
        valid = false;
      }
      var times = this.times,
          values = this.values,
          nKeys = times.length;
      if (nKeys === 0) {
        console.error('THREE.KeyframeTrackPrototype: Track is empty.', this);
        valid = false;
      }
      var prevTime = null;
      for (var i = 0; i !== nKeys; i++) {
        var currTime = times[i];
        if (typeof currTime === 'number' && isNaN(currTime)) {
          console.error('THREE.KeyframeTrackPrototype: Time is not a valid number.', this, i, currTime);
          valid = false;
          break;
        }
        if (prevTime !== null && prevTime > currTime) {
          console.error('THREE.KeyframeTrackPrototype: Out of order keys.', this, i, currTime, prevTime);
          valid = false;
          break;
        }
        prevTime = currTime;
      }
      if (values !== undefined) {
        if (AnimationUtils.isTypedArray(values)) {
          for (var i = 0,
              n = values.length; i !== n; ++i) {
            var value = values[i];
            if (isNaN(value)) {
              console.error('THREE.KeyframeTrackPrototype: Value is not a valid number.', this, i, value);
              valid = false;
              break;
            }
          }
        }
      }
      return valid;
    },
    optimize: function() {
      var times = this.times,
          values = this.values,
          stride = this.getValueSize(),
          smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
          writeIndex = 1,
          lastIndex = times.length - 1;
      for (var i = 1; i < lastIndex; ++i) {
        var keep = false;
        var time = times[i];
        var timeNext = times[i + 1];
        if (time !== timeNext && (i !== 1 || time !== time[0])) {
          if (!smoothInterpolation) {
            var offset = i * stride,
                offsetP = offset - stride,
                offsetN = offset + stride;
            for (var j = 0; j !== stride; ++j) {
              var value = values[offset + j];
              if (value !== values[offsetP + j] || value !== values[offsetN + j]) {
                keep = true;
                break;
              }
            }
          } else
            keep = true;
        }
        if (keep) {
          if (i !== writeIndex) {
            times[writeIndex] = times[i];
            var readOffset = i * stride,
                writeOffset = writeIndex * stride;
            for (var j = 0; j !== stride; ++j)
              values[writeOffset + j] = values[readOffset + j];
          }
          ++writeIndex;
        }
      }
      if (lastIndex > 0) {
        times[writeIndex] = times[lastIndex];
        for (var readOffset = lastIndex * stride,
            writeOffset = writeIndex * stride,
            j = 0; j !== stride; ++j)
          values[writeOffset + j] = values[readOffset + j];
        ++writeIndex;
      }
      if (writeIndex !== times.length) {
        this.times = AnimationUtils.arraySlice(times, 0, writeIndex);
        this.values = AnimationUtils.arraySlice(values, 0, writeIndex * stride);
      }
      return this;
    }
  };
  function KeyframeTrackConstructor(name, times, values, interpolation) {
    if (name === undefined)
      throw new Error('track name is undefined');
    if (times === undefined || times.length === 0) {
      throw new Error('no keyframes in track named ' + name);
    }
    this.name = name;
    this.times = AnimationUtils.convertArray(times, this.TimeBufferType);
    this.values = AnimationUtils.convertArray(values, this.ValueBufferType);
    this.setInterpolation(interpolation || this.DefaultInterpolation);
    this.validate();
    this.optimize();
  }
  function VectorKeyframeTrack(name, times, values, interpolation) {
    KeyframeTrackConstructor.call(this, name, times, values, interpolation);
  }
  VectorKeyframeTrack.prototype = Object.assign(Object.create(KeyframeTrackPrototype), {
    constructor: VectorKeyframeTrack,
    ValueTypeName: 'vector'
  });
  function QuaternionLinearInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
  }
  QuaternionLinearInterpolant.prototype = Object.assign(Object.create(Interpolant.prototype), {
    constructor: QuaternionLinearInterpolant,
    interpolate_: function(i1, t0, t, t1) {
      var result = this.resultBuffer,
          values = this.sampleValues,
          stride = this.valueSize,
          offset = i1 * stride,
          alpha = (t - t0) / (t1 - t0);
      for (var end = offset + stride; offset !== end; offset += 4) {
        Quaternion.slerpFlat(result, 0, values, offset - stride, values, offset, alpha);
      }
      return result;
    }
  });
  function QuaternionKeyframeTrack(name, times, values, interpolation) {
    KeyframeTrackConstructor.call(this, name, times, values, interpolation);
  }
  QuaternionKeyframeTrack.prototype = Object.assign(Object.create(KeyframeTrackPrototype), {
    constructor: QuaternionKeyframeTrack,
    ValueTypeName: 'quaternion',
    DefaultInterpolation: InterpolateLinear,
    InterpolantFactoryMethodLinear: function(result) {
      return new QuaternionLinearInterpolant(this.times, this.values, this.getValueSize(), result);
    },
    InterpolantFactoryMethodSmooth: undefined
  });
  function NumberKeyframeTrack(name, times, values, interpolation) {
    KeyframeTrackConstructor.call(this, name, times, values, interpolation);
  }
  NumberKeyframeTrack.prototype = Object.assign(Object.create(KeyframeTrackPrototype), {
    constructor: NumberKeyframeTrack,
    ValueTypeName: 'number'
  });
  function StringKeyframeTrack(name, times, values, interpolation) {
    KeyframeTrackConstructor.call(this, name, times, values, interpolation);
  }
  StringKeyframeTrack.prototype = Object.assign(Object.create(KeyframeTrackPrototype), {
    constructor: StringKeyframeTrack,
    ValueTypeName: 'string',
    ValueBufferType: Array,
    DefaultInterpolation: InterpolateDiscrete,
    InterpolantFactoryMethodLinear: undefined,
    InterpolantFactoryMethodSmooth: undefined
  });
  function BooleanKeyframeTrack(name, times, values) {
    KeyframeTrackConstructor.call(this, name, times, values);
  }
  BooleanKeyframeTrack.prototype = Object.assign(Object.create(KeyframeTrackPrototype), {
    constructor: BooleanKeyframeTrack,
    ValueTypeName: 'bool',
    ValueBufferType: Array,
    DefaultInterpolation: InterpolateDiscrete,
    InterpolantFactoryMethodLinear: undefined,
    InterpolantFactoryMethodSmooth: undefined
  });
  function ColorKeyframeTrack(name, times, values, interpolation) {
    KeyframeTrackConstructor.call(this, name, times, values, interpolation);
  }
  ColorKeyframeTrack.prototype = Object.assign(Object.create(KeyframeTrackPrototype), {
    constructor: ColorKeyframeTrack,
    ValueTypeName: 'color'
  });
  function KeyframeTrack(name, times, values, interpolation) {
    KeyframeTrackConstructor.apply(this, name, times, values, interpolation);
  }
  KeyframeTrack.prototype = KeyframeTrackPrototype;
  KeyframeTrackPrototype.constructor = KeyframeTrack;
  Object.assign(KeyframeTrack, {
    parse: function(json) {
      if (json.type === undefined) {
        throw new Error('track type undefined, can not parse');
      }
      var trackType = KeyframeTrack._getTrackTypeForValueTypeName(json.type);
      if (json.times === undefined) {
        var times = [],
            values = [];
        AnimationUtils.flattenJSON(json.keys, times, values, 'value');
        json.times = times;
        json.values = values;
      }
      if (trackType.parse !== undefined) {
        return trackType.parse(json);
      } else {
        return new trackType(json.name, json.times, json.values, json.interpolation);
      }
    },
    toJSON: function(track) {
      var trackType = track.constructor;
      var json;
      if (trackType.toJSON !== undefined) {
        json = trackType.toJSON(track);
      } else {
        json = {
          'name': track.name,
          'times': AnimationUtils.convertArray(track.times, Array),
          'values': AnimationUtils.convertArray(track.values, Array)
        };
        var interpolation = track.getInterpolation();
        if (interpolation !== track.DefaultInterpolation) {
          json.interpolation = interpolation;
        }
      }
      json.type = track.ValueTypeName;
      return json;
    },
    _getTrackTypeForValueTypeName: function(typeName) {
      switch (typeName.toLowerCase()) {
        case 'scalar':
        case 'double':
        case 'float':
        case 'number':
        case 'integer':
          return NumberKeyframeTrack;
        case 'vector':
        case 'vector2':
        case 'vector3':
        case 'vector4':
          return VectorKeyframeTrack;
        case 'color':
          return ColorKeyframeTrack;
        case 'quaternion':
          return QuaternionKeyframeTrack;
        case 'bool':
        case 'boolean':
          return BooleanKeyframeTrack;
        case 'string':
          return StringKeyframeTrack;
      }
      throw new Error('Unsupported typeName: ' + typeName);
    }
  });
  function AnimationClip(name, duration, tracks) {
    this.name = name;
    this.tracks = tracks;
    this.duration = (duration !== undefined) ? duration : -1;
    this.uuid = _Math.generateUUID();
    if (this.duration < 0) {
      this.resetDuration();
    }
    this.optimize();
  }
  Object.assign(AnimationClip, {
    parse: function(json) {
      var tracks = [],
          jsonTracks = json.tracks,
          frameTime = 1.0 / (json.fps || 1.0);
      for (var i = 0,
          n = jsonTracks.length; i !== n; ++i) {
        tracks.push(KeyframeTrack.parse(jsonTracks[i]).scale(frameTime));
      }
      return new AnimationClip(json.name, json.duration, tracks);
    },
    toJSON: function(clip) {
      var tracks = [],
          clipTracks = clip.tracks;
      var json = {
        'name': clip.name,
        'duration': clip.duration,
        'tracks': tracks
      };
      for (var i = 0,
          n = clipTracks.length; i !== n; ++i) {
        tracks.push(KeyframeTrack.toJSON(clipTracks[i]));
      }
      return json;
    },
    CreateFromMorphTargetSequence: function(name, morphTargetSequence, fps, noLoop) {
      var numMorphTargets = morphTargetSequence.length;
      var tracks = [];
      for (var i = 0; i < numMorphTargets; i++) {
        var times = [];
        var values = [];
        times.push((i + numMorphTargets - 1) % numMorphTargets, i, (i + 1) % numMorphTargets);
        values.push(0, 1, 0);
        var order = AnimationUtils.getKeyframeOrder(times);
        times = AnimationUtils.sortedArray(times, 1, order);
        values = AnimationUtils.sortedArray(values, 1, order);
        if (!noLoop && times[0] === 0) {
          times.push(numMorphTargets);
          values.push(values[0]);
        }
        tracks.push(new NumberKeyframeTrack('.morphTargetInfluences[' + morphTargetSequence[i].name + ']', times, values).scale(1.0 / fps));
      }
      return new AnimationClip(name, -1, tracks);
    },
    findByName: function(objectOrClipArray, name) {
      var clipArray = objectOrClipArray;
      if (!Array.isArray(objectOrClipArray)) {
        var o = objectOrClipArray;
        clipArray = o.geometry && o.geometry.animations || o.animations;
      }
      for (var i = 0; i < clipArray.length; i++) {
        if (clipArray[i].name === name) {
          return clipArray[i];
        }
      }
      return null;
    },
    CreateClipsFromMorphTargetSequences: function(morphTargets, fps, noLoop) {
      var animationToMorphTargets = {};
      var pattern = /^([\w-]*?)([\d]+)$/;
      for (var i = 0,
          il = morphTargets.length; i < il; i++) {
        var morphTarget = morphTargets[i];
        var parts = morphTarget.name.match(pattern);
        if (parts && parts.length > 1) {
          var name = parts[1];
          var animationMorphTargets = animationToMorphTargets[name];
          if (!animationMorphTargets) {
            animationToMorphTargets[name] = animationMorphTargets = [];
          }
          animationMorphTargets.push(morphTarget);
        }
      }
      var clips = [];
      for (var name in animationToMorphTargets) {
        clips.push(AnimationClip.CreateFromMorphTargetSequence(name, animationToMorphTargets[name], fps, noLoop));
      }
      return clips;
    },
    parseAnimation: function(animation, bones) {
      if (!animation) {
        console.error('THREE.AnimationClip: No animation in JSONLoader data.');
        return null;
      }
      var addNonemptyTrack = function(trackType, trackName, animationKeys, propertyName, destTracks) {
        if (animationKeys.length !== 0) {
          var times = [];
          var values = [];
          AnimationUtils.flattenJSON(animationKeys, times, values, propertyName);
          if (times.length !== 0) {
            destTracks.push(new trackType(trackName, times, values));
          }
        }
      };
      var tracks = [];
      var clipName = animation.name || 'default';
      var duration = animation.length || -1;
      var fps = animation.fps || 30;
      var hierarchyTracks = animation.hierarchy || [];
      for (var h = 0; h < hierarchyTracks.length; h++) {
        var animationKeys = hierarchyTracks[h].keys;
        if (!animationKeys || animationKeys.length === 0)
          continue;
        if (animationKeys[0].morphTargets) {
          var morphTargetNames = {};
          for (var k = 0; k < animationKeys.length; k++) {
            if (animationKeys[k].morphTargets) {
              for (var m = 0; m < animationKeys[k].morphTargets.length; m++) {
                morphTargetNames[animationKeys[k].morphTargets[m]] = -1;
              }
            }
          }
          for (var morphTargetName in morphTargetNames) {
            var times = [];
            var values = [];
            for (var m = 0; m !== animationKeys[k].morphTargets.length; ++m) {
              var animationKey = animationKeys[k];
              times.push(animationKey.time);
              values.push((animationKey.morphTarget === morphTargetName) ? 1 : 0);
            }
            tracks.push(new NumberKeyframeTrack('.morphTargetInfluence[' + morphTargetName + ']', times, values));
          }
          duration = morphTargetNames.length * (fps || 1.0);
        } else {
          var boneName = '.bones[' + bones[h].name + ']';
          addNonemptyTrack(VectorKeyframeTrack, boneName + '.position', animationKeys, 'pos', tracks);
          addNonemptyTrack(QuaternionKeyframeTrack, boneName + '.quaternion', animationKeys, 'rot', tracks);
          addNonemptyTrack(VectorKeyframeTrack, boneName + '.scale', animationKeys, 'scl', tracks);
        }
      }
      if (tracks.length === 0) {
        return null;
      }
      var clip = new AnimationClip(clipName, duration, tracks);
      return clip;
    }
  });
  Object.assign(AnimationClip.prototype, {
    resetDuration: function() {
      var tracks = this.tracks,
          duration = 0;
      for (var i = 0,
          n = tracks.length; i !== n; ++i) {
        var track = this.tracks[i];
        duration = Math.max(duration, track.times[track.times.length - 1]);
      }
      this.duration = duration;
    },
    trim: function() {
      for (var i = 0; i < this.tracks.length; i++) {
        this.tracks[i].trim(0, this.duration);
      }
      return this;
    },
    optimize: function() {
      for (var i = 0; i < this.tracks.length; i++) {
        this.tracks[i].optimize();
      }
      return this;
    }
  });
  function MaterialLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
    this.textures = {};
  }
  Object.assign(MaterialLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var loader = new FileLoader(scope.manager);
      loader.load(url, function(text) {
        onLoad(scope.parse(JSON.parse(text)));
      }, onProgress, onError);
    },
    setTextures: function(value) {
      this.textures = value;
    },
    parse: function(json) {
      var textures = this.textures;
      function getTexture(name) {
        if (textures[name] === undefined) {
          console.warn('THREE.MaterialLoader: Undefined texture', name);
        }
        return textures[name];
      }
      var material = new Materials[json.type]();
      if (json.uuid !== undefined)
        material.uuid = json.uuid;
      if (json.name !== undefined)
        material.name = json.name;
      if (json.color !== undefined)
        material.color.setHex(json.color);
      if (json.roughness !== undefined)
        material.roughness = json.roughness;
      if (json.metalness !== undefined)
        material.metalness = json.metalness;
      if (json.emissive !== undefined)
        material.emissive.setHex(json.emissive);
      if (json.specular !== undefined)
        material.specular.setHex(json.specular);
      if (json.shininess !== undefined)
        material.shininess = json.shininess;
      if (json.clearCoat !== undefined)
        material.clearCoat = json.clearCoat;
      if (json.clearCoatRoughness !== undefined)
        material.clearCoatRoughness = json.clearCoatRoughness;
      if (json.uniforms !== undefined)
        material.uniforms = json.uniforms;
      if (json.vertexShader !== undefined)
        material.vertexShader = json.vertexShader;
      if (json.fragmentShader !== undefined)
        material.fragmentShader = json.fragmentShader;
      if (json.vertexColors !== undefined)
        material.vertexColors = json.vertexColors;
      if (json.fog !== undefined)
        material.fog = json.fog;
      if (json.flatShading !== undefined)
        material.flatShading = json.flatShading;
      if (json.blending !== undefined)
        material.blending = json.blending;
      if (json.side !== undefined)
        material.side = json.side;
      if (json.opacity !== undefined)
        material.opacity = json.opacity;
      if (json.transparent !== undefined)
        material.transparent = json.transparent;
      if (json.alphaTest !== undefined)
        material.alphaTest = json.alphaTest;
      if (json.depthTest !== undefined)
        material.depthTest = json.depthTest;
      if (json.depthWrite !== undefined)
        material.depthWrite = json.depthWrite;
      if (json.colorWrite !== undefined)
        material.colorWrite = json.colorWrite;
      if (json.wireframe !== undefined)
        material.wireframe = json.wireframe;
      if (json.wireframeLinewidth !== undefined)
        material.wireframeLinewidth = json.wireframeLinewidth;
      if (json.wireframeLinecap !== undefined)
        material.wireframeLinecap = json.wireframeLinecap;
      if (json.wireframeLinejoin !== undefined)
        material.wireframeLinejoin = json.wireframeLinejoin;
      if (json.rotation !== undefined)
        material.rotation = json.rotation;
      if (json.linewidth !== 1)
        material.linewidth = json.linewidth;
      if (json.dashSize !== undefined)
        material.dashSize = json.dashSize;
      if (json.gapSize !== undefined)
        material.gapSize = json.gapSize;
      if (json.scale !== undefined)
        material.scale = json.scale;
      if (json.skinning !== undefined)
        material.skinning = json.skinning;
      if (json.morphTargets !== undefined)
        material.morphTargets = json.morphTargets;
      if (json.dithering !== undefined)
        material.dithering = json.dithering;
      if (json.visible !== undefined)
        material.visible = json.visible;
      if (json.userData !== undefined)
        material.userData = json.userData;
      if (json.shading !== undefined)
        material.flatShading = json.shading === 1;
      if (json.size !== undefined)
        material.size = json.size;
      if (json.sizeAttenuation !== undefined)
        material.sizeAttenuation = json.sizeAttenuation;
      if (json.map !== undefined)
        material.map = getTexture(json.map);
      if (json.alphaMap !== undefined) {
        material.alphaMap = getTexture(json.alphaMap);
        material.transparent = true;
      }
      if (json.bumpMap !== undefined)
        material.bumpMap = getTexture(json.bumpMap);
      if (json.bumpScale !== undefined)
        material.bumpScale = json.bumpScale;
      if (json.normalMap !== undefined)
        material.normalMap = getTexture(json.normalMap);
      if (json.normalScale !== undefined) {
        var normalScale = json.normalScale;
        if (Array.isArray(normalScale) === false) {
          normalScale = [normalScale, normalScale];
        }
        material.normalScale = new Vector2().fromArray(normalScale);
      }
      if (json.displacementMap !== undefined)
        material.displacementMap = getTexture(json.displacementMap);
      if (json.displacementScale !== undefined)
        material.displacementScale = json.displacementScale;
      if (json.displacementBias !== undefined)
        material.displacementBias = json.displacementBias;
      if (json.roughnessMap !== undefined)
        material.roughnessMap = getTexture(json.roughnessMap);
      if (json.metalnessMap !== undefined)
        material.metalnessMap = getTexture(json.metalnessMap);
      if (json.emissiveMap !== undefined)
        material.emissiveMap = getTexture(json.emissiveMap);
      if (json.emissiveIntensity !== undefined)
        material.emissiveIntensity = json.emissiveIntensity;
      if (json.specularMap !== undefined)
        material.specularMap = getTexture(json.specularMap);
      if (json.envMap !== undefined)
        material.envMap = getTexture(json.envMap);
      if (json.reflectivity !== undefined)
        material.reflectivity = json.reflectivity;
      if (json.lightMap !== undefined)
        material.lightMap = getTexture(json.lightMap);
      if (json.lightMapIntensity !== undefined)
        material.lightMapIntensity = json.lightMapIntensity;
      if (json.aoMap !== undefined)
        material.aoMap = getTexture(json.aoMap);
      if (json.aoMapIntensity !== undefined)
        material.aoMapIntensity = json.aoMapIntensity;
      if (json.gradientMap !== undefined)
        material.gradientMap = getTexture(json.gradientMap);
      return material;
    }
  });
  function BufferGeometryLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
  }
  Object.assign(BufferGeometryLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var loader = new FileLoader(scope.manager);
      loader.load(url, function(text) {
        onLoad(scope.parse(JSON.parse(text)));
      }, onProgress, onError);
    },
    parse: function(json) {
      var geometry = new BufferGeometry();
      var index = json.data.index;
      if (index !== undefined) {
        var typedArray = new TYPED_ARRAYS[index.type](index.array);
        geometry.setIndex(new BufferAttribute(typedArray, 1));
      }
      var attributes = json.data.attributes;
      for (var key in attributes) {
        var attribute = attributes[key];
        var typedArray = new TYPED_ARRAYS[attribute.type](attribute.array);
        geometry.addAttribute(key, new BufferAttribute(typedArray, attribute.itemSize, attribute.normalized));
      }
      var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
      if (groups !== undefined) {
        for (var i = 0,
            n = groups.length; i !== n; ++i) {
          var group = groups[i];
          geometry.addGroup(group.start, group.count, group.materialIndex);
        }
      }
      var boundingSphere = json.data.boundingSphere;
      if (boundingSphere !== undefined) {
        var center = new Vector3();
        if (boundingSphere.center !== undefined) {
          center.fromArray(boundingSphere.center);
        }
        geometry.boundingSphere = new Sphere(center, boundingSphere.radius);
      }
      return geometry;
    }
  });
  var TYPED_ARRAYS = {
    Int8Array: Int8Array,
    Uint8Array: Uint8Array,
    Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
    Int16Array: Int16Array,
    Uint16Array: Uint16Array,
    Int32Array: Int32Array,
    Uint32Array: Uint32Array,
    Float32Array: Float32Array,
    Float64Array: Float64Array
  };
  function Loader() {
    this.onLoadStart = function() {};
    this.onLoadProgress = function() {};
    this.onLoadComplete = function() {};
  }
  Loader.Handlers = {
    handlers: [],
    add: function(regex, loader) {
      this.handlers.push(regex, loader);
    },
    get: function(file) {
      var handlers = this.handlers;
      for (var i = 0,
          l = handlers.length; i < l; i += 2) {
        var regex = handlers[i];
        var loader = handlers[i + 1];
        if (regex.test(file)) {
          return loader;
        }
      }
      return null;
    }
  };
  Object.assign(Loader.prototype, {
    crossOrigin: undefined,
    extractUrlBase: function(url) {
      var parts = url.split('/');
      if (parts.length === 1)
        return './';
      parts.pop();
      return parts.join('/') + '/';
    },
    initMaterials: function(materials, texturePath, crossOrigin) {
      var array = [];
      for (var i = 0; i < materials.length; ++i) {
        array[i] = this.createMaterial(materials[i], texturePath, crossOrigin);
      }
      return array;
    },
    createMaterial: (function() {
      var BlendingMode = {
        NoBlending: NoBlending,
        NormalBlending: NormalBlending,
        AdditiveBlending: AdditiveBlending,
        SubtractiveBlending: SubtractiveBlending,
        MultiplyBlending: MultiplyBlending,
        CustomBlending: CustomBlending
      };
      var color = new Color();
      var textureLoader = new TextureLoader();
      var materialLoader = new MaterialLoader();
      return function createMaterial(m, texturePath, crossOrigin) {
        var textures = {};
        function loadTexture(path, repeat, offset, wrap, anisotropy) {
          var fullPath = texturePath + path;
          var loader = Loader.Handlers.get(fullPath);
          var texture;
          if (loader !== null) {
            texture = loader.load(fullPath);
          } else {
            textureLoader.setCrossOrigin(crossOrigin);
            texture = textureLoader.load(fullPath);
          }
          if (repeat !== undefined) {
            texture.repeat.fromArray(repeat);
            if (repeat[0] !== 1)
              texture.wrapS = RepeatWrapping;
            if (repeat[1] !== 1)
              texture.wrapT = RepeatWrapping;
          }
          if (offset !== undefined) {
            texture.offset.fromArray(offset);
          }
          if (wrap !== undefined) {
            if (wrap[0] === 'repeat')
              texture.wrapS = RepeatWrapping;
            if (wrap[0] === 'mirror')
              texture.wrapS = MirroredRepeatWrapping;
            if (wrap[1] === 'repeat')
              texture.wrapT = RepeatWrapping;
            if (wrap[1] === 'mirror')
              texture.wrapT = MirroredRepeatWrapping;
          }
          if (anisotropy !== undefined) {
            texture.anisotropy = anisotropy;
          }
          var uuid = _Math.generateUUID();
          textures[uuid] = texture;
          return uuid;
        }
        var json = {
          uuid: _Math.generateUUID(),
          type: 'MeshLambertMaterial'
        };
        for (var name in m) {
          var value = m[name];
          switch (name) {
            case 'DbgColor':
            case 'DbgIndex':
            case 'opticalDensity':
            case 'illumination':
              break;
            case 'DbgName':
              json.name = value;
              break;
            case 'blending':
              json.blending = BlendingMode[value];
              break;
            case 'colorAmbient':
            case 'mapAmbient':
              console.warn('THREE.Loader.createMaterial:', name, 'is no longer supported.');
              break;
            case 'colorDiffuse':
              json.color = color.fromArray(value).getHex();
              break;
            case 'colorSpecular':
              json.specular = color.fromArray(value).getHex();
              break;
            case 'colorEmissive':
              json.emissive = color.fromArray(value).getHex();
              break;
            case 'specularCoef':
              json.shininess = value;
              break;
            case 'shading':
              if (value.toLowerCase() === 'basic')
                json.type = 'MeshBasicMaterial';
              if (value.toLowerCase() === 'phong')
                json.type = 'MeshPhongMaterial';
              if (value.toLowerCase() === 'standard')
                json.type = 'MeshStandardMaterial';
              break;
            case 'mapDiffuse':
              json.map = loadTexture(value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy);
              break;
            case 'mapDiffuseRepeat':
            case 'mapDiffuseOffset':
            case 'mapDiffuseWrap':
            case 'mapDiffuseAnisotropy':
              break;
            case 'mapEmissive':
              json.emissiveMap = loadTexture(value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy);
              break;
            case 'mapEmissiveRepeat':
            case 'mapEmissiveOffset':
            case 'mapEmissiveWrap':
            case 'mapEmissiveAnisotropy':
              break;
            case 'mapLight':
              json.lightMap = loadTexture(value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy);
              break;
            case 'mapLightRepeat':
            case 'mapLightOffset':
            case 'mapLightWrap':
            case 'mapLightAnisotropy':
              break;
            case 'mapAO':
              json.aoMap = loadTexture(value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy);
              break;
            case 'mapAORepeat':
            case 'mapAOOffset':
            case 'mapAOWrap':
            case 'mapAOAnisotropy':
              break;
            case 'mapBump':
              json.bumpMap = loadTexture(value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy);
              break;
            case 'mapBumpScale':
              json.bumpScale = value;
              break;
            case 'mapBumpRepeat':
            case 'mapBumpOffset':
            case 'mapBumpWrap':
            case 'mapBumpAnisotropy':
              break;
            case 'mapNormal':
              json.normalMap = loadTexture(value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy);
              break;
            case 'mapNormalFactor':
              json.normalScale = [value, value];
              break;
            case 'mapNormalRepeat':
            case 'mapNormalOffset':
            case 'mapNormalWrap':
            case 'mapNormalAnisotropy':
              break;
            case 'mapSpecular':
              json.specularMap = loadTexture(value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy);
              break;
            case 'mapSpecularRepeat':
            case 'mapSpecularOffset':
            case 'mapSpecularWrap':
            case 'mapSpecularAnisotropy':
              break;
            case 'mapMetalness':
              json.metalnessMap = loadTexture(value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy);
              break;
            case 'mapMetalnessRepeat':
            case 'mapMetalnessOffset':
            case 'mapMetalnessWrap':
            case 'mapMetalnessAnisotropy':
              break;
            case 'mapRoughness':
              json.roughnessMap = loadTexture(value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy);
              break;
            case 'mapRoughnessRepeat':
            case 'mapRoughnessOffset':
            case 'mapRoughnessWrap':
            case 'mapRoughnessAnisotropy':
              break;
            case 'mapAlpha':
              json.alphaMap = loadTexture(value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy);
              break;
            case 'mapAlphaRepeat':
            case 'mapAlphaOffset':
            case 'mapAlphaWrap':
            case 'mapAlphaAnisotropy':
              break;
            case 'flipSided':
              json.side = BackSide;
              break;
            case 'doubleSided':
              json.side = DoubleSide;
              break;
            case 'transparency':
              console.warn('THREE.Loader.createMaterial: transparency has been renamed to opacity');
              json.opacity = value;
              break;
            case 'depthTest':
            case 'depthWrite':
            case 'colorWrite':
            case 'opacity':
            case 'reflectivity':
            case 'transparent':
            case 'visible':
            case 'wireframe':
              json[name] = value;
              break;
            case 'vertexColors':
              if (value === true)
                json.vertexColors = VertexColors;
              if (value === 'face')
                json.vertexColors = FaceColors;
              break;
            default:
              console.error('THREE.Loader.createMaterial: Unsupported', name, value);
              break;
          }
        }
        if (json.type === 'MeshBasicMaterial')
          delete json.emissive;
        if (json.type !== 'MeshPhongMaterial')
          delete json.specular;
        if (json.opacity < 1)
          json.transparent = true;
        materialLoader.setTextures(textures);
        return materialLoader.parse(json);
      };
    })()
  });
  function JSONLoader(manager) {
    if (typeof manager === 'boolean') {
      console.warn('THREE.JSONLoader: showStatus parameter has been removed from constructor.');
      manager = undefined;
    }
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
    this.withCredentials = false;
  }
  Object.assign(JSONLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var texturePath = this.texturePath && (typeof this.texturePath === "string") ? this.texturePath : Loader.prototype.extractUrlBase(url);
      var loader = new FileLoader(this.manager);
      loader.setWithCredentials(this.withCredentials);
      loader.load(url, function(text) {
        var json = JSON.parse(text);
        var metadata = json.metadata;
        if (metadata !== undefined) {
          var type = metadata.type;
          if (type !== undefined) {
            if (type.toLowerCase() === 'object') {
              console.error('THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.');
              return;
            }
            if (type.toLowerCase() === 'scene') {
              console.error('THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.');
              return;
            }
          }
        }
        var object = scope.parse(json, texturePath);
        onLoad(object.geometry, object.materials);
      }, onProgress, onError);
    },
    setTexturePath: function(value) {
      this.texturePath = value;
    },
    parse: (function() {
      function parseModel(json, geometry) {
        function isBitSet(value, position) {
          return value & (1 << position);
        }
        var i,
            j,
            fi,
            offset,
            zLength,
            colorIndex,
            normalIndex,
            uvIndex,
            materialIndex,
            type,
            isQuad,
            hasMaterial,
            hasFaceVertexUv,
            hasFaceNormal,
            hasFaceVertexNormal,
            hasFaceColor,
            hasFaceVertexColor,
            vertex,
            face,
            faceA,
            faceB,
            hex,
            normal,
            uvLayer,
            uv,
            u,
            v,
            faces = json.faces,
            vertices = json.vertices,
            normals = json.normals,
            colors = json.colors,
            scale = json.scale,
            nUvLayers = 0;
        if (json.uvs !== undefined) {
          for (i = 0; i < json.uvs.length; i++) {
            if (json.uvs[i].length)
              nUvLayers++;
          }
          for (i = 0; i < nUvLayers; i++) {
            geometry.faceVertexUvs[i] = [];
          }
        }
        offset = 0;
        zLength = vertices.length;
        while (offset < zLength) {
          vertex = new Vector3();
          vertex.x = vertices[offset++] * scale;
          vertex.y = vertices[offset++] * scale;
          vertex.z = vertices[offset++] * scale;
          geometry.vertices.push(vertex);
        }
        offset = 0;
        zLength = faces.length;
        while (offset < zLength) {
          type = faces[offset++];
          isQuad = isBitSet(type, 0);
          hasMaterial = isBitSet(type, 1);
          hasFaceVertexUv = isBitSet(type, 3);
          hasFaceNormal = isBitSet(type, 4);
          hasFaceVertexNormal = isBitSet(type, 5);
          hasFaceColor = isBitSet(type, 6);
          hasFaceVertexColor = isBitSet(type, 7);
          if (isQuad) {
            faceA = new Face3();
            faceA.a = faces[offset];
            faceA.b = faces[offset + 1];
            faceA.c = faces[offset + 3];
            faceB = new Face3();
            faceB.a = faces[offset + 1];
            faceB.b = faces[offset + 2];
            faceB.c = faces[offset + 3];
            offset += 4;
            if (hasMaterial) {
              materialIndex = faces[offset++];
              faceA.materialIndex = materialIndex;
              faceB.materialIndex = materialIndex;
            }
            fi = geometry.faces.length;
            if (hasFaceVertexUv) {
              for (i = 0; i < nUvLayers; i++) {
                uvLayer = json.uvs[i];
                geometry.faceVertexUvs[i][fi] = [];
                geometry.faceVertexUvs[i][fi + 1] = [];
                for (j = 0; j < 4; j++) {
                  uvIndex = faces[offset++];
                  u = uvLayer[uvIndex * 2];
                  v = uvLayer[uvIndex * 2 + 1];
                  uv = new Vector2(u, v);
                  if (j !== 2)
                    geometry.faceVertexUvs[i][fi].push(uv);
                  if (j !== 0)
                    geometry.faceVertexUvs[i][fi + 1].push(uv);
                }
              }
            }
            if (hasFaceNormal) {
              normalIndex = faces[offset++] * 3;
              faceA.normal.set(normals[normalIndex++], normals[normalIndex++], normals[normalIndex]);
              faceB.normal.copy(faceA.normal);
            }
            if (hasFaceVertexNormal) {
              for (i = 0; i < 4; i++) {
                normalIndex = faces[offset++] * 3;
                normal = new Vector3(normals[normalIndex++], normals[normalIndex++], normals[normalIndex]);
                if (i !== 2)
                  faceA.vertexNormals.push(normal);
                if (i !== 0)
                  faceB.vertexNormals.push(normal);
              }
            }
            if (hasFaceColor) {
              colorIndex = faces[offset++];
              hex = colors[colorIndex];
              faceA.color.setHex(hex);
              faceB.color.setHex(hex);
            }
            if (hasFaceVertexColor) {
              for (i = 0; i < 4; i++) {
                colorIndex = faces[offset++];
                hex = colors[colorIndex];
                if (i !== 2)
                  faceA.vertexColors.push(new Color(hex));
                if (i !== 0)
                  faceB.vertexColors.push(new Color(hex));
              }
            }
            geometry.faces.push(faceA);
            geometry.faces.push(faceB);
          } else {
            face = new Face3();
            face.a = faces[offset++];
            face.b = faces[offset++];
            face.c = faces[offset++];
            if (hasMaterial) {
              materialIndex = faces[offset++];
              face.materialIndex = materialIndex;
            }
            fi = geometry.faces.length;
            if (hasFaceVertexUv) {
              for (i = 0; i < nUvLayers; i++) {
                uvLayer = json.uvs[i];
                geometry.faceVertexUvs[i][fi] = [];
                for (j = 0; j < 3; j++) {
                  uvIndex = faces[offset++];
                  u = uvLayer[uvIndex * 2];
                  v = uvLayer[uvIndex * 2 + 1];
                  uv = new Vector2(u, v);
                  geometry.faceVertexUvs[i][fi].push(uv);
                }
              }
            }
            if (hasFaceNormal) {
              normalIndex = faces[offset++] * 3;
              face.normal.set(normals[normalIndex++], normals[normalIndex++], normals[normalIndex]);
            }
            if (hasFaceVertexNormal) {
              for (i = 0; i < 3; i++) {
                normalIndex = faces[offset++] * 3;
                normal = new Vector3(normals[normalIndex++], normals[normalIndex++], normals[normalIndex]);
                face.vertexNormals.push(normal);
              }
            }
            if (hasFaceColor) {
              colorIndex = faces[offset++];
              face.color.setHex(colors[colorIndex]);
            }
            if (hasFaceVertexColor) {
              for (i = 0; i < 3; i++) {
                colorIndex = faces[offset++];
                face.vertexColors.push(new Color(colors[colorIndex]));
              }
            }
            geometry.faces.push(face);
          }
        }
      }
      function parseSkin(json, geometry) {
        var influencesPerVertex = (json.influencesPerVertex !== undefined) ? json.influencesPerVertex : 2;
        if (json.skinWeights) {
          for (var i = 0,
              l = json.skinWeights.length; i < l; i += influencesPerVertex) {
            var x = json.skinWeights[i];
            var y = (influencesPerVertex > 1) ? json.skinWeights[i + 1] : 0;
            var z = (influencesPerVertex > 2) ? json.skinWeights[i + 2] : 0;
            var w = (influencesPerVertex > 3) ? json.skinWeights[i + 3] : 0;
            geometry.skinWeights.push(new Vector4(x, y, z, w));
          }
        }
        if (json.skinIndices) {
          for (var i = 0,
              l = json.skinIndices.length; i < l; i += influencesPerVertex) {
            var a = json.skinIndices[i];
            var b = (influencesPerVertex > 1) ? json.skinIndices[i + 1] : 0;
            var c = (influencesPerVertex > 2) ? json.skinIndices[i + 2] : 0;
            var d = (influencesPerVertex > 3) ? json.skinIndices[i + 3] : 0;
            geometry.skinIndices.push(new Vector4(a, b, c, d));
          }
        }
        geometry.bones = json.bones;
        if (geometry.bones && geometry.bones.length > 0 && (geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length)) {
          console.warn('When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.');
        }
      }
      function parseMorphing(json, geometry) {
        var scale = json.scale;
        if (json.morphTargets !== undefined) {
          for (var i = 0,
              l = json.morphTargets.length; i < l; i++) {
            geometry.morphTargets[i] = {};
            geometry.morphTargets[i].name = json.morphTargets[i].name;
            geometry.morphTargets[i].vertices = [];
            var dstVertices = geometry.morphTargets[i].vertices;
            var srcVertices = json.morphTargets[i].vertices;
            for (var v = 0,
                vl = srcVertices.length; v < vl; v += 3) {
              var vertex = new Vector3();
              vertex.x = srcVertices[v] * scale;
              vertex.y = srcVertices[v + 1] * scale;
              vertex.z = srcVertices[v + 2] * scale;
              dstVertices.push(vertex);
            }
          }
        }
        if (json.morphColors !== undefined && json.morphColors.length > 0) {
          console.warn('THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.');
          var faces = geometry.faces;
          var morphColors = json.morphColors[0].colors;
          for (var i = 0,
              l = faces.length; i < l; i++) {
            faces[i].color.fromArray(morphColors, i * 3);
          }
        }
      }
      function parseAnimations(json, geometry) {
        var outputAnimations = [];
        var animations = [];
        if (json.animation !== undefined) {
          animations.push(json.animation);
        }
        if (json.animations !== undefined) {
          if (json.animations.length) {
            animations = animations.concat(json.animations);
          } else {
            animations.push(json.animations);
          }
        }
        for (var i = 0; i < animations.length; i++) {
          var clip = AnimationClip.parseAnimation(animations[i], geometry.bones);
          if (clip)
            outputAnimations.push(clip);
        }
        if (geometry.morphTargets) {
          var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences(geometry.morphTargets, 10);
          outputAnimations = outputAnimations.concat(morphAnimationClips);
        }
        if (outputAnimations.length > 0)
          geometry.animations = outputAnimations;
      }
      return function(json, texturePath) {
        if (json.data !== undefined) {
          json = json.data;
        }
        if (json.scale !== undefined) {
          json.scale = 1.0 / json.scale;
        } else {
          json.scale = 1.0;
        }
        var geometry = new Geometry();
        parseModel(json, geometry);
        parseSkin(json, geometry);
        parseMorphing(json, geometry);
        parseAnimations(json, geometry);
        geometry.computeFaceNormals();
        geometry.computeBoundingSphere();
        if (json.materials === undefined || json.materials.length === 0) {
          return {geometry: geometry};
        } else {
          var materials = Loader.prototype.initMaterials(json.materials, texturePath, this.crossOrigin);
          return {
            geometry: geometry,
            materials: materials
          };
        }
      };
    })()
  });
  function ObjectLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
    this.texturePath = '';
  }
  Object.assign(ObjectLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      if (this.texturePath === '') {
        this.texturePath = url.substring(0, url.lastIndexOf('/') + 1);
      }
      var scope = this;
      var loader = new FileLoader(scope.manager);
      loader.load(url, function(text) {
        var json = null;
        try {
          json = JSON.parse(text);
        } catch (error) {
          if (onError !== undefined)
            onError(error);
          console.error('THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message);
          return;
        }
        var metadata = json.metadata;
        if (metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry') {
          console.error('THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.');
          return;
        }
        scope.parse(json, onLoad);
      }, onProgress, onError);
    },
    setTexturePath: function(value) {
      this.texturePath = value;
    },
    setCrossOrigin: function(value) {
      this.crossOrigin = value;
    },
    parse: function(json, onLoad) {
      var geometries = this.parseGeometries(json.geometries);
      var images = this.parseImages(json.images, function() {
        if (onLoad !== undefined)
          onLoad(object);
      });
      var textures = this.parseTextures(json.textures, images);
      var materials = this.parseMaterials(json.materials, textures);
      var object = this.parseObject(json.object, geometries, materials);
      if (json.animations) {
        object.animations = this.parseAnimations(json.animations);
      }
      if (json.images === undefined || json.images.length === 0) {
        if (onLoad !== undefined)
          onLoad(object);
      }
      return object;
    },
    parseGeometries: function(json) {
      var geometries = {};
      if (json !== undefined) {
        var geometryLoader = new JSONLoader();
        var bufferGeometryLoader = new BufferGeometryLoader();
        for (var i = 0,
            l = json.length; i < l; i++) {
          var geometry;
          var data = json[i];
          switch (data.type) {
            case 'PlaneGeometry':
            case 'PlaneBufferGeometry':
              geometry = new Geometries[data.type](data.width, data.height, data.widthSegments, data.heightSegments);
              break;
            case 'BoxGeometry':
            case 'BoxBufferGeometry':
            case 'CubeGeometry':
              geometry = new Geometries[data.type](data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments);
              break;
            case 'CircleGeometry':
            case 'CircleBufferGeometry':
              geometry = new Geometries[data.type](data.radius, data.segments, data.thetaStart, data.thetaLength);
              break;
            case 'CylinderGeometry':
            case 'CylinderBufferGeometry':
              geometry = new Geometries[data.type](data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength);
              break;
            case 'ConeGeometry':
            case 'ConeBufferGeometry':
              geometry = new Geometries[data.type](data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength);
              break;
            case 'SphereGeometry':
            case 'SphereBufferGeometry':
              geometry = new Geometries[data.type](data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength);
              break;
            case 'DodecahedronGeometry':
            case 'DodecahedronBufferGeometry':
            case 'IcosahedronGeometry':
            case 'IcosahedronBufferGeometry':
            case 'OctahedronGeometry':
            case 'OctahedronBufferGeometry':
            case 'TetrahedronGeometry':
            case 'TetrahedronBufferGeometry':
              geometry = new Geometries[data.type](data.radius, data.detail);
              break;
            case 'RingGeometry':
            case 'RingBufferGeometry':
              geometry = new Geometries[data.type](data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength);
              break;
            case 'TorusGeometry':
            case 'TorusBufferGeometry':
              geometry = new Geometries[data.type](data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc);
              break;
            case 'TorusKnotGeometry':
            case 'TorusKnotBufferGeometry':
              geometry = new Geometries[data.type](data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q);
              break;
            case 'LatheGeometry':
            case 'LatheBufferGeometry':
              geometry = new Geometries[data.type](data.points, data.segments, data.phiStart, data.phiLength);
              break;
            case 'PolyhedronGeometry':
            case 'PolyhedronBufferGeometry':
              geometry = new Geometries[data.type](data.vertices, data.indices, data.radius, data.details);
              break;
            case 'BufferGeometry':
              geometry = bufferGeometryLoader.parse(data);
              break;
            case 'Geometry':
              geometry = geometryLoader.parse(data, this.texturePath).geometry;
              break;
            default:
              console.warn('THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"');
              continue;
          }
          geometry.uuid = data.uuid;
          if (data.name !== undefined)
            geometry.name = data.name;
          geometries[data.uuid] = geometry;
        }
      }
      return geometries;
    },
    parseMaterials: function(json, textures) {
      var materials = {};
      if (json !== undefined) {
        var loader = new MaterialLoader();
        loader.setTextures(textures);
        for (var i = 0,
            l = json.length; i < l; i++) {
          var data = json[i];
          if (data.type === 'MultiMaterial') {
            var array = [];
            for (var j = 0; j < data.materials.length; j++) {
              array.push(loader.parse(data.materials[j]));
            }
            materials[data.uuid] = array;
          } else {
            materials[data.uuid] = loader.parse(data);
          }
        }
      }
      return materials;
    },
    parseAnimations: function(json) {
      var animations = [];
      for (var i = 0; i < json.length; i++) {
        var clip = AnimationClip.parse(json[i]);
        animations.push(clip);
      }
      return animations;
    },
    parseImages: function(json, onLoad) {
      var scope = this;
      var images = {};
      function loadImage(url) {
        scope.manager.itemStart(url);
        return loader.load(url, function() {
          scope.manager.itemEnd(url);
        }, undefined, function() {
          scope.manager.itemEnd(url);
          scope.manager.itemError(url);
        });
      }
      if (json !== undefined && json.length > 0) {
        var manager = new LoadingManager(onLoad);
        var loader = new ImageLoader(manager);
        loader.setCrossOrigin(this.crossOrigin);
        for (var i = 0,
            l = json.length; i < l; i++) {
          var image = json[i];
          var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test(image.url) ? image.url : scope.texturePath + image.url;
          images[image.uuid] = loadImage(path);
        }
      }
      return images;
    },
    parseTextures: function(json, images) {
      function parseConstant(value, type) {
        if (typeof value === 'number')
          return value;
        console.warn('THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value);
        return type[value];
      }
      var textures = {};
      if (json !== undefined) {
        for (var i = 0,
            l = json.length; i < l; i++) {
          var data = json[i];
          if (data.image === undefined) {
            console.warn('THREE.ObjectLoader: No "image" specified for', data.uuid);
          }
          if (images[data.image] === undefined) {
            console.warn('THREE.ObjectLoader: Undefined image', data.image);
          }
          var texture = new Texture(images[data.image]);
          texture.needsUpdate = true;
          texture.uuid = data.uuid;
          if (data.name !== undefined)
            texture.name = data.name;
          if (data.mapping !== undefined)
            texture.mapping = parseConstant(data.mapping, TEXTURE_MAPPING);
          if (data.offset !== undefined)
            texture.offset.fromArray(data.offset);
          if (data.repeat !== undefined)
            texture.repeat.fromArray(data.repeat);
          if (data.center !== undefined)
            texture.center.fromArray(data.center);
          if (data.rotation !== undefined)
            texture.rotation = data.rotation;
          if (data.wrap !== undefined) {
            texture.wrapS = parseConstant(data.wrap[0], TEXTURE_WRAPPING);
            texture.wrapT = parseConstant(data.wrap[1], TEXTURE_WRAPPING);
          }
          if (data.minFilter !== undefined)
            texture.minFilter = parseConstant(data.minFilter, TEXTURE_FILTER);
          if (data.magFilter !== undefined)
            texture.magFilter = parseConstant(data.magFilter, TEXTURE_FILTER);
          if (data.anisotropy !== undefined)
            texture.anisotropy = data.anisotropy;
          if (data.flipY !== undefined)
            texture.flipY = data.flipY;
          textures[data.uuid] = texture;
        }
      }
      return textures;
    },
    parseObject: function() {
      var matrix = new Matrix4();
      return function parseObject(data, geometries, materials) {
        var object;
        function getGeometry(name) {
          if (geometries[name] === undefined) {
            console.warn('THREE.ObjectLoader: Undefined geometry', name);
          }
          return geometries[name];
        }
        function getMaterial(name) {
          if (name === undefined)
            return undefined;
          if (Array.isArray(name)) {
            var array = [];
            for (var i = 0,
                l = name.length; i < l; i++) {
              var uuid = name[i];
              if (materials[uuid] === undefined) {
                console.warn('THREE.ObjectLoader: Undefined material', uuid);
              }
              array.push(materials[uuid]);
            }
            return array;
          }
          if (materials[name] === undefined) {
            console.warn('THREE.ObjectLoader: Undefined material', name);
          }
          return materials[name];
        }
        switch (data.type) {
          case 'Scene':
            object = new Scene();
            if (data.background !== undefined) {
              if (Number.isInteger(data.background)) {
                object.background = new Color(data.background);
              }
            }
            if (data.fog !== undefined) {
              if (data.fog.type === 'Fog') {
                object.fog = new Fog(data.fog.color, data.fog.near, data.fog.far);
              } else if (data.fog.type === 'FogExp2') {
                object.fog = new FogExp2(data.fog.color, data.fog.density);
              }
            }
            break;
          case 'PerspectiveCamera':
            object = new PerspectiveCamera(data.fov, data.aspect, data.near, data.far);
            if (data.focus !== undefined)
              object.focus = data.focus;
            if (data.zoom !== undefined)
              object.zoom = data.zoom;
            if (data.filmGauge !== undefined)
              object.filmGauge = data.filmGauge;
            if (data.filmOffset !== undefined)
              object.filmOffset = data.filmOffset;
            if (data.view !== undefined)
              object.view = Object.assign({}, data.view);
            break;
          case 'OrthographicCamera':
            object = new OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far);
            break;
          case 'AmbientLight':
            object = new AmbientLight(data.color, data.intensity);
            break;
          case 'DirectionalLight':
            object = new DirectionalLight(data.color, data.intensity);
            break;
          case 'PointLight':
            object = new PointLight(data.color, data.intensity, data.distance, data.decay);
            break;
          case 'RectAreaLight':
            object = new RectAreaLight(data.color, data.intensity, data.width, data.height);
            break;
          case 'SpotLight':
            object = new SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay);
            break;
          case 'HemisphereLight':
            object = new HemisphereLight(data.color, data.groundColor, data.intensity);
            break;
          case 'SkinnedMesh':
            console.warn('THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.');
          case 'Mesh':
            var geometry = getGeometry(data.geometry);
            var material = getMaterial(data.material);
            if (geometry.bones && geometry.bones.length > 0) {
              object = new SkinnedMesh(geometry, material);
            } else {
              object = new Mesh(geometry, material);
            }
            break;
          case 'LOD':
            object = new LOD();
            break;
          case 'Line':
            object = new Line(getGeometry(data.geometry), getMaterial(data.material), data.mode);
            break;
          case 'LineLoop':
            object = new LineLoop(getGeometry(data.geometry), getMaterial(data.material));
            break;
          case 'LineSegments':
            object = new LineSegments(getGeometry(data.geometry), getMaterial(data.material));
            break;
          case 'PointCloud':
          case 'Points':
            object = new Points(getGeometry(data.geometry), getMaterial(data.material));
            break;
          case 'Sprite':
            object = new Sprite(getMaterial(data.material));
            break;
          case 'Group':
            object = new Group();
            break;
          default:
            object = new Object3D();
        }
        object.uuid = data.uuid;
        if (data.name !== undefined)
          object.name = data.name;
        if (data.matrix !== undefined) {
          matrix.fromArray(data.matrix);
          matrix.decompose(object.position, object.quaternion, object.scale);
        } else {
          if (data.position !== undefined)
            object.position.fromArray(data.position);
          if (data.rotation !== undefined)
            object.rotation.fromArray(data.rotation);
          if (data.quaternion !== undefined)
            object.quaternion.fromArray(data.quaternion);
          if (data.scale !== undefined)
            object.scale.fromArray(data.scale);
        }
        if (data.castShadow !== undefined)
          object.castShadow = data.castShadow;
        if (data.receiveShadow !== undefined)
          object.receiveShadow = data.receiveShadow;
        if (data.shadow) {
          if (data.shadow.bias !== undefined)
            object.shadow.bias = data.shadow.bias;
          if (data.shadow.radius !== undefined)
            object.shadow.radius = data.shadow.radius;
          if (data.shadow.mapSize !== undefined)
            object.shadow.mapSize.fromArray(data.shadow.mapSize);
          if (data.shadow.camera !== undefined)
            object.shadow.camera = this.parseObject(data.shadow.camera);
        }
        if (data.visible !== undefined)
          object.visible = data.visible;
        if (data.userData !== undefined)
          object.userData = data.userData;
        if (data.children !== undefined) {
          var children = data.children;
          for (var i = 0; i < children.length; i++) {
            object.add(this.parseObject(children[i], geometries, materials));
          }
        }
        if (data.type === 'LOD') {
          var levels = data.levels;
          for (var l = 0; l < levels.length; l++) {
            var level = levels[l];
            var child = object.getObjectByProperty('uuid', level.object);
            if (child !== undefined) {
              object.addLevel(child, level.distance);
            }
          }
        }
        return object;
      };
    }()
  });
  var TEXTURE_MAPPING = {
    UVMapping: UVMapping,
    CubeReflectionMapping: CubeReflectionMapping,
    CubeRefractionMapping: CubeRefractionMapping,
    EquirectangularReflectionMapping: EquirectangularReflectionMapping,
    EquirectangularRefractionMapping: EquirectangularRefractionMapping,
    SphericalReflectionMapping: SphericalReflectionMapping,
    CubeUVReflectionMapping: CubeUVReflectionMapping,
    CubeUVRefractionMapping: CubeUVRefractionMapping
  };
  var TEXTURE_WRAPPING = {
    RepeatWrapping: RepeatWrapping,
    ClampToEdgeWrapping: ClampToEdgeWrapping,
    MirroredRepeatWrapping: MirroredRepeatWrapping
  };
  var TEXTURE_FILTER = {
    NearestFilter: NearestFilter,
    NearestMipMapNearestFilter: NearestMipMapNearestFilter,
    NearestMipMapLinearFilter: NearestMipMapLinearFilter,
    LinearFilter: LinearFilter,
    LinearMipMapNearestFilter: LinearMipMapNearestFilter,
    LinearMipMapLinearFilter: LinearMipMapLinearFilter
  };
  function CatmullRom(t, p0, p1, p2, p3) {
    var v0 = (p2 - p0) * 0.5;
    var v1 = (p3 - p1) * 0.5;
    var t2 = t * t;
    var t3 = t * t2;
    return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
  }
  function QuadraticBezierP0(t, p) {
    var k = 1 - t;
    return k * k * p;
  }
  function QuadraticBezierP1(t, p) {
    return 2 * (1 - t) * t * p;
  }
  function QuadraticBezierP2(t, p) {
    return t * t * p;
  }
  function QuadraticBezier(t, p0, p1, p2) {
    return QuadraticBezierP0(t, p0) + QuadraticBezierP1(t, p1) + QuadraticBezierP2(t, p2);
  }
  function CubicBezierP0(t, p) {
    var k = 1 - t;
    return k * k * k * p;
  }
  function CubicBezierP1(t, p) {
    var k = 1 - t;
    return 3 * k * k * t * p;
  }
  function CubicBezierP2(t, p) {
    return 3 * (1 - t) * t * t * p;
  }
  function CubicBezierP3(t, p) {
    return t * t * t * p;
  }
  function CubicBezier(t, p0, p1, p2, p3) {
    return CubicBezierP0(t, p0) + CubicBezierP1(t, p1) + CubicBezierP2(t, p2) + CubicBezierP3(t, p3);
  }
  function Curve() {
    this.type = 'Curve';
    this.arcLengthDivisions = 200;
  }
  Object.assign(Curve.prototype, {
    getPoint: function() {
      console.warn('THREE.Curve: .getPoint() not implemented.');
      return null;
    },
    getPointAt: function(u, optionalTarget) {
      var t = this.getUtoTmapping(u);
      return this.getPoint(t, optionalTarget);
    },
    getPoints: function(divisions) {
      if (divisions === undefined)
        divisions = 5;
      var points = [];
      for (var d = 0; d <= divisions; d++) {
        points.push(this.getPoint(d / divisions));
      }
      return points;
    },
    getSpacedPoints: function(divisions) {
      if (divisions === undefined)
        divisions = 5;
      var points = [];
      for (var d = 0; d <= divisions; d++) {
        points.push(this.getPointAt(d / divisions));
      }
      return points;
    },
    getLength: function() {
      var lengths = this.getLengths();
      return lengths[lengths.length - 1];
    },
    getLengths: function(divisions) {
      if (divisions === undefined)
        divisions = this.arcLengthDivisions;
      if (this.cacheArcLengths && (this.cacheArcLengths.length === divisions + 1) && !this.needsUpdate) {
        return this.cacheArcLengths;
      }
      this.needsUpdate = false;
      var cache = [];
      var current,
          last = this.getPoint(0);
      var p,
          sum = 0;
      cache.push(0);
      for (p = 1; p <= divisions; p++) {
        current = this.getPoint(p / divisions);
        sum += current.distanceTo(last);
        cache.push(sum);
        last = current;
      }
      this.cacheArcLengths = cache;
      return cache;
    },
    updateArcLengths: function() {
      this.needsUpdate = true;
      this.getLengths();
    },
    getUtoTmapping: function(u, distance) {
      var arcLengths = this.getLengths();
      var i = 0,
          il = arcLengths.length;
      var targetArcLength;
      if (distance) {
        targetArcLength = distance;
      } else {
        targetArcLength = u * arcLengths[il - 1];
      }
      var low = 0,
          high = il - 1,
          comparison;
      while (low <= high) {
        i = Math.floor(low + (high - low) / 2);
        comparison = arcLengths[i] - targetArcLength;
        if (comparison < 0) {
          low = i + 1;
        } else if (comparison > 0) {
          high = i - 1;
        } else {
          high = i;
          break;
        }
      }
      i = high;
      if (arcLengths[i] === targetArcLength) {
        return i / (il - 1);
      }
      var lengthBefore = arcLengths[i];
      var lengthAfter = arcLengths[i + 1];
      var segmentLength = lengthAfter - lengthBefore;
      var segmentFraction = (targetArcLength - lengthBefore) / segmentLength;
      var t = (i + segmentFraction) / (il - 1);
      return t;
    },
    getTangent: function(t) {
      var delta = 0.0001;
      var t1 = t - delta;
      var t2 = t + delta;
      if (t1 < 0)
        t1 = 0;
      if (t2 > 1)
        t2 = 1;
      var pt1 = this.getPoint(t1);
      var pt2 = this.getPoint(t2);
      var vec = pt2.clone().sub(pt1);
      return vec.normalize();
    },
    getTangentAt: function(u) {
      var t = this.getUtoTmapping(u);
      return this.getTangent(t);
    },
    computeFrenetFrames: function(segments, closed) {
      var normal = new Vector3();
      var tangents = [];
      var normals = [];
      var binormals = [];
      var vec = new Vector3();
      var mat = new Matrix4();
      var i,
          u,
          theta;
      for (i = 0; i <= segments; i++) {
        u = i / segments;
        tangents[i] = this.getTangentAt(u);
        tangents[i].normalize();
      }
      normals[0] = new Vector3();
      binormals[0] = new Vector3();
      var min = Number.MAX_VALUE;
      var tx = Math.abs(tangents[0].x);
      var ty = Math.abs(tangents[0].y);
      var tz = Math.abs(tangents[0].z);
      if (tx <= min) {
        min = tx;
        normal.set(1, 0, 0);
      }
      if (ty <= min) {
        min = ty;
        normal.set(0, 1, 0);
      }
      if (tz <= min) {
        normal.set(0, 0, 1);
      }
      vec.crossVectors(tangents[0], normal).normalize();
      normals[0].crossVectors(tangents[0], vec);
      binormals[0].crossVectors(tangents[0], normals[0]);
      for (i = 1; i <= segments; i++) {
        normals[i] = normals[i - 1].clone();
        binormals[i] = binormals[i - 1].clone();
        vec.crossVectors(tangents[i - 1], tangents[i]);
        if (vec.length() > Number.EPSILON) {
          vec.normalize();
          theta = Math.acos(_Math.clamp(tangents[i - 1].dot(tangents[i]), -1, 1));
          normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
        }
        binormals[i].crossVectors(tangents[i], normals[i]);
      }
      if (closed === true) {
        theta = Math.acos(_Math.clamp(normals[0].dot(normals[segments]), -1, 1));
        theta /= segments;
        if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
          theta = -theta;
        }
        for (i = 1; i <= segments; i++) {
          normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i));
          binormals[i].crossVectors(tangents[i], normals[i]);
        }
      }
      return {
        tangents: tangents,
        normals: normals,
        binormals: binormals
      };
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.arcLengthDivisions = source.arcLengthDivisions;
      return this;
    }
  });
  function LineCurve(v1, v2) {
    Curve.call(this);
    this.type = 'LineCurve';
    this.v1 = v1 || new Vector2();
    this.v2 = v2 || new Vector2();
  }
  LineCurve.prototype = Object.create(Curve.prototype);
  LineCurve.prototype.constructor = LineCurve;
  LineCurve.prototype.isLineCurve = true;
  LineCurve.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector2();
    if (t === 1) {
      point.copy(this.v2);
    } else {
      point.copy(this.v2).sub(this.v1);
      point.multiplyScalar(t).add(this.v1);
    }
    return point;
  };
  LineCurve.prototype.getPointAt = function(u, optionalTarget) {
    return this.getPoint(u, optionalTarget);
  };
  LineCurve.prototype.getTangent = function() {
    var tangent = this.v2.clone().sub(this.v1);
    return tangent.normalize();
  };
  LineCurve.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.v1.copy(source.v1);
    this.v2.copy(source.v2);
    return this;
  };
  function CurvePath() {
    Curve.call(this);
    this.type = 'CurvePath';
    this.curves = [];
    this.autoClose = false;
  }
  CurvePath.prototype = Object.assign(Object.create(Curve.prototype), {
    constructor: CurvePath,
    add: function(curve) {
      this.curves.push(curve);
    },
    closePath: function() {
      var startPoint = this.curves[0].getPoint(0);
      var endPoint = this.curves[this.curves.length - 1].getPoint(1);
      if (!startPoint.equals(endPoint)) {
        this.curves.push(new LineCurve(endPoint, startPoint));
      }
    },
    getPoint: function(t) {
      var d = t * this.getLength();
      var curveLengths = this.getCurveLengths();
      var i = 0;
      while (i < curveLengths.length) {
        if (curveLengths[i] >= d) {
          var diff = curveLengths[i] - d;
          var curve = this.curves[i];
          var segmentLength = curve.getLength();
          var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
          return curve.getPointAt(u);
        }
        i++;
      }
      return null;
    },
    getLength: function() {
      var lens = this.getCurveLengths();
      return lens[lens.length - 1];
    },
    updateArcLengths: function() {
      this.needsUpdate = true;
      this.cacheLengths = null;
      this.getCurveLengths();
    },
    getCurveLengths: function() {
      if (this.cacheLengths && this.cacheLengths.length === this.curves.length) {
        return this.cacheLengths;
      }
      var lengths = [],
          sums = 0;
      for (var i = 0,
          l = this.curves.length; i < l; i++) {
        sums += this.curves[i].getLength();
        lengths.push(sums);
      }
      this.cacheLengths = lengths;
      return lengths;
    },
    getSpacedPoints: function(divisions) {
      if (divisions === undefined)
        divisions = 40;
      var points = [];
      for (var i = 0; i <= divisions; i++) {
        points.push(this.getPoint(i / divisions));
      }
      if (this.autoClose) {
        points.push(points[0]);
      }
      return points;
    },
    getPoints: function(divisions) {
      divisions = divisions || 12;
      var points = [],
          last;
      for (var i = 0,
          curves = this.curves; i < curves.length; i++) {
        var curve = curves[i];
        var resolution = (curve && curve.isEllipseCurve) ? divisions * 2 : (curve && curve.isLineCurve) ? 1 : (curve && curve.isSplineCurve) ? divisions * curve.points.length : divisions;
        var pts = curve.getPoints(resolution);
        for (var j = 0; j < pts.length; j++) {
          var point = pts[j];
          if (last && last.equals(point))
            continue;
          points.push(point);
          last = point;
        }
      }
      if (this.autoClose && points.length > 1 && !points[points.length - 1].equals(points[0])) {
        points.push(points[0]);
      }
      return points;
    },
    copy: function(source) {
      Curve.prototype.copy.call(this, source);
      this.curves = [];
      for (var i = 0,
          l = source.curves.length; i < l; i++) {
        var curve = source.curves[i];
        this.curves.push(curve.clone());
      }
      this.autoClose = source.autoClose;
      return this;
    }
  });
  function EllipseCurve(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
    Curve.call(this);
    this.type = 'EllipseCurve';
    this.aX = aX || 0;
    this.aY = aY || 0;
    this.xRadius = xRadius || 1;
    this.yRadius = yRadius || 1;
    this.aStartAngle = aStartAngle || 0;
    this.aEndAngle = aEndAngle || 2 * Math.PI;
    this.aClockwise = aClockwise || false;
    this.aRotation = aRotation || 0;
  }
  EllipseCurve.prototype = Object.create(Curve.prototype);
  EllipseCurve.prototype.constructor = EllipseCurve;
  EllipseCurve.prototype.isEllipseCurve = true;
  EllipseCurve.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector2();
    var twoPi = Math.PI * 2;
    var deltaAngle = this.aEndAngle - this.aStartAngle;
    var samePoints = Math.abs(deltaAngle) < Number.EPSILON;
    while (deltaAngle < 0)
      deltaAngle += twoPi;
    while (deltaAngle > twoPi)
      deltaAngle -= twoPi;
    if (deltaAngle < Number.EPSILON) {
      if (samePoints) {
        deltaAngle = 0;
      } else {
        deltaAngle = twoPi;
      }
    }
    if (this.aClockwise === true && !samePoints) {
      if (deltaAngle === twoPi) {
        deltaAngle = -twoPi;
      } else {
        deltaAngle = deltaAngle - twoPi;
      }
    }
    var angle = this.aStartAngle + t * deltaAngle;
    var x = this.aX + this.xRadius * Math.cos(angle);
    var y = this.aY + this.yRadius * Math.sin(angle);
    if (this.aRotation !== 0) {
      var cos = Math.cos(this.aRotation);
      var sin = Math.sin(this.aRotation);
      var tx = x - this.aX;
      var ty = y - this.aY;
      x = tx * cos - ty * sin + this.aX;
      y = tx * sin + ty * cos + this.aY;
    }
    return point.set(x, y);
  };
  EllipseCurve.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.aX = source.aX;
    this.aY = source.aY;
    this.xRadius = source.xRadius;
    this.yRadius = source.yRadius;
    this.aStartAngle = source.aStartAngle;
    this.aEndAngle = source.aEndAngle;
    this.aClockwise = source.aClockwise;
    this.aRotation = source.aRotation;
    return this;
  };
  function SplineCurve(points) {
    Curve.call(this);
    this.type = 'SplineCurve';
    this.points = points || [];
  }
  SplineCurve.prototype = Object.create(Curve.prototype);
  SplineCurve.prototype.constructor = SplineCurve;
  SplineCurve.prototype.isSplineCurve = true;
  SplineCurve.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector2();
    var points = this.points;
    var p = (points.length - 1) * t;
    var intPoint = Math.floor(p);
    var weight = p - intPoint;
    var p0 = points[intPoint === 0 ? intPoint : intPoint - 1];
    var p1 = points[intPoint];
    var p2 = points[intPoint > points.length - 2 ? points.length - 1 : intPoint + 1];
    var p3 = points[intPoint > points.length - 3 ? points.length - 1 : intPoint + 2];
    point.set(CatmullRom(weight, p0.x, p1.x, p2.x, p3.x), CatmullRom(weight, p0.y, p1.y, p2.y, p3.y));
    return point;
  };
  SplineCurve.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.points = [];
    for (var i = 0,
        l = source.points.length; i < l; i++) {
      var point = source.points[i];
      this.points.push(point.clone());
    }
    return this;
  };
  function CubicBezierCurve(v0, v1, v2, v3) {
    Curve.call(this);
    this.type = 'CubicBezierCurve';
    this.v0 = v0 || new Vector2();
    this.v1 = v1 || new Vector2();
    this.v2 = v2 || new Vector2();
    this.v3 = v3 || new Vector2();
  }
  CubicBezierCurve.prototype = Object.create(Curve.prototype);
  CubicBezierCurve.prototype.constructor = CubicBezierCurve;
  CubicBezierCurve.prototype.isCubicBezierCurve = true;
  CubicBezierCurve.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector2();
    var v0 = this.v0,
        v1 = this.v1,
        v2 = this.v2,
        v3 = this.v3;
    point.set(CubicBezier(t, v0.x, v1.x, v2.x, v3.x), CubicBezier(t, v0.y, v1.y, v2.y, v3.y));
    return point;
  };
  CubicBezierCurve.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.v0.copy(source.v0);
    this.v1.copy(source.v1);
    this.v2.copy(source.v2);
    this.v3.copy(source.v3);
    return this;
  };
  function QuadraticBezierCurve(v0, v1, v2) {
    Curve.call(this);
    this.type = 'QuadraticBezierCurve';
    this.v0 = v0 || new Vector2();
    this.v1 = v1 || new Vector2();
    this.v2 = v2 || new Vector2();
  }
  QuadraticBezierCurve.prototype = Object.create(Curve.prototype);
  QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
  QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
  QuadraticBezierCurve.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector2();
    var v0 = this.v0,
        v1 = this.v1,
        v2 = this.v2;
    point.set(QuadraticBezier(t, v0.x, v1.x, v2.x), QuadraticBezier(t, v0.y, v1.y, v2.y));
    return point;
  };
  QuadraticBezierCurve.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.v0.copy(source.v0);
    this.v1.copy(source.v1);
    this.v2.copy(source.v2);
    return this;
  };
  var PathPrototype = Object.assign(Object.create(CurvePath.prototype), {
    setFromPoints: function(points) {
      this.moveTo(points[0].x, points[0].y);
      for (var i = 1,
          l = points.length; i < l; i++) {
        this.lineTo(points[i].x, points[i].y);
      }
    },
    moveTo: function(x, y) {
      this.currentPoint.set(x, y);
    },
    lineTo: function(x, y) {
      var curve = new LineCurve(this.currentPoint.clone(), new Vector2(x, y));
      this.curves.push(curve);
      this.currentPoint.set(x, y);
    },
    quadraticCurveTo: function(aCPx, aCPy, aX, aY) {
      var curve = new QuadraticBezierCurve(this.currentPoint.clone(), new Vector2(aCPx, aCPy), new Vector2(aX, aY));
      this.curves.push(curve);
      this.currentPoint.set(aX, aY);
    },
    bezierCurveTo: function(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
      var curve = new CubicBezierCurve(this.currentPoint.clone(), new Vector2(aCP1x, aCP1y), new Vector2(aCP2x, aCP2y), new Vector2(aX, aY));
      this.curves.push(curve);
      this.currentPoint.set(aX, aY);
    },
    splineThru: function(pts) {
      var npts = [this.currentPoint.clone()].concat(pts);
      var curve = new SplineCurve(npts);
      this.curves.push(curve);
      this.currentPoint.copy(pts[pts.length - 1]);
    },
    arc: function(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
      var x0 = this.currentPoint.x;
      var y0 = this.currentPoint.y;
      this.absarc(aX + x0, aY + y0, aRadius, aStartAngle, aEndAngle, aClockwise);
    },
    absarc: function(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
      this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
    },
    ellipse: function(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
      var x0 = this.currentPoint.x;
      var y0 = this.currentPoint.y;
      this.absellipse(aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation);
    },
    absellipse: function(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
      var curve = new EllipseCurve(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation);
      if (this.curves.length > 0) {
        var firstPoint = curve.getPoint(0);
        if (!firstPoint.equals(this.currentPoint)) {
          this.lineTo(firstPoint.x, firstPoint.y);
        }
      }
      this.curves.push(curve);
      var lastPoint = curve.getPoint(1);
      this.currentPoint.copy(lastPoint);
    },
    copy: function(source) {
      CurvePath.prototype.copy.call(this, source);
      this.currentPoint.copy(source.currentPoint);
      return this;
    }
  });
  function Path(points) {
    CurvePath.call(this);
    this.type = 'Path';
    this.currentPoint = new Vector2();
    if (points) {
      this.setFromPoints(points);
    }
  }
  Path.prototype = PathPrototype;
  PathPrototype.constructor = Path;
  function Shape(points) {
    Path.call(this, points);
    this.type = 'Shape';
    this.holes = [];
  }
  Shape.prototype = Object.assign(Object.create(PathPrototype), {
    constructor: Shape,
    getPointsHoles: function(divisions) {
      var holesPts = [];
      for (var i = 0,
          l = this.holes.length; i < l; i++) {
        holesPts[i] = this.holes[i].getPoints(divisions);
      }
      return holesPts;
    },
    extractPoints: function(divisions) {
      return {
        shape: this.getPoints(divisions),
        holes: this.getPointsHoles(divisions)
      };
    },
    copy: function(source) {
      Path.prototype.copy.call(this, source);
      this.holes = [];
      for (var i = 0,
          l = source.holes.length; i < l; i++) {
        var hole = source.holes[i];
        this.holes.push(hole.clone());
      }
      return this;
    }
  });
  function ShapePath() {
    this.type = 'ShapePath';
    this.subPaths = [];
    this.currentPath = null;
  }
  Object.assign(ShapePath.prototype, {
    moveTo: function(x, y) {
      this.currentPath = new Path();
      this.subPaths.push(this.currentPath);
      this.currentPath.moveTo(x, y);
    },
    lineTo: function(x, y) {
      this.currentPath.lineTo(x, y);
    },
    quadraticCurveTo: function(aCPx, aCPy, aX, aY) {
      this.currentPath.quadraticCurveTo(aCPx, aCPy, aX, aY);
    },
    bezierCurveTo: function(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
      this.currentPath.bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY);
    },
    splineThru: function(pts) {
      this.currentPath.splineThru(pts);
    },
    toShapes: function(isCCW, noHoles) {
      function toShapesNoHoles(inSubpaths) {
        var shapes = [];
        for (var i = 0,
            l = inSubpaths.length; i < l; i++) {
          var tmpPath = inSubpaths[i];
          var tmpShape = new Shape();
          tmpShape.curves = tmpPath.curves;
          shapes.push(tmpShape);
        }
        return shapes;
      }
      function isPointInsidePolygon(inPt, inPolygon) {
        var polyLen = inPolygon.length;
        var inside = false;
        for (var p = polyLen - 1,
            q = 0; q < polyLen; p = q++) {
          var edgeLowPt = inPolygon[p];
          var edgeHighPt = inPolygon[q];
          var edgeDx = edgeHighPt.x - edgeLowPt.x;
          var edgeDy = edgeHighPt.y - edgeLowPt.y;
          if (Math.abs(edgeDy) > Number.EPSILON) {
            if (edgeDy < 0) {
              edgeLowPt = inPolygon[q];
              edgeDx = -edgeDx;
              edgeHighPt = inPolygon[p];
              edgeDy = -edgeDy;
            }
            if ((inPt.y < edgeLowPt.y) || (inPt.y > edgeHighPt.y))
              continue;
            if (inPt.y === edgeLowPt.y) {
              if (inPt.x === edgeLowPt.x)
                return true;
            } else {
              var perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
              if (perpEdge === 0)
                return true;
              if (perpEdge < 0)
                continue;
              inside = !inside;
            }
          } else {
            if (inPt.y !== edgeLowPt.y)
              continue;
            if (((edgeHighPt.x <= inPt.x) && (inPt.x <= edgeLowPt.x)) || ((edgeLowPt.x <= inPt.x) && (inPt.x <= edgeHighPt.x)))
              return true;
          }
        }
        return inside;
      }
      var isClockWise = ShapeUtils.isClockWise;
      var subPaths = this.subPaths;
      if (subPaths.length === 0)
        return [];
      if (noHoles === true)
        return toShapesNoHoles(subPaths);
      var solid,
          tmpPath,
          tmpShape,
          shapes = [];
      if (subPaths.length === 1) {
        tmpPath = subPaths[0];
        tmpShape = new Shape();
        tmpShape.curves = tmpPath.curves;
        shapes.push(tmpShape);
        return shapes;
      }
      var holesFirst = !isClockWise(subPaths[0].getPoints());
      holesFirst = isCCW ? !holesFirst : holesFirst;
      var betterShapeHoles = [];
      var newShapes = [];
      var newShapeHoles = [];
      var mainIdx = 0;
      var tmpPoints;
      newShapes[mainIdx] = undefined;
      newShapeHoles[mainIdx] = [];
      for (var i = 0,
          l = subPaths.length; i < l; i++) {
        tmpPath = subPaths[i];
        tmpPoints = tmpPath.getPoints();
        solid = isClockWise(tmpPoints);
        solid = isCCW ? !solid : solid;
        if (solid) {
          if ((!holesFirst) && (newShapes[mainIdx]))
            mainIdx++;
          newShapes[mainIdx] = {
            s: new Shape(),
            p: tmpPoints
          };
          newShapes[mainIdx].s.curves = tmpPath.curves;
          if (holesFirst)
            mainIdx++;
          newShapeHoles[mainIdx] = [];
        } else {
          newShapeHoles[mainIdx].push({
            h: tmpPath,
            p: tmpPoints[0]
          });
        }
      }
      if (!newShapes[0])
        return toShapesNoHoles(subPaths);
      if (newShapes.length > 1) {
        var ambiguous = false;
        var toChange = [];
        for (var sIdx = 0,
            sLen = newShapes.length; sIdx < sLen; sIdx++) {
          betterShapeHoles[sIdx] = [];
        }
        for (var sIdx = 0,
            sLen = newShapes.length; sIdx < sLen; sIdx++) {
          var sho = newShapeHoles[sIdx];
          for (var hIdx = 0; hIdx < sho.length; hIdx++) {
            var ho = sho[hIdx];
            var hole_unassigned = true;
            for (var s2Idx = 0; s2Idx < newShapes.length; s2Idx++) {
              if (isPointInsidePolygon(ho.p, newShapes[s2Idx].p)) {
                if (sIdx !== s2Idx)
                  toChange.push({
                    froms: sIdx,
                    tos: s2Idx,
                    hole: hIdx
                  });
                if (hole_unassigned) {
                  hole_unassigned = false;
                  betterShapeHoles[s2Idx].push(ho);
                } else {
                  ambiguous = true;
                }
              }
            }
            if (hole_unassigned) {
              betterShapeHoles[sIdx].push(ho);
            }
          }
        }
        if (toChange.length > 0) {
          if (!ambiguous)
            newShapeHoles = betterShapeHoles;
        }
      }
      var tmpHoles;
      for (var i = 0,
          il = newShapes.length; i < il; i++) {
        tmpShape = newShapes[i].s;
        shapes.push(tmpShape);
        tmpHoles = newShapeHoles[i];
        for (var j = 0,
            jl = tmpHoles.length; j < jl; j++) {
          tmpShape.holes.push(tmpHoles[j].h);
        }
      }
      return shapes;
    }
  });
  function Font(data) {
    this.type = 'Font';
    this.data = data;
  }
  Object.assign(Font.prototype, {
    isFont: true,
    generateShapes: function(text, size, divisions) {
      function createPaths(text) {
        var chars = String(text).split('');
        var scale = size / data.resolution;
        var line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale;
        var offsetX = 0,
            offsetY = 0;
        var paths = [];
        for (var i = 0; i < chars.length; i++) {
          var char = chars[i];
          if (char === '\n') {
            offsetX = 0;
            offsetY -= line_height;
          } else {
            var ret = createPath(char, scale, offsetX, offsetY);
            offsetX += ret.offsetX;
            paths.push(ret.path);
          }
        }
        return paths;
      }
      function createPath(c, scale, offsetX, offsetY) {
        var glyph = data.glyphs[c] || data.glyphs['?'];
        if (!glyph)
          return;
        var path = new ShapePath();
        var pts = [];
        var x,
            y,
            cpx,
            cpy,
            cpx0,
            cpy0,
            cpx1,
            cpy1,
            cpx2,
            cpy2,
            laste;
        if (glyph.o) {
          var outline = glyph._cachedOutline || (glyph._cachedOutline = glyph.o.split(' '));
          for (var i = 0,
              l = outline.length; i < l; ) {
            var action = outline[i++];
            switch (action) {
              case 'm':
                x = outline[i++] * scale + offsetX;
                y = outline[i++] * scale + offsetY;
                path.moveTo(x, y);
                break;
              case 'l':
                x = outline[i++] * scale + offsetX;
                y = outline[i++] * scale + offsetY;
                path.lineTo(x, y);
                break;
              case 'q':
                cpx = outline[i++] * scale + offsetX;
                cpy = outline[i++] * scale + offsetY;
                cpx1 = outline[i++] * scale + offsetX;
                cpy1 = outline[i++] * scale + offsetY;
                path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
                laste = pts[pts.length - 1];
                if (laste) {
                  cpx0 = laste.x;
                  cpy0 = laste.y;
                  for (var i2 = 1; i2 <= divisions; i2++) {
                    var t = i2 / divisions;
                    QuadraticBezier(t, cpx0, cpx1, cpx);
                    QuadraticBezier(t, cpy0, cpy1, cpy);
                  }
                }
                break;
              case 'b':
                cpx = outline[i++] * scale + offsetX;
                cpy = outline[i++] * scale + offsetY;
                cpx1 = outline[i++] * scale + offsetX;
                cpy1 = outline[i++] * scale + offsetY;
                cpx2 = outline[i++] * scale + offsetX;
                cpy2 = outline[i++] * scale + offsetY;
                path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, cpx, cpy);
                laste = pts[pts.length - 1];
                if (laste) {
                  cpx0 = laste.x;
                  cpy0 = laste.y;
                  for (var i2 = 1; i2 <= divisions; i2++) {
                    var t = i2 / divisions;
                    CubicBezier(t, cpx0, cpx1, cpx2, cpx);
                    CubicBezier(t, cpy0, cpy1, cpy2, cpy);
                  }
                }
                break;
            }
          }
        }
        return {
          offsetX: glyph.ha * scale,
          path: path
        };
      }
      if (size === undefined)
        size = 100;
      if (divisions === undefined)
        divisions = 4;
      var data = this.data;
      var paths = createPaths(text);
      var shapes = [];
      for (var p = 0,
          pl = paths.length; p < pl; p++) {
        Array.prototype.push.apply(shapes, paths[p].toShapes());
      }
      return shapes;
    }
  });
  function FontLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
  }
  Object.assign(FontLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var loader = new FileLoader(this.manager);
      loader.setPath(this.path);
      loader.load(url, function(text) {
        var json;
        try {
          json = JSON.parse(text);
        } catch (e) {
          console.warn('THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.');
          json = JSON.parse(text.substring(65, text.length - 2));
        }
        var font = scope.parse(json);
        if (onLoad)
          onLoad(font);
      }, onProgress, onError);
    },
    parse: function(json) {
      return new Font(json);
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  var context;
  var AudioContext = {
    getContext: function() {
      if (context === undefined) {
        context = new (window.AudioContext || window.webkitAudioContext)();
      }
      return context;
    },
    setContext: function(value) {
      context = value;
    }
  };
  function AudioLoader(manager) {
    this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
  }
  Object.assign(AudioLoader.prototype, {load: function(url, onLoad, onProgress, onError) {
      var loader = new FileLoader(this.manager);
      loader.setResponseType('arraybuffer');
      loader.load(url, function(buffer) {
        var context = AudioContext.getContext();
        context.decodeAudioData(buffer, function(audioBuffer) {
          onLoad(audioBuffer);
        });
      }, onProgress, onError);
    }});
  function StereoCamera() {
    this.type = 'StereoCamera';
    this.aspect = 1;
    this.eyeSep = 0.064;
    this.cameraL = new PerspectiveCamera();
    this.cameraL.layers.enable(1);
    this.cameraL.matrixAutoUpdate = false;
    this.cameraR = new PerspectiveCamera();
    this.cameraR.layers.enable(2);
    this.cameraR.matrixAutoUpdate = false;
  }
  Object.assign(StereoCamera.prototype, {update: (function() {
      var instance,
          focus,
          fov,
          aspect,
          near,
          far,
          zoom,
          eyeSep;
      var eyeRight = new Matrix4();
      var eyeLeft = new Matrix4();
      return function update(camera) {
        var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov || aspect !== camera.aspect * this.aspect || near !== camera.near || far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep;
        if (needsUpdate) {
          instance = this;
          focus = camera.focus;
          fov = camera.fov;
          aspect = camera.aspect * this.aspect;
          near = camera.near;
          far = camera.far;
          zoom = camera.zoom;
          var projectionMatrix = camera.projectionMatrix.clone();
          eyeSep = this.eyeSep / 2;
          var eyeSepOnProjection = eyeSep * near / focus;
          var ymax = (near * Math.tan(_Math.DEG2RAD * fov * 0.5)) / zoom;
          var xmin,
              xmax;
          eyeLeft.elements[12] = -eyeSep;
          eyeRight.elements[12] = eyeSep;
          xmin = -ymax * aspect + eyeSepOnProjection;
          xmax = ymax * aspect + eyeSepOnProjection;
          projectionMatrix.elements[0] = 2 * near / (xmax - xmin);
          projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin);
          this.cameraL.projectionMatrix.copy(projectionMatrix);
          xmin = -ymax * aspect - eyeSepOnProjection;
          xmax = ymax * aspect - eyeSepOnProjection;
          projectionMatrix.elements[0] = 2 * near / (xmax - xmin);
          projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin);
          this.cameraR.projectionMatrix.copy(projectionMatrix);
        }
        this.cameraL.matrixWorld.copy(camera.matrixWorld).multiply(eyeLeft);
        this.cameraR.matrixWorld.copy(camera.matrixWorld).multiply(eyeRight);
      };
    })()});
  function CubeCamera(near, far, cubeResolution) {
    Object3D.call(this);
    this.type = 'CubeCamera';
    var fov = 90,
        aspect = 1;
    var cameraPX = new PerspectiveCamera(fov, aspect, near, far);
    cameraPX.up.set(0, -1, 0);
    cameraPX.lookAt(new Vector3(1, 0, 0));
    this.add(cameraPX);
    var cameraNX = new PerspectiveCamera(fov, aspect, near, far);
    cameraNX.up.set(0, -1, 0);
    cameraNX.lookAt(new Vector3(-1, 0, 0));
    this.add(cameraNX);
    var cameraPY = new PerspectiveCamera(fov, aspect, near, far);
    cameraPY.up.set(0, 0, 1);
    cameraPY.lookAt(new Vector3(0, 1, 0));
    this.add(cameraPY);
    var cameraNY = new PerspectiveCamera(fov, aspect, near, far);
    cameraNY.up.set(0, 0, -1);
    cameraNY.lookAt(new Vector3(0, -1, 0));
    this.add(cameraNY);
    var cameraPZ = new PerspectiveCamera(fov, aspect, near, far);
    cameraPZ.up.set(0, -1, 0);
    cameraPZ.lookAt(new Vector3(0, 0, 1));
    this.add(cameraPZ);
    var cameraNZ = new PerspectiveCamera(fov, aspect, near, far);
    cameraNZ.up.set(0, -1, 0);
    cameraNZ.lookAt(new Vector3(0, 0, -1));
    this.add(cameraNZ);
    var options = {
      format: RGBFormat,
      magFilter: LinearFilter,
      minFilter: LinearFilter
    };
    this.renderTarget = new WebGLRenderTargetCube(cubeResolution, cubeResolution, options);
    this.renderTarget.texture.name = "CubeCamera";
    this.update = function(renderer, scene) {
      if (this.parent === null)
        this.updateMatrixWorld();
      var renderTarget = this.renderTarget;
      var generateMipmaps = renderTarget.texture.generateMipmaps;
      renderTarget.texture.generateMipmaps = false;
      renderTarget.activeCubeFace = 0;
      renderer.render(scene, cameraPX, renderTarget);
      renderTarget.activeCubeFace = 1;
      renderer.render(scene, cameraNX, renderTarget);
      renderTarget.activeCubeFace = 2;
      renderer.render(scene, cameraPY, renderTarget);
      renderTarget.activeCubeFace = 3;
      renderer.render(scene, cameraNY, renderTarget);
      renderTarget.activeCubeFace = 4;
      renderer.render(scene, cameraPZ, renderTarget);
      renderTarget.texture.generateMipmaps = generateMipmaps;
      renderTarget.activeCubeFace = 5;
      renderer.render(scene, cameraNZ, renderTarget);
      renderer.setRenderTarget(null);
    };
    this.clear = function(renderer, color, depth, stencil) {
      var renderTarget = this.renderTarget;
      for (var i = 0; i < 6; i++) {
        renderTarget.activeCubeFace = i;
        renderer.setRenderTarget(renderTarget);
        renderer.clear(color, depth, stencil);
      }
      renderer.setRenderTarget(null);
    };
  }
  CubeCamera.prototype = Object.create(Object3D.prototype);
  CubeCamera.prototype.constructor = CubeCamera;
  function AudioListener() {
    Object3D.call(this);
    this.type = 'AudioListener';
    this.context = AudioContext.getContext();
    this.gain = this.context.createGain();
    this.gain.connect(this.context.destination);
    this.filter = null;
  }
  AudioListener.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: AudioListener,
    getInput: function() {
      return this.gain;
    },
    removeFilter: function() {
      if (this.filter !== null) {
        this.gain.disconnect(this.filter);
        this.filter.disconnect(this.context.destination);
        this.gain.connect(this.context.destination);
        this.filter = null;
      }
    },
    getFilter: function() {
      return this.filter;
    },
    setFilter: function(value) {
      if (this.filter !== null) {
        this.gain.disconnect(this.filter);
        this.filter.disconnect(this.context.destination);
      } else {
        this.gain.disconnect(this.context.destination);
      }
      this.filter = value;
      this.gain.connect(this.filter);
      this.filter.connect(this.context.destination);
    },
    getMasterVolume: function() {
      return this.gain.gain.value;
    },
    setMasterVolume: function(value) {
      this.gain.gain.value = value;
    },
    updateMatrixWorld: (function() {
      var position = new Vector3();
      var quaternion = new Quaternion();
      var scale = new Vector3();
      var orientation = new Vector3();
      return function updateMatrixWorld(force) {
        Object3D.prototype.updateMatrixWorld.call(this, force);
        var listener = this.context.listener;
        var up = this.up;
        this.matrixWorld.decompose(position, quaternion, scale);
        orientation.set(0, 0, -1).applyQuaternion(quaternion);
        if (listener.positionX) {
          listener.positionX.setValueAtTime(position.x, this.context.currentTime);
          listener.positionY.setValueAtTime(position.y, this.context.currentTime);
          listener.positionZ.setValueAtTime(position.z, this.context.currentTime);
          listener.forwardX.setValueAtTime(orientation.x, this.context.currentTime);
          listener.forwardY.setValueAtTime(orientation.y, this.context.currentTime);
          listener.forwardZ.setValueAtTime(orientation.z, this.context.currentTime);
          listener.upX.setValueAtTime(up.x, this.context.currentTime);
          listener.upY.setValueAtTime(up.y, this.context.currentTime);
          listener.upZ.setValueAtTime(up.z, this.context.currentTime);
        } else {
          listener.setPosition(position.x, position.y, position.z);
          listener.setOrientation(orientation.x, orientation.y, orientation.z, up.x, up.y, up.z);
        }
      };
    })()
  });
  function Audio(listener) {
    Object3D.call(this);
    this.type = 'Audio';
    this.context = listener.context;
    this.gain = this.context.createGain();
    this.gain.connect(listener.getInput());
    this.autoplay = false;
    this.buffer = null;
    this.loop = false;
    this.startTime = 0;
    this.offset = 0;
    this.playbackRate = 1;
    this.isPlaying = false;
    this.hasPlaybackControl = true;
    this.sourceType = 'empty';
    this.filters = [];
  }
  Audio.prototype = Object.assign(Object.create(Object3D.prototype), {
    constructor: Audio,
    getOutput: function() {
      return this.gain;
    },
    setNodeSource: function(audioNode) {
      this.hasPlaybackControl = false;
      this.sourceType = 'audioNode';
      this.source = audioNode;
      this.connect();
      return this;
    },
    setBuffer: function(audioBuffer) {
      this.buffer = audioBuffer;
      this.sourceType = 'buffer';
      if (this.autoplay)
        this.play();
      return this;
    },
    play: function() {
      if (this.isPlaying === true) {
        console.warn('THREE.Audio: Audio is already playing.');
        return;
      }
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      var source = this.context.createBufferSource();
      source.buffer = this.buffer;
      source.loop = this.loop;
      source.onended = this.onEnded.bind(this);
      source.playbackRate.setValueAtTime(this.playbackRate, this.startTime);
      this.startTime = this.context.currentTime;
      source.start(this.startTime, this.offset);
      this.isPlaying = true;
      this.source = source;
      return this.connect();
    },
    pause: function() {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      if (this.isPlaying === true) {
        this.source.stop();
        this.offset += (this.context.currentTime - this.startTime) * this.playbackRate;
        this.isPlaying = false;
      }
      return this;
    },
    stop: function() {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      this.source.stop();
      this.offset = 0;
      this.isPlaying = false;
      return this;
    },
    connect: function() {
      if (this.filters.length > 0) {
        this.source.connect(this.filters[0]);
        for (var i = 1,
            l = this.filters.length; i < l; i++) {
          this.filters[i - 1].connect(this.filters[i]);
        }
        this.filters[this.filters.length - 1].connect(this.getOutput());
      } else {
        this.source.connect(this.getOutput());
      }
      return this;
    },
    disconnect: function() {
      if (this.filters.length > 0) {
        this.source.disconnect(this.filters[0]);
        for (var i = 1,
            l = this.filters.length; i < l; i++) {
          this.filters[i - 1].disconnect(this.filters[i]);
        }
        this.filters[this.filters.length - 1].disconnect(this.getOutput());
      } else {
        this.source.disconnect(this.getOutput());
      }
      return this;
    },
    getFilters: function() {
      return this.filters;
    },
    setFilters: function(value) {
      if (!value)
        value = [];
      if (this.isPlaying === true) {
        this.disconnect();
        this.filters = value;
        this.connect();
      } else {
        this.filters = value;
      }
      return this;
    },
    getFilter: function() {
      return this.getFilters()[0];
    },
    setFilter: function(filter) {
      return this.setFilters(filter ? [filter] : []);
    },
    setPlaybackRate: function(value) {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      this.playbackRate = value;
      if (this.isPlaying === true) {
        this.source.playbackRate.setValueAtTime(this.playbackRate, this.context.currentTime);
      }
      return this;
    },
    getPlaybackRate: function() {
      return this.playbackRate;
    },
    onEnded: function() {
      this.isPlaying = false;
    },
    getLoop: function() {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return false;
      }
      return this.loop;
    },
    setLoop: function(value) {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      this.loop = value;
      if (this.isPlaying === true) {
        this.source.loop = this.loop;
      }
      return this;
    },
    getVolume: function() {
      return this.gain.gain.value;
    },
    setVolume: function(value) {
      this.gain.gain.value = value;
      return this;
    }
  });
  function PositionalAudio(listener) {
    Audio.call(this, listener);
    this.panner = this.context.createPanner();
    this.panner.connect(this.gain);
  }
  PositionalAudio.prototype = Object.assign(Object.create(Audio.prototype), {
    constructor: PositionalAudio,
    getOutput: function() {
      return this.panner;
    },
    getRefDistance: function() {
      return this.panner.refDistance;
    },
    setRefDistance: function(value) {
      this.panner.refDistance = value;
    },
    getRolloffFactor: function() {
      return this.panner.rolloffFactor;
    },
    setRolloffFactor: function(value) {
      this.panner.rolloffFactor = value;
    },
    getDistanceModel: function() {
      return this.panner.distanceModel;
    },
    setDistanceModel: function(value) {
      this.panner.distanceModel = value;
    },
    getMaxDistance: function() {
      return this.panner.maxDistance;
    },
    setMaxDistance: function(value) {
      this.panner.maxDistance = value;
    },
    updateMatrixWorld: (function() {
      var position = new Vector3();
      return function updateMatrixWorld(force) {
        Object3D.prototype.updateMatrixWorld.call(this, force);
        position.setFromMatrixPosition(this.matrixWorld);
        this.panner.setPosition(position.x, position.y, position.z);
      };
    })()
  });
  function AudioAnalyser(audio, fftSize) {
    this.analyser = audio.context.createAnalyser();
    this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
    this.data = new Uint8Array(this.analyser.frequencyBinCount);
    audio.getOutput().connect(this.analyser);
  }
  Object.assign(AudioAnalyser.prototype, {
    getFrequencyData: function() {
      this.analyser.getByteFrequencyData(this.data);
      return this.data;
    },
    getAverageFrequency: function() {
      var value = 0,
          data = this.getFrequencyData();
      for (var i = 0; i < data.length; i++) {
        value += data[i];
      }
      return value / data.length;
    }
  });
  function PropertyMixer(binding, typeName, valueSize) {
    this.binding = binding;
    this.valueSize = valueSize;
    var bufferType = Float64Array,
        mixFunction;
    switch (typeName) {
      case 'quaternion':
        mixFunction = this._slerp;
        break;
      case 'string':
      case 'bool':
        bufferType = Array;
        mixFunction = this._select;
        break;
      default:
        mixFunction = this._lerp;
    }
    this.buffer = new bufferType(valueSize * 4);
    this._mixBufferRegion = mixFunction;
    this.cumulativeWeight = 0;
    this.useCount = 0;
    this.referenceCount = 0;
  }
  Object.assign(PropertyMixer.prototype, {
    accumulate: function(accuIndex, weight) {
      var buffer = this.buffer,
          stride = this.valueSize,
          offset = accuIndex * stride + stride,
          currentWeight = this.cumulativeWeight;
      if (currentWeight === 0) {
        for (var i = 0; i !== stride; ++i) {
          buffer[offset + i] = buffer[i];
        }
        currentWeight = weight;
      } else {
        currentWeight += weight;
        var mix = weight / currentWeight;
        this._mixBufferRegion(buffer, offset, 0, mix, stride);
      }
      this.cumulativeWeight = currentWeight;
    },
    apply: function(accuIndex) {
      var stride = this.valueSize,
          buffer = this.buffer,
          offset = accuIndex * stride + stride,
          weight = this.cumulativeWeight,
          binding = this.binding;
      this.cumulativeWeight = 0;
      if (weight < 1) {
        var originalValueOffset = stride * 3;
        this._mixBufferRegion(buffer, offset, originalValueOffset, 1 - weight, stride);
      }
      for (var i = stride,
          e = stride + stride; i !== e; ++i) {
        if (buffer[i] !== buffer[i + stride]) {
          binding.setValue(buffer, offset);
          break;
        }
      }
    },
    saveOriginalState: function() {
      var binding = this.binding;
      var buffer = this.buffer,
          stride = this.valueSize,
          originalValueOffset = stride * 3;
      binding.getValue(buffer, originalValueOffset);
      for (var i = stride,
          e = originalValueOffset; i !== e; ++i) {
        buffer[i] = buffer[originalValueOffset + (i % stride)];
      }
      this.cumulativeWeight = 0;
    },
    restoreOriginalState: function() {
      var originalValueOffset = this.valueSize * 3;
      this.binding.setValue(this.buffer, originalValueOffset);
    },
    _select: function(buffer, dstOffset, srcOffset, t, stride) {
      if (t >= 0.5) {
        for (var i = 0; i !== stride; ++i) {
          buffer[dstOffset + i] = buffer[srcOffset + i];
        }
      }
    },
    _slerp: function(buffer, dstOffset, srcOffset, t) {
      Quaternion.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t);
    },
    _lerp: function(buffer, dstOffset, srcOffset, t, stride) {
      var s = 1 - t;
      for (var i = 0; i !== stride; ++i) {
        var j = dstOffset + i;
        buffer[j] = buffer[j] * s + buffer[srcOffset + i] * t;
      }
    }
  });
  function Composite(targetGroup, path, optionalParsedPath) {
    var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName(path);
    this._targetGroup = targetGroup;
    this._bindings = targetGroup.subscribe_(path, parsedPath);
  }
  Object.assign(Composite.prototype, {
    getValue: function(array, offset) {
      this.bind();
      var firstValidIndex = this._targetGroup.nCachedObjects_,
          binding = this._bindings[firstValidIndex];
      if (binding !== undefined)
        binding.getValue(array, offset);
    },
    setValue: function(array, offset) {
      var bindings = this._bindings;
      for (var i = this._targetGroup.nCachedObjects_,
          n = bindings.length; i !== n; ++i) {
        bindings[i].setValue(array, offset);
      }
    },
    bind: function() {
      var bindings = this._bindings;
      for (var i = this._targetGroup.nCachedObjects_,
          n = bindings.length; i !== n; ++i) {
        bindings[i].bind();
      }
    },
    unbind: function() {
      var bindings = this._bindings;
      for (var i = this._targetGroup.nCachedObjects_,
          n = bindings.length; i !== n; ++i) {
        bindings[i].unbind();
      }
    }
  });
  function PropertyBinding(rootNode, path, parsedPath) {
    this.path = path;
    this.parsedPath = parsedPath || PropertyBinding.parseTrackName(path);
    this.node = PropertyBinding.findNode(rootNode, this.parsedPath.nodeName) || rootNode;
    this.rootNode = rootNode;
  }
  Object.assign(PropertyBinding, {
    Composite: Composite,
    create: function(root, path, parsedPath) {
      if (!(root && root.isAnimationObjectGroup)) {
        return new PropertyBinding(root, path, parsedPath);
      } else {
        return new PropertyBinding.Composite(root, path, parsedPath);
      }
    },
    sanitizeNodeName: function(name) {
      return name.replace(/\s/g, '_').replace(/[^\w-]/g, '');
    },
    parseTrackName: function() {
      var directoryRe = /((?:[\w-]+[\/:])*)/;
      var nodeRe = /([\w-\.]+)?/;
      var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/;
      var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/;
      var trackRe = new RegExp('' + '^' + directoryRe.source + nodeRe.source + objectRe.source + propertyRe.source + '$');
      var supportedObjectNames = ['material', 'materials', 'bones'];
      return function(trackName) {
        var matches = trackRe.exec(trackName);
        if (!matches) {
          throw new Error('PropertyBinding: Cannot parse trackName: ' + trackName);
        }
        var results = {
          nodeName: matches[2],
          objectName: matches[3],
          objectIndex: matches[4],
          propertyName: matches[5],
          propertyIndex: matches[6]
        };
        var lastDot = results.nodeName && results.nodeName.lastIndexOf('.');
        if (lastDot !== undefined && lastDot !== -1) {
          var objectName = results.nodeName.substring(lastDot + 1);
          if (supportedObjectNames.indexOf(objectName) !== -1) {
            results.nodeName = results.nodeName.substring(0, lastDot);
            results.objectName = objectName;
          }
        }
        if (results.propertyName === null || results.propertyName.length === 0) {
          throw new Error('PropertyBinding: can not parse propertyName from trackName: ' + trackName);
        }
        return results;
      };
    }(),
    findNode: function(root, nodeName) {
      if (!nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === -1 || nodeName === root.name || nodeName === root.uuid) {
        return root;
      }
      if (root.skeleton) {
        var searchSkeleton = function(skeleton) {
          for (var i = 0; i < skeleton.bones.length; i++) {
            var bone = skeleton.bones[i];
            if (bone.name === nodeName) {
              return bone;
            }
          }
          return null;
        };
        var bone = searchSkeleton(root.skeleton);
        if (bone) {
          return bone;
        }
      }
      if (root.children) {
        var searchNodeSubtree = function(children) {
          for (var i = 0; i < children.length; i++) {
            var childNode = children[i];
            if (childNode.name === nodeName || childNode.uuid === nodeName) {
              return childNode;
            }
            var result = searchNodeSubtree(childNode.children);
            if (result)
              return result;
          }
          return null;
        };
        var subTreeNode = searchNodeSubtree(root.children);
        if (subTreeNode) {
          return subTreeNode;
        }
      }
      return null;
    }
  });
  Object.assign(PropertyBinding.prototype, {
    _getValue_unavailable: function() {},
    _setValue_unavailable: function() {},
    BindingType: {
      Direct: 0,
      EntireArray: 1,
      ArrayElement: 2,
      HasFromToArray: 3
    },
    Versioning: {
      None: 0,
      NeedsUpdate: 1,
      MatrixWorldNeedsUpdate: 2
    },
    GetterByBindingType: [function getValue_direct(buffer, offset) {
      buffer[offset] = this.node[this.propertyName];
    }, function getValue_array(buffer, offset) {
      var source = this.resolvedProperty;
      for (var i = 0,
          n = source.length; i !== n; ++i) {
        buffer[offset++] = source[i];
      }
    }, function getValue_arrayElement(buffer, offset) {
      buffer[offset] = this.resolvedProperty[this.propertyIndex];
    }, function getValue_toArray(buffer, offset) {
      this.resolvedProperty.toArray(buffer, offset);
    }],
    SetterByBindingTypeAndVersioning: [[function setValue_direct(buffer, offset) {
      this.targetObject[this.propertyName] = buffer[offset];
    }, function setValue_direct_setNeedsUpdate(buffer, offset) {
      this.targetObject[this.propertyName] = buffer[offset];
      this.targetObject.needsUpdate = true;
    }, function setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) {
      this.targetObject[this.propertyName] = buffer[offset];
      this.targetObject.matrixWorldNeedsUpdate = true;
    }], [function setValue_array(buffer, offset) {
      var dest = this.resolvedProperty;
      for (var i = 0,
          n = dest.length; i !== n; ++i) {
        dest[i] = buffer[offset++];
      }
    }, function setValue_array_setNeedsUpdate(buffer, offset) {
      var dest = this.resolvedProperty;
      for (var i = 0,
          n = dest.length; i !== n; ++i) {
        dest[i] = buffer[offset++];
      }
      this.targetObject.needsUpdate = true;
    }, function setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) {
      var dest = this.resolvedProperty;
      for (var i = 0,
          n = dest.length; i !== n; ++i) {
        dest[i] = buffer[offset++];
      }
      this.targetObject.matrixWorldNeedsUpdate = true;
    }], [function setValue_arrayElement(buffer, offset) {
      this.resolvedProperty[this.propertyIndex] = buffer[offset];
    }, function setValue_arrayElement_setNeedsUpdate(buffer, offset) {
      this.resolvedProperty[this.propertyIndex] = buffer[offset];
      this.targetObject.needsUpdate = true;
    }, function setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) {
      this.resolvedProperty[this.propertyIndex] = buffer[offset];
      this.targetObject.matrixWorldNeedsUpdate = true;
    }], [function setValue_fromArray(buffer, offset) {
      this.resolvedProperty.fromArray(buffer, offset);
    }, function setValue_fromArray_setNeedsUpdate(buffer, offset) {
      this.resolvedProperty.fromArray(buffer, offset);
      this.targetObject.needsUpdate = true;
    }, function setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) {
      this.resolvedProperty.fromArray(buffer, offset);
      this.targetObject.matrixWorldNeedsUpdate = true;
    }]],
    getValue: function getValue_unbound(targetArray, offset) {
      this.bind();
      this.getValue(targetArray, offset);
    },
    setValue: function getValue_unbound(sourceArray, offset) {
      this.bind();
      this.setValue(sourceArray, offset);
    },
    bind: function() {
      var targetObject = this.node,
          parsedPath = this.parsedPath,
          objectName = parsedPath.objectName,
          propertyName = parsedPath.propertyName,
          propertyIndex = parsedPath.propertyIndex;
      if (!targetObject) {
        targetObject = PropertyBinding.findNode(this.rootNode, parsedPath.nodeName) || this.rootNode;
        this.node = targetObject;
      }
      this.getValue = this._getValue_unavailable;
      this.setValue = this._setValue_unavailable;
      if (!targetObject) {
        console.error('THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.');
        return;
      }
      if (objectName) {
        var objectIndex = parsedPath.objectIndex;
        switch (objectName) {
          case 'materials':
            if (!targetObject.material) {
              console.error('THREE.PropertyBinding: Can not bind to material as node does not have a material.', this);
              return;
            }
            if (!targetObject.material.materials) {
              console.error('THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this);
              return;
            }
            targetObject = targetObject.material.materials;
            break;
          case 'bones':
            if (!targetObject.skeleton) {
              console.error('THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this);
              return;
            }
            targetObject = targetObject.skeleton.bones;
            for (var i = 0; i < targetObject.length; i++) {
              if (targetObject[i].name === objectIndex) {
                objectIndex = i;
                break;
              }
            }
            break;
          default:
            if (targetObject[objectName] === undefined) {
              console.error('THREE.PropertyBinding: Can not bind to objectName of node undefined.', this);
              return;
            }
            targetObject = targetObject[objectName];
        }
        if (objectIndex !== undefined) {
          if (targetObject[objectIndex] === undefined) {
            console.error('THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject);
            return;
          }
          targetObject = targetObject[objectIndex];
        }
      }
      var nodeProperty = targetObject[propertyName];
      if (nodeProperty === undefined) {
        var nodeName = parsedPath.nodeName;
        console.error('THREE.PropertyBinding: Trying to update property for track: ' + nodeName + '.' + propertyName + ' but it wasn\'t found.', targetObject);
        return;
      }
      var versioning = this.Versioning.None;
      if (targetObject.needsUpdate !== undefined) {
        versioning = this.Versioning.NeedsUpdate;
        this.targetObject = targetObject;
      } else if (targetObject.matrixWorldNeedsUpdate !== undefined) {
        versioning = this.Versioning.MatrixWorldNeedsUpdate;
        this.targetObject = targetObject;
      }
      var bindingType = this.BindingType.Direct;
      if (propertyIndex !== undefined) {
        if (propertyName === "morphTargetInfluences") {
          if (!targetObject.geometry) {
            console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this);
            return;
          }
          if (targetObject.geometry.isBufferGeometry) {
            if (!targetObject.geometry.morphAttributes) {
              console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this);
              return;
            }
            for (var i = 0; i < this.node.geometry.morphAttributes.position.length; i++) {
              if (targetObject.geometry.morphAttributes.position[i].name === propertyIndex) {
                propertyIndex = i;
                break;
              }
            }
          } else {
            if (!targetObject.geometry.morphTargets) {
              console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this);
              return;
            }
            for (var i = 0; i < this.node.geometry.morphTargets.length; i++) {
              if (targetObject.geometry.morphTargets[i].name === propertyIndex) {
                propertyIndex = i;
                break;
              }
            }
          }
        }
        bindingType = this.BindingType.ArrayElement;
        this.resolvedProperty = nodeProperty;
        this.propertyIndex = propertyIndex;
      } else if (nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined) {
        bindingType = this.BindingType.HasFromToArray;
        this.resolvedProperty = nodeProperty;
      } else if (Array.isArray(nodeProperty)) {
        bindingType = this.BindingType.EntireArray;
        this.resolvedProperty = nodeProperty;
      } else {
        this.propertyName = propertyName;
      }
      this.getValue = this.GetterByBindingType[bindingType];
      this.setValue = this.SetterByBindingTypeAndVersioning[bindingType][versioning];
    },
    unbind: function() {
      this.node = null;
      this.getValue = this._getValue_unbound;
      this.setValue = this._setValue_unbound;
    }
  });
  Object.assign(PropertyBinding.prototype, {
    _getValue_unbound: PropertyBinding.prototype.getValue,
    _setValue_unbound: PropertyBinding.prototype.setValue
  });
  function AnimationObjectGroup() {
    this.uuid = _Math.generateUUID();
    this._objects = Array.prototype.slice.call(arguments);
    this.nCachedObjects_ = 0;
    var indices = {};
    this._indicesByUUID = indices;
    for (var i = 0,
        n = arguments.length; i !== n; ++i) {
      indices[arguments[i].uuid] = i;
    }
    this._paths = [];
    this._parsedPaths = [];
    this._bindings = [];
    this._bindingsIndicesByPath = {};
    var scope = this;
    this.stats = {
      objects: {
        get total() {
          return scope._objects.length;
        },
        get inUse() {
          return this.total - scope.nCachedObjects_;
        }
      },
      get bindingsPerObject() {
        return scope._bindings.length;
      }
    };
  }
  Object.assign(AnimationObjectGroup.prototype, {
    isAnimationObjectGroup: true,
    add: function() {
      var objects = this._objects,
          nObjects = objects.length,
          nCachedObjects = this.nCachedObjects_,
          indicesByUUID = this._indicesByUUID,
          paths = this._paths,
          parsedPaths = this._parsedPaths,
          bindings = this._bindings,
          nBindings = bindings.length;
      for (var i = 0,
          n = arguments.length; i !== n; ++i) {
        var object = arguments[i],
            uuid = object.uuid,
            index = indicesByUUID[uuid],
            knownObject = undefined;
        if (index === undefined) {
          index = nObjects++;
          indicesByUUID[uuid] = index;
          objects.push(object);
          for (var j = 0,
              m = nBindings; j !== m; ++j) {
            bindings[j].push(new PropertyBinding(object, paths[j], parsedPaths[j]));
          }
        } else if (index < nCachedObjects) {
          knownObject = objects[index];
          var firstActiveIndex = --nCachedObjects,
              lastCachedObject = objects[firstActiveIndex];
          indicesByUUID[lastCachedObject.uuid] = index;
          objects[index] = lastCachedObject;
          indicesByUUID[uuid] = firstActiveIndex;
          objects[firstActiveIndex] = object;
          for (var j = 0,
              m = nBindings; j !== m; ++j) {
            var bindingsForPath = bindings[j],
                lastCached = bindingsForPath[firstActiveIndex],
                binding = bindingsForPath[index];
            bindingsForPath[index] = lastCached;
            if (binding === undefined) {
              binding = new PropertyBinding(object, paths[j], parsedPaths[j]);
            }
            bindingsForPath[firstActiveIndex] = binding;
          }
        } else if (objects[index] !== knownObject) {
          console.error('THREE.AnimationObjectGroup: Different objects with the same UUID ' + 'detected. Clean the caches or recreate your infrastructure when reloading scenes.');
        }
      }
      this.nCachedObjects_ = nCachedObjects;
    },
    remove: function() {
      var objects = this._objects,
          nCachedObjects = this.nCachedObjects_,
          indicesByUUID = this._indicesByUUID,
          bindings = this._bindings,
          nBindings = bindings.length;
      for (var i = 0,
          n = arguments.length; i !== n; ++i) {
        var object = arguments[i],
            uuid = object.uuid,
            index = indicesByUUID[uuid];
        if (index !== undefined && index >= nCachedObjects) {
          var lastCachedIndex = nCachedObjects++,
              firstActiveObject = objects[lastCachedIndex];
          indicesByUUID[firstActiveObject.uuid] = index;
          objects[index] = firstActiveObject;
          indicesByUUID[uuid] = lastCachedIndex;
          objects[lastCachedIndex] = object;
          for (var j = 0,
              m = nBindings; j !== m; ++j) {
            var bindingsForPath = bindings[j],
                firstActive = bindingsForPath[lastCachedIndex],
                binding = bindingsForPath[index];
            bindingsForPath[index] = firstActive;
            bindingsForPath[lastCachedIndex] = binding;
          }
        }
      }
      this.nCachedObjects_ = nCachedObjects;
    },
    uncache: function() {
      var objects = this._objects,
          nObjects = objects.length,
          nCachedObjects = this.nCachedObjects_,
          indicesByUUID = this._indicesByUUID,
          bindings = this._bindings,
          nBindings = bindings.length;
      for (var i = 0,
          n = arguments.length; i !== n; ++i) {
        var object = arguments[i],
            uuid = object.uuid,
            index = indicesByUUID[uuid];
        if (index !== undefined) {
          delete indicesByUUID[uuid];
          if (index < nCachedObjects) {
            var firstActiveIndex = --nCachedObjects,
                lastCachedObject = objects[firstActiveIndex],
                lastIndex = --nObjects,
                lastObject = objects[lastIndex];
            indicesByUUID[lastCachedObject.uuid] = index;
            objects[index] = lastCachedObject;
            indicesByUUID[lastObject.uuid] = firstActiveIndex;
            objects[firstActiveIndex] = lastObject;
            objects.pop();
            for (var j = 0,
                m = nBindings; j !== m; ++j) {
              var bindingsForPath = bindings[j],
                  lastCached = bindingsForPath[firstActiveIndex],
                  last = bindingsForPath[lastIndex];
              bindingsForPath[index] = lastCached;
              bindingsForPath[firstActiveIndex] = last;
              bindingsForPath.pop();
            }
          } else {
            var lastIndex = --nObjects,
                lastObject = objects[lastIndex];
            indicesByUUID[lastObject.uuid] = index;
            objects[index] = lastObject;
            objects.pop();
            for (var j = 0,
                m = nBindings; j !== m; ++j) {
              var bindingsForPath = bindings[j];
              bindingsForPath[index] = bindingsForPath[lastIndex];
              bindingsForPath.pop();
            }
          }
        }
      }
      this.nCachedObjects_ = nCachedObjects;
    },
    subscribe_: function(path, parsedPath) {
      var indicesByPath = this._bindingsIndicesByPath,
          index = indicesByPath[path],
          bindings = this._bindings;
      if (index !== undefined)
        return bindings[index];
      var paths = this._paths,
          parsedPaths = this._parsedPaths,
          objects = this._objects,
          nObjects = objects.length,
          nCachedObjects = this.nCachedObjects_,
          bindingsForPath = new Array(nObjects);
      index = bindings.length;
      indicesByPath[path] = index;
      paths.push(path);
      parsedPaths.push(parsedPath);
      bindings.push(bindingsForPath);
      for (var i = nCachedObjects,
          n = objects.length; i !== n; ++i) {
        var object = objects[i];
        bindingsForPath[i] = new PropertyBinding(object, path, parsedPath);
      }
      return bindingsForPath;
    },
    unsubscribe_: function(path) {
      var indicesByPath = this._bindingsIndicesByPath,
          index = indicesByPath[path];
      if (index !== undefined) {
        var paths = this._paths,
            parsedPaths = this._parsedPaths,
            bindings = this._bindings,
            lastBindingsIndex = bindings.length - 1,
            lastBindings = bindings[lastBindingsIndex],
            lastBindingsPath = path[lastBindingsIndex];
        indicesByPath[lastBindingsPath] = index;
        bindings[index] = lastBindings;
        bindings.pop();
        parsedPaths[index] = parsedPaths[lastBindingsIndex];
        parsedPaths.pop();
        paths[index] = paths[lastBindingsIndex];
        paths.pop();
      }
    }
  });
  function AnimationAction(mixer, clip, localRoot) {
    this._mixer = mixer;
    this._clip = clip;
    this._localRoot = localRoot || null;
    var tracks = clip.tracks,
        nTracks = tracks.length,
        interpolants = new Array(nTracks);
    var interpolantSettings = {
      endingStart: ZeroCurvatureEnding,
      endingEnd: ZeroCurvatureEnding
    };
    for (var i = 0; i !== nTracks; ++i) {
      var interpolant = tracks[i].createInterpolant(null);
      interpolants[i] = interpolant;
      interpolant.settings = interpolantSettings;
    }
    this._interpolantSettings = interpolantSettings;
    this._interpolants = interpolants;
    this._propertyBindings = new Array(nTracks);
    this._cacheIndex = null;
    this._byClipCacheIndex = null;
    this._timeScaleInterpolant = null;
    this._weightInterpolant = null;
    this.loop = LoopRepeat;
    this._loopCount = -1;
    this._startTime = null;
    this.time = 0;
    this.timeScale = 1;
    this._effectiveTimeScale = 1;
    this.weight = 1;
    this._effectiveWeight = 1;
    this.repetitions = Infinity;
    this.paused = false;
    this.enabled = true;
    this.clampWhenFinished = false;
    this.zeroSlopeAtStart = true;
    this.zeroSlopeAtEnd = true;
  }
  Object.assign(AnimationAction.prototype, {
    play: function() {
      this._mixer._activateAction(this);
      return this;
    },
    stop: function() {
      this._mixer._deactivateAction(this);
      return this.reset();
    },
    reset: function() {
      this.paused = false;
      this.enabled = true;
      this.time = 0;
      this._loopCount = -1;
      this._startTime = null;
      return this.stopFading().stopWarping();
    },
    isRunning: function() {
      return this.enabled && !this.paused && this.timeScale !== 0 && this._startTime === null && this._mixer._isActiveAction(this);
    },
    isScheduled: function() {
      return this._mixer._isActiveAction(this);
    },
    startAt: function(time) {
      this._startTime = time;
      return this;
    },
    setLoop: function(mode, repetitions) {
      this.loop = mode;
      this.repetitions = repetitions;
      return this;
    },
    setEffectiveWeight: function(weight) {
      this.weight = weight;
      this._effectiveWeight = this.enabled ? weight : 0;
      return this.stopFading();
    },
    getEffectiveWeight: function() {
      return this._effectiveWeight;
    },
    fadeIn: function(duration) {
      return this._scheduleFading(duration, 0, 1);
    },
    fadeOut: function(duration) {
      return this._scheduleFading(duration, 1, 0);
    },
    crossFadeFrom: function(fadeOutAction, duration, warp) {
      fadeOutAction.fadeOut(duration);
      this.fadeIn(duration);
      if (warp) {
        var fadeInDuration = this._clip.duration,
            fadeOutDuration = fadeOutAction._clip.duration,
            startEndRatio = fadeOutDuration / fadeInDuration,
            endStartRatio = fadeInDuration / fadeOutDuration;
        fadeOutAction.warp(1.0, startEndRatio, duration);
        this.warp(endStartRatio, 1.0, duration);
      }
      return this;
    },
    crossFadeTo: function(fadeInAction, duration, warp) {
      return fadeInAction.crossFadeFrom(this, duration, warp);
    },
    stopFading: function() {
      var weightInterpolant = this._weightInterpolant;
      if (weightInterpolant !== null) {
        this._weightInterpolant = null;
        this._mixer._takeBackControlInterpolant(weightInterpolant);
      }
      return this;
    },
    setEffectiveTimeScale: function(timeScale) {
      this.timeScale = timeScale;
      this._effectiveTimeScale = this.paused ? 0 : timeScale;
      return this.stopWarping();
    },
    getEffectiveTimeScale: function() {
      return this._effectiveTimeScale;
    },
    setDuration: function(duration) {
      this.timeScale = this._clip.duration / duration;
      return this.stopWarping();
    },
    syncWith: function(action) {
      this.time = action.time;
      this.timeScale = action.timeScale;
      return this.stopWarping();
    },
    halt: function(duration) {
      return this.warp(this._effectiveTimeScale, 0, duration);
    },
    warp: function(startTimeScale, endTimeScale, duration) {
      var mixer = this._mixer,
          now = mixer.time,
          interpolant = this._timeScaleInterpolant,
          timeScale = this.timeScale;
      if (interpolant === null) {
        interpolant = mixer._lendControlInterpolant();
        this._timeScaleInterpolant = interpolant;
      }
      var times = interpolant.parameterPositions,
          values = interpolant.sampleValues;
      times[0] = now;
      times[1] = now + duration;
      values[0] = startTimeScale / timeScale;
      values[1] = endTimeScale / timeScale;
      return this;
    },
    stopWarping: function() {
      var timeScaleInterpolant = this._timeScaleInterpolant;
      if (timeScaleInterpolant !== null) {
        this._timeScaleInterpolant = null;
        this._mixer._takeBackControlInterpolant(timeScaleInterpolant);
      }
      return this;
    },
    getMixer: function() {
      return this._mixer;
    },
    getClip: function() {
      return this._clip;
    },
    getRoot: function() {
      return this._localRoot || this._mixer._root;
    },
    _update: function(time, deltaTime, timeDirection, accuIndex) {
      if (!this.enabled) {
        this._updateWeight(time);
        return;
      }
      var startTime = this._startTime;
      if (startTime !== null) {
        var timeRunning = (time - startTime) * timeDirection;
        if (timeRunning < 0 || timeDirection === 0) {
          return;
        }
        this._startTime = null;
        deltaTime = timeDirection * timeRunning;
      }
      deltaTime *= this._updateTimeScale(time);
      var clipTime = this._updateTime(deltaTime);
      var weight = this._updateWeight(time);
      if (weight > 0) {
        var interpolants = this._interpolants;
        var propertyMixers = this._propertyBindings;
        for (var j = 0,
            m = interpolants.length; j !== m; ++j) {
          interpolants[j].evaluate(clipTime);
          propertyMixers[j].accumulate(accuIndex, weight);
        }
      }
    },
    _updateWeight: function(time) {
      var weight = 0;
      if (this.enabled) {
        weight = this.weight;
        var interpolant = this._weightInterpolant;
        if (interpolant !== null) {
          var interpolantValue = interpolant.evaluate(time)[0];
          weight *= interpolantValue;
          if (time > interpolant.parameterPositions[1]) {
            this.stopFading();
            if (interpolantValue === 0) {
              this.enabled = false;
            }
          }
        }
      }
      this._effectiveWeight = weight;
      return weight;
    },
    _updateTimeScale: function(time) {
      var timeScale = 0;
      if (!this.paused) {
        timeScale = this.timeScale;
        var interpolant = this._timeScaleInterpolant;
        if (interpolant !== null) {
          var interpolantValue = interpolant.evaluate(time)[0];
          timeScale *= interpolantValue;
          if (time > interpolant.parameterPositions[1]) {
            this.stopWarping();
            if (timeScale === 0) {
              this.paused = true;
            } else {
              this.timeScale = timeScale;
            }
          }
        }
      }
      this._effectiveTimeScale = timeScale;
      return timeScale;
    },
    _updateTime: function(deltaTime) {
      var time = this.time + deltaTime;
      if (deltaTime === 0)
        return time;
      var duration = this._clip.duration,
          loop = this.loop,
          loopCount = this._loopCount;
      if (loop === LoopOnce) {
        if (loopCount === -1) {
          this._loopCount = 0;
          this._setEndings(true, true, false);
        }
        handle_stop: {
          if (time >= duration) {
            time = duration;
          } else if (time < 0) {
            time = 0;
          } else
            break handle_stop;
          if (this.clampWhenFinished)
            this.paused = true;
          else
            this.enabled = false;
          this._mixer.dispatchEvent({
            type: 'finished',
            action: this,
            direction: deltaTime < 0 ? -1 : 1
          });
        }
      } else {
        var pingPong = (loop === LoopPingPong);
        if (loopCount === -1) {
          if (deltaTime >= 0) {
            loopCount = 0;
            this._setEndings(true, this.repetitions === 0, pingPong);
          } else {
            this._setEndings(this.repetitions === 0, true, pingPong);
          }
        }
        if (time >= duration || time < 0) {
          var loopDelta = Math.floor(time / duration);
          time -= duration * loopDelta;
          loopCount += Math.abs(loopDelta);
          var pending = this.repetitions - loopCount;
          if (pending < 0) {
            if (this.clampWhenFinished)
              this.paused = true;
            else
              this.enabled = false;
            time = deltaTime > 0 ? duration : 0;
            this._mixer.dispatchEvent({
              type: 'finished',
              action: this,
              direction: deltaTime > 0 ? 1 : -1
            });
          } else {
            if (pending === 0) {
              var atStart = deltaTime < 0;
              this._setEndings(atStart, !atStart, pingPong);
            } else {
              this._setEndings(false, false, pingPong);
            }
            this._loopCount = loopCount;
            this._mixer.dispatchEvent({
              type: 'loop',
              action: this,
              loopDelta: loopDelta
            });
          }
        }
        if (pingPong && (loopCount & 1) === 1) {
          this.time = time;
          return duration - time;
        }
      }
      this.time = time;
      return time;
    },
    _setEndings: function(atStart, atEnd, pingPong) {
      var settings = this._interpolantSettings;
      if (pingPong) {
        settings.endingStart = ZeroSlopeEnding;
        settings.endingEnd = ZeroSlopeEnding;
      } else {
        if (atStart) {
          settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
        } else {
          settings.endingStart = WrapAroundEnding;
        }
        if (atEnd) {
          settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
        } else {
          settings.endingEnd = WrapAroundEnding;
        }
      }
    },
    _scheduleFading: function(duration, weightNow, weightThen) {
      var mixer = this._mixer,
          now = mixer.time,
          interpolant = this._weightInterpolant;
      if (interpolant === null) {
        interpolant = mixer._lendControlInterpolant();
        this._weightInterpolant = interpolant;
      }
      var times = interpolant.parameterPositions,
          values = interpolant.sampleValues;
      times[0] = now;
      values[0] = weightNow;
      times[1] = now + duration;
      values[1] = weightThen;
      return this;
    }
  });
  function AnimationMixer(root) {
    this._root = root;
    this._initMemoryManager();
    this._accuIndex = 0;
    this.time = 0;
    this.timeScale = 1.0;
  }
  Object.assign(AnimationMixer.prototype, EventDispatcher.prototype, {
    _bindAction: function(action, prototypeAction) {
      var root = action._localRoot || this._root,
          tracks = action._clip.tracks,
          nTracks = tracks.length,
          bindings = action._propertyBindings,
          interpolants = action._interpolants,
          rootUuid = root.uuid,
          bindingsByRoot = this._bindingsByRootAndName,
          bindingsByName = bindingsByRoot[rootUuid];
      if (bindingsByName === undefined) {
        bindingsByName = {};
        bindingsByRoot[rootUuid] = bindingsByName;
      }
      for (var i = 0; i !== nTracks; ++i) {
        var track = tracks[i],
            trackName = track.name,
            binding = bindingsByName[trackName];
        if (binding !== undefined) {
          bindings[i] = binding;
        } else {
          binding = bindings[i];
          if (binding !== undefined) {
            if (binding._cacheIndex === null) {
              ++binding.referenceCount;
              this._addInactiveBinding(binding, rootUuid, trackName);
            }
            continue;
          }
          var path = prototypeAction && prototypeAction._propertyBindings[i].binding.parsedPath;
          binding = new PropertyMixer(PropertyBinding.create(root, trackName, path), track.ValueTypeName, track.getValueSize());
          ++binding.referenceCount;
          this._addInactiveBinding(binding, rootUuid, trackName);
          bindings[i] = binding;
        }
        interpolants[i].resultBuffer = binding.buffer;
      }
    },
    _activateAction: function(action) {
      if (!this._isActiveAction(action)) {
        if (action._cacheIndex === null) {
          var rootUuid = (action._localRoot || this._root).uuid,
              clipUuid = action._clip.uuid,
              actionsForClip = this._actionsByClip[clipUuid];
          this._bindAction(action, actionsForClip && actionsForClip.knownActions[0]);
          this._addInactiveAction(action, clipUuid, rootUuid);
        }
        var bindings = action._propertyBindings;
        for (var i = 0,
            n = bindings.length; i !== n; ++i) {
          var binding = bindings[i];
          if (binding.useCount++ === 0) {
            this._lendBinding(binding);
            binding.saveOriginalState();
          }
        }
        this._lendAction(action);
      }
    },
    _deactivateAction: function(action) {
      if (this._isActiveAction(action)) {
        var bindings = action._propertyBindings;
        for (var i = 0,
            n = bindings.length; i !== n; ++i) {
          var binding = bindings[i];
          if (--binding.useCount === 0) {
            binding.restoreOriginalState();
            this._takeBackBinding(binding);
          }
        }
        this._takeBackAction(action);
      }
    },
    _initMemoryManager: function() {
      this._actions = [];
      this._nActiveActions = 0;
      this._actionsByClip = {};
      this._bindings = [];
      this._nActiveBindings = 0;
      this._bindingsByRootAndName = {};
      this._controlInterpolants = [];
      this._nActiveControlInterpolants = 0;
      var scope = this;
      this.stats = {
        actions: {
          get total() {
            return scope._actions.length;
          },
          get inUse() {
            return scope._nActiveActions;
          }
        },
        bindings: {
          get total() {
            return scope._bindings.length;
          },
          get inUse() {
            return scope._nActiveBindings;
          }
        },
        controlInterpolants: {
          get total() {
            return scope._controlInterpolants.length;
          },
          get inUse() {
            return scope._nActiveControlInterpolants;
          }
        }
      };
    },
    _isActiveAction: function(action) {
      var index = action._cacheIndex;
      return index !== null && index < this._nActiveActions;
    },
    _addInactiveAction: function(action, clipUuid, rootUuid) {
      var actions = this._actions,
          actionsByClip = this._actionsByClip,
          actionsForClip = actionsByClip[clipUuid];
      if (actionsForClip === undefined) {
        actionsForClip = {
          knownActions: [action],
          actionByRoot: {}
        };
        action._byClipCacheIndex = 0;
        actionsByClip[clipUuid] = actionsForClip;
      } else {
        var knownActions = actionsForClip.knownActions;
        action._byClipCacheIndex = knownActions.length;
        knownActions.push(action);
      }
      action._cacheIndex = actions.length;
      actions.push(action);
      actionsForClip.actionByRoot[rootUuid] = action;
    },
    _removeInactiveAction: function(action) {
      var actions = this._actions,
          lastInactiveAction = actions[actions.length - 1],
          cacheIndex = action._cacheIndex;
      lastInactiveAction._cacheIndex = cacheIndex;
      actions[cacheIndex] = lastInactiveAction;
      actions.pop();
      action._cacheIndex = null;
      var clipUuid = action._clip.uuid,
          actionsByClip = this._actionsByClip,
          actionsForClip = actionsByClip[clipUuid],
          knownActionsForClip = actionsForClip.knownActions,
          lastKnownAction = knownActionsForClip[knownActionsForClip.length - 1],
          byClipCacheIndex = action._byClipCacheIndex;
      lastKnownAction._byClipCacheIndex = byClipCacheIndex;
      knownActionsForClip[byClipCacheIndex] = lastKnownAction;
      knownActionsForClip.pop();
      action._byClipCacheIndex = null;
      var actionByRoot = actionsForClip.actionByRoot,
          rootUuid = (action._localRoot || this._root).uuid;
      delete actionByRoot[rootUuid];
      if (knownActionsForClip.length === 0) {
        delete actionsByClip[clipUuid];
      }
      this._removeInactiveBindingsForAction(action);
    },
    _removeInactiveBindingsForAction: function(action) {
      var bindings = action._propertyBindings;
      for (var i = 0,
          n = bindings.length; i !== n; ++i) {
        var binding = bindings[i];
        if (--binding.referenceCount === 0) {
          this._removeInactiveBinding(binding);
        }
      }
    },
    _lendAction: function(action) {
      var actions = this._actions,
          prevIndex = action._cacheIndex,
          lastActiveIndex = this._nActiveActions++,
          firstInactiveAction = actions[lastActiveIndex];
      action._cacheIndex = lastActiveIndex;
      actions[lastActiveIndex] = action;
      firstInactiveAction._cacheIndex = prevIndex;
      actions[prevIndex] = firstInactiveAction;
    },
    _takeBackAction: function(action) {
      var actions = this._actions,
          prevIndex = action._cacheIndex,
          firstInactiveIndex = --this._nActiveActions,
          lastActiveAction = actions[firstInactiveIndex];
      action._cacheIndex = firstInactiveIndex;
      actions[firstInactiveIndex] = action;
      lastActiveAction._cacheIndex = prevIndex;
      actions[prevIndex] = lastActiveAction;
    },
    _addInactiveBinding: function(binding, rootUuid, trackName) {
      var bindingsByRoot = this._bindingsByRootAndName,
          bindingByName = bindingsByRoot[rootUuid],
          bindings = this._bindings;
      if (bindingByName === undefined) {
        bindingByName = {};
        bindingsByRoot[rootUuid] = bindingByName;
      }
      bindingByName[trackName] = binding;
      binding._cacheIndex = bindings.length;
      bindings.push(binding);
    },
    _removeInactiveBinding: function(binding) {
      var bindings = this._bindings,
          propBinding = binding.binding,
          rootUuid = propBinding.rootNode.uuid,
          trackName = propBinding.path,
          bindingsByRoot = this._bindingsByRootAndName,
          bindingByName = bindingsByRoot[rootUuid],
          lastInactiveBinding = bindings[bindings.length - 1],
          cacheIndex = binding._cacheIndex;
      lastInactiveBinding._cacheIndex = cacheIndex;
      bindings[cacheIndex] = lastInactiveBinding;
      bindings.pop();
      delete bindingByName[trackName];
      remove_empty_map: {
        for (var _ in bindingByName)
          break remove_empty_map;
        delete bindingsByRoot[rootUuid];
      }
    },
    _lendBinding: function(binding) {
      var bindings = this._bindings,
          prevIndex = binding._cacheIndex,
          lastActiveIndex = this._nActiveBindings++,
          firstInactiveBinding = bindings[lastActiveIndex];
      binding._cacheIndex = lastActiveIndex;
      bindings[lastActiveIndex] = binding;
      firstInactiveBinding._cacheIndex = prevIndex;
      bindings[prevIndex] = firstInactiveBinding;
    },
    _takeBackBinding: function(binding) {
      var bindings = this._bindings,
          prevIndex = binding._cacheIndex,
          firstInactiveIndex = --this._nActiveBindings,
          lastActiveBinding = bindings[firstInactiveIndex];
      binding._cacheIndex = firstInactiveIndex;
      bindings[firstInactiveIndex] = binding;
      lastActiveBinding._cacheIndex = prevIndex;
      bindings[prevIndex] = lastActiveBinding;
    },
    _lendControlInterpolant: function() {
      var interpolants = this._controlInterpolants,
          lastActiveIndex = this._nActiveControlInterpolants++,
          interpolant = interpolants[lastActiveIndex];
      if (interpolant === undefined) {
        interpolant = new LinearInterpolant(new Float32Array(2), new Float32Array(2), 1, this._controlInterpolantsResultBuffer);
        interpolant.__cacheIndex = lastActiveIndex;
        interpolants[lastActiveIndex] = interpolant;
      }
      return interpolant;
    },
    _takeBackControlInterpolant: function(interpolant) {
      var interpolants = this._controlInterpolants,
          prevIndex = interpolant.__cacheIndex,
          firstInactiveIndex = --this._nActiveControlInterpolants,
          lastActiveInterpolant = interpolants[firstInactiveIndex];
      interpolant.__cacheIndex = firstInactiveIndex;
      interpolants[firstInactiveIndex] = interpolant;
      lastActiveInterpolant.__cacheIndex = prevIndex;
      interpolants[prevIndex] = lastActiveInterpolant;
    },
    _controlInterpolantsResultBuffer: new Float32Array(1),
    clipAction: function(clip, optionalRoot) {
      var root = optionalRoot || this._root,
          rootUuid = root.uuid,
          clipObject = typeof clip === 'string' ? AnimationClip.findByName(root, clip) : clip,
          clipUuid = clipObject !== null ? clipObject.uuid : clip,
          actionsForClip = this._actionsByClip[clipUuid],
          prototypeAction = null;
      if (actionsForClip !== undefined) {
        var existingAction = actionsForClip.actionByRoot[rootUuid];
        if (existingAction !== undefined) {
          return existingAction;
        }
        prototypeAction = actionsForClip.knownActions[0];
        if (clipObject === null)
          clipObject = prototypeAction._clip;
      }
      if (clipObject === null)
        return null;
      var newAction = new AnimationAction(this, clipObject, optionalRoot);
      this._bindAction(newAction, prototypeAction);
      this._addInactiveAction(newAction, clipUuid, rootUuid);
      return newAction;
    },
    existingAction: function(clip, optionalRoot) {
      var root = optionalRoot || this._root,
          rootUuid = root.uuid,
          clipObject = typeof clip === 'string' ? AnimationClip.findByName(root, clip) : clip,
          clipUuid = clipObject ? clipObject.uuid : clip,
          actionsForClip = this._actionsByClip[clipUuid];
      if (actionsForClip !== undefined) {
        return actionsForClip.actionByRoot[rootUuid] || null;
      }
      return null;
    },
    stopAllAction: function() {
      var actions = this._actions,
          nActions = this._nActiveActions,
          bindings = this._bindings,
          nBindings = this._nActiveBindings;
      this._nActiveActions = 0;
      this._nActiveBindings = 0;
      for (var i = 0; i !== nActions; ++i) {
        actions[i].reset();
      }
      for (var i = 0; i !== nBindings; ++i) {
        bindings[i].useCount = 0;
      }
      return this;
    },
    update: function(deltaTime) {
      deltaTime *= this.timeScale;
      var actions = this._actions,
          nActions = this._nActiveActions,
          time = this.time += deltaTime,
          timeDirection = Math.sign(deltaTime),
          accuIndex = this._accuIndex ^= 1;
      for (var i = 0; i !== nActions; ++i) {
        var action = actions[i];
        action._update(time, deltaTime, timeDirection, accuIndex);
      }
      var bindings = this._bindings,
          nBindings = this._nActiveBindings;
      for (var i = 0; i !== nBindings; ++i) {
        bindings[i].apply(accuIndex);
      }
      return this;
    },
    getRoot: function() {
      return this._root;
    },
    uncacheClip: function(clip) {
      var actions = this._actions,
          clipUuid = clip.uuid,
          actionsByClip = this._actionsByClip,
          actionsForClip = actionsByClip[clipUuid];
      if (actionsForClip !== undefined) {
        var actionsToRemove = actionsForClip.knownActions;
        for (var i = 0,
            n = actionsToRemove.length; i !== n; ++i) {
          var action = actionsToRemove[i];
          this._deactivateAction(action);
          var cacheIndex = action._cacheIndex,
              lastInactiveAction = actions[actions.length - 1];
          action._cacheIndex = null;
          action._byClipCacheIndex = null;
          lastInactiveAction._cacheIndex = cacheIndex;
          actions[cacheIndex] = lastInactiveAction;
          actions.pop();
          this._removeInactiveBindingsForAction(action);
        }
        delete actionsByClip[clipUuid];
      }
    },
    uncacheRoot: function(root) {
      var rootUuid = root.uuid,
          actionsByClip = this._actionsByClip;
      for (var clipUuid in actionsByClip) {
        var actionByRoot = actionsByClip[clipUuid].actionByRoot,
            action = actionByRoot[rootUuid];
        if (action !== undefined) {
          this._deactivateAction(action);
          this._removeInactiveAction(action);
        }
      }
      var bindingsByRoot = this._bindingsByRootAndName,
          bindingByName = bindingsByRoot[rootUuid];
      if (bindingByName !== undefined) {
        for (var trackName in bindingByName) {
          var binding = bindingByName[trackName];
          binding.restoreOriginalState();
          this._removeInactiveBinding(binding);
        }
      }
    },
    uncacheAction: function(clip, optionalRoot) {
      var action = this.existingAction(clip, optionalRoot);
      if (action !== null) {
        this._deactivateAction(action);
        this._removeInactiveAction(action);
      }
    }
  });
  function Uniform(value) {
    if (typeof value === 'string') {
      console.warn('THREE.Uniform: Type parameter is no longer needed.');
      value = arguments[1];
    }
    this.value = value;
  }
  Uniform.prototype.clone = function() {
    return new Uniform(this.value.clone === undefined ? this.value : this.value.clone());
  };
  function InstancedBufferGeometry() {
    BufferGeometry.call(this);
    this.type = 'InstancedBufferGeometry';
    this.maxInstancedCount = undefined;
  }
  InstancedBufferGeometry.prototype = Object.assign(Object.create(BufferGeometry.prototype), {
    constructor: InstancedBufferGeometry,
    isInstancedBufferGeometry: true,
    copy: function(source) {
      BufferGeometry.prototype.copy.call(this, source);
      this.maxInstancedCount = source.maxInstancedCount;
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    }
  });
  function InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, normalized) {
    this.uuid = _Math.generateUUID();
    this.data = interleavedBuffer;
    this.itemSize = itemSize;
    this.offset = offset;
    this.normalized = normalized === true;
  }
  Object.defineProperties(InterleavedBufferAttribute.prototype, {
    count: {get: function() {
        return this.data.count;
      }},
    array: {get: function() {
        return this.data.array;
      }}
  });
  Object.assign(InterleavedBufferAttribute.prototype, {
    isInterleavedBufferAttribute: true,
    setX: function(index, x) {
      this.data.array[index * this.data.stride + this.offset] = x;
      return this;
    },
    setY: function(index, y) {
      this.data.array[index * this.data.stride + this.offset + 1] = y;
      return this;
    },
    setZ: function(index, z) {
      this.data.array[index * this.data.stride + this.offset + 2] = z;
      return this;
    },
    setW: function(index, w) {
      this.data.array[index * this.data.stride + this.offset + 3] = w;
      return this;
    },
    getX: function(index) {
      return this.data.array[index * this.data.stride + this.offset];
    },
    getY: function(index) {
      return this.data.array[index * this.data.stride + this.offset + 1];
    },
    getZ: function(index) {
      return this.data.array[index * this.data.stride + this.offset + 2];
    },
    getW: function(index) {
      return this.data.array[index * this.data.stride + this.offset + 3];
    },
    setXY: function(index, x, y) {
      index = index * this.data.stride + this.offset;
      this.data.array[index + 0] = x;
      this.data.array[index + 1] = y;
      return this;
    },
    setXYZ: function(index, x, y, z) {
      index = index * this.data.stride + this.offset;
      this.data.array[index + 0] = x;
      this.data.array[index + 1] = y;
      this.data.array[index + 2] = z;
      return this;
    },
    setXYZW: function(index, x, y, z, w) {
      index = index * this.data.stride + this.offset;
      this.data.array[index + 0] = x;
      this.data.array[index + 1] = y;
      this.data.array[index + 2] = z;
      this.data.array[index + 3] = w;
      return this;
    }
  });
  function InterleavedBuffer(array, stride) {
    this.uuid = _Math.generateUUID();
    this.array = array;
    this.stride = stride;
    this.count = array !== undefined ? array.length / stride : 0;
    this.dynamic = false;
    this.updateRange = {
      offset: 0,
      count: -1
    };
    this.onUploadCallback = function() {};
    this.version = 0;
  }
  Object.defineProperty(InterleavedBuffer.prototype, 'needsUpdate', {set: function(value) {
      if (value === true)
        this.version++;
    }});
  Object.assign(InterleavedBuffer.prototype, {
    isInterleavedBuffer: true,
    setArray: function(array) {
      if (Array.isArray(array)) {
        throw new TypeError('THREE.BufferAttribute: array should be a Typed Array.');
      }
      this.count = array !== undefined ? array.length / this.stride : 0;
      this.array = array;
    },
    setDynamic: function(value) {
      this.dynamic = value;
      return this;
    },
    copy: function(source) {
      this.array = new source.array.constructor(source.array);
      this.count = source.count;
      this.stride = source.stride;
      this.dynamic = source.dynamic;
      return this;
    },
    copyAt: function(index1, attribute, index2) {
      index1 *= this.stride;
      index2 *= attribute.stride;
      for (var i = 0,
          l = this.stride; i < l; i++) {
        this.array[index1 + i] = attribute.array[index2 + i];
      }
      return this;
    },
    set: function(value, offset) {
      if (offset === undefined)
        offset = 0;
      this.array.set(value, offset);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    onUpload: function(callback) {
      this.onUploadCallback = callback;
      return this;
    }
  });
  function InstancedInterleavedBuffer(array, stride, meshPerAttribute) {
    InterleavedBuffer.call(this, array, stride);
    this.meshPerAttribute = meshPerAttribute || 1;
  }
  InstancedInterleavedBuffer.prototype = Object.assign(Object.create(InterleavedBuffer.prototype), {
    constructor: InstancedInterleavedBuffer,
    isInstancedInterleavedBuffer: true,
    copy: function(source) {
      InterleavedBuffer.prototype.copy.call(this, source);
      this.meshPerAttribute = source.meshPerAttribute;
      return this;
    }
  });
  function InstancedBufferAttribute(array, itemSize, meshPerAttribute) {
    BufferAttribute.call(this, array, itemSize);
    this.meshPerAttribute = meshPerAttribute || 1;
  }
  InstancedBufferAttribute.prototype = Object.assign(Object.create(BufferAttribute.prototype), {
    constructor: InstancedBufferAttribute,
    isInstancedBufferAttribute: true,
    copy: function(source) {
      BufferAttribute.prototype.copy.call(this, source);
      this.meshPerAttribute = source.meshPerAttribute;
      return this;
    }
  });
  function Raycaster(origin, direction, near, far) {
    this.ray = new Ray(origin, direction);
    this.near = near || 0;
    this.far = far || Infinity;
    this.params = {
      Mesh: {},
      Line: {},
      LOD: {},
      Points: {threshold: 1},
      Sprite: {}
    };
    Object.defineProperties(this.params, {PointCloud: {get: function() {
          console.warn('THREE.Raycaster: params.PointCloud has been renamed to params.Points.');
          return this.Points;
        }}});
  }
  function ascSort(a, b) {
    return a.distance - b.distance;
  }
  function intersectObject(object, raycaster, intersects, recursive) {
    if (object.visible === false)
      return;
    object.raycast(raycaster, intersects);
    if (recursive === true) {
      var children = object.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        intersectObject(children[i], raycaster, intersects, true);
      }
    }
  }
  Object.assign(Raycaster.prototype, {
    linePrecision: 1,
    set: function(origin, direction) {
      this.ray.set(origin, direction);
    },
    setFromCamera: function(coords, camera) {
      if ((camera && camera.isPerspectiveCamera)) {
        this.ray.origin.setFromMatrixPosition(camera.matrixWorld);
        this.ray.direction.set(coords.x, coords.y, 0.5).unproject(camera).sub(this.ray.origin).normalize();
      } else if ((camera && camera.isOrthographicCamera)) {
        this.ray.origin.set(coords.x, coords.y, (camera.near + camera.far) / (camera.near - camera.far)).unproject(camera);
        this.ray.direction.set(0, 0, -1).transformDirection(camera.matrixWorld);
      } else {
        console.error('THREE.Raycaster: Unsupported camera type.');
      }
    },
    intersectObject: function(object, recursive) {
      var intersects = [];
      intersectObject(object, this, intersects, recursive);
      intersects.sort(ascSort);
      return intersects;
    },
    intersectObjects: function(objects, recursive) {
      var intersects = [];
      if (Array.isArray(objects) === false) {
        console.warn('THREE.Raycaster.intersectObjects: objects is not an Array.');
        return intersects;
      }
      for (var i = 0,
          l = objects.length; i < l; i++) {
        intersectObject(objects[i], this, intersects, recursive);
      }
      intersects.sort(ascSort);
      return intersects;
    }
  });
  function Clock(autoStart) {
    this.autoStart = (autoStart !== undefined) ? autoStart : true;
    this.startTime = 0;
    this.oldTime = 0;
    this.elapsedTime = 0;
    this.running = false;
  }
  Object.assign(Clock.prototype, {
    start: function() {
      this.startTime = (typeof performance === 'undefined' ? Date : performance).now();
      this.oldTime = this.startTime;
      this.elapsedTime = 0;
      this.running = true;
    },
    stop: function() {
      this.getElapsedTime();
      this.running = false;
      this.autoStart = false;
    },
    getElapsedTime: function() {
      this.getDelta();
      return this.elapsedTime;
    },
    getDelta: function() {
      var diff = 0;
      if (this.autoStart && !this.running) {
        this.start();
        return 0;
      }
      if (this.running) {
        var newTime = (typeof performance === 'undefined' ? Date : performance).now();
        diff = (newTime - this.oldTime) / 1000;
        this.oldTime = newTime;
        this.elapsedTime += diff;
      }
      return diff;
    }
  });
  function Spherical(radius, phi, theta) {
    this.radius = (radius !== undefined) ? radius : 1.0;
    this.phi = (phi !== undefined) ? phi : 0;
    this.theta = (theta !== undefined) ? theta : 0;
    return this;
  }
  Object.assign(Spherical.prototype, {
    set: function(radius, phi, theta) {
      this.radius = radius;
      this.phi = phi;
      this.theta = theta;
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(other) {
      this.radius = other.radius;
      this.phi = other.phi;
      this.theta = other.theta;
      return this;
    },
    makeSafe: function() {
      var EPS = 0.000001;
      this.phi = Math.max(EPS, Math.min(Math.PI - EPS, this.phi));
      return this;
    },
    setFromVector3: function(vec3) {
      this.radius = vec3.length();
      if (this.radius === 0) {
        this.theta = 0;
        this.phi = 0;
      } else {
        this.theta = Math.atan2(vec3.x, vec3.z);
        this.phi = Math.acos(_Math.clamp(vec3.y / this.radius, -1, 1));
      }
      return this;
    }
  });
  function Cylindrical(radius, theta, y) {
    this.radius = (radius !== undefined) ? radius : 1.0;
    this.theta = (theta !== undefined) ? theta : 0;
    this.y = (y !== undefined) ? y : 0;
    return this;
  }
  Object.assign(Cylindrical.prototype, {
    set: function(radius, theta, y) {
      this.radius = radius;
      this.theta = theta;
      this.y = y;
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(other) {
      this.radius = other.radius;
      this.theta = other.theta;
      this.y = other.y;
      return this;
    },
    setFromVector3: function(vec3) {
      this.radius = Math.sqrt(vec3.x * vec3.x + vec3.z * vec3.z);
      this.theta = Math.atan2(vec3.x, vec3.z);
      this.y = vec3.y;
      return this;
    }
  });
  function ImmediateRenderObject(material) {
    Object3D.call(this);
    this.material = material;
    this.render = function() {};
  }
  ImmediateRenderObject.prototype = Object.create(Object3D.prototype);
  ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
  ImmediateRenderObject.prototype.isImmediateRenderObject = true;
  function VertexNormalsHelper(object, size, hex, linewidth) {
    this.object = object;
    this.size = (size !== undefined) ? size : 1;
    var color = (hex !== undefined) ? hex : 0xff0000;
    var width = (linewidth !== undefined) ? linewidth : 1;
    var nNormals = 0;
    var objGeometry = this.object.geometry;
    if (objGeometry && objGeometry.isGeometry) {
      nNormals = objGeometry.faces.length * 3;
    } else if (objGeometry && objGeometry.isBufferGeometry) {
      nNormals = objGeometry.attributes.normal.count;
    }
    var geometry = new BufferGeometry();
    var positions = new Float32BufferAttribute(nNormals * 2 * 3, 3);
    geometry.addAttribute('position', positions);
    LineSegments.call(this, geometry, new LineBasicMaterial({
      color: color,
      linewidth: width
    }));
    this.matrixAutoUpdate = false;
    this.update();
  }
  VertexNormalsHelper.prototype = Object.create(LineSegments.prototype);
  VertexNormalsHelper.prototype.constructor = VertexNormalsHelper;
  VertexNormalsHelper.prototype.update = (function() {
    var v1 = new Vector3();
    var v2 = new Vector3();
    var normalMatrix = new Matrix3();
    return function update() {
      var keys = ['a', 'b', 'c'];
      this.object.updateMatrixWorld(true);
      normalMatrix.getNormalMatrix(this.object.matrixWorld);
      var matrixWorld = this.object.matrixWorld;
      var position = this.geometry.attributes.position;
      var objGeometry = this.object.geometry;
      if (objGeometry && objGeometry.isGeometry) {
        var vertices = objGeometry.vertices;
        var faces = objGeometry.faces;
        var idx = 0;
        for (var i = 0,
            l = faces.length; i < l; i++) {
          var face = faces[i];
          for (var j = 0,
              jl = face.vertexNormals.length; j < jl; j++) {
            var vertex = vertices[face[keys[j]]];
            var normal = face.vertexNormals[j];
            v1.copy(vertex).applyMatrix4(matrixWorld);
            v2.copy(normal).applyMatrix3(normalMatrix).normalize().multiplyScalar(this.size).add(v1);
            position.setXYZ(idx, v1.x, v1.y, v1.z);
            idx = idx + 1;
            position.setXYZ(idx, v2.x, v2.y, v2.z);
            idx = idx + 1;
          }
        }
      } else if (objGeometry && objGeometry.isBufferGeometry) {
        var objPos = objGeometry.attributes.position;
        var objNorm = objGeometry.attributes.normal;
        var idx = 0;
        for (var j = 0,
            jl = objPos.count; j < jl; j++) {
          v1.set(objPos.getX(j), objPos.getY(j), objPos.getZ(j)).applyMatrix4(matrixWorld);
          v2.set(objNorm.getX(j), objNorm.getY(j), objNorm.getZ(j));
          v2.applyMatrix3(normalMatrix).normalize().multiplyScalar(this.size).add(v1);
          position.setXYZ(idx, v1.x, v1.y, v1.z);
          idx = idx + 1;
          position.setXYZ(idx, v2.x, v2.y, v2.z);
          idx = idx + 1;
        }
      }
      position.needsUpdate = true;
    };
  }());
  function SpotLightHelper(light, color) {
    Object3D.call(this);
    this.light = light;
    this.light.updateMatrixWorld();
    this.matrix = light.matrixWorld;
    this.matrixAutoUpdate = false;
    this.color = color;
    var geometry = new BufferGeometry();
    var positions = [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, -1, 1];
    for (var i = 0,
        j = 1,
        l = 32; i < l; i++, j++) {
      var p1 = (i / l) * Math.PI * 2;
      var p2 = (j / l) * Math.PI * 2;
      positions.push(Math.cos(p1), Math.sin(p1), 1, Math.cos(p2), Math.sin(p2), 1);
    }
    geometry.addAttribute('position', new Float32BufferAttribute(positions, 3));
    var material = new LineBasicMaterial({fog: false});
    this.cone = new LineSegments(geometry, material);
    this.add(this.cone);
    this.update();
  }
  SpotLightHelper.prototype = Object.create(Object3D.prototype);
  SpotLightHelper.prototype.constructor = SpotLightHelper;
  SpotLightHelper.prototype.dispose = function() {
    this.cone.geometry.dispose();
    this.cone.material.dispose();
  };
  SpotLightHelper.prototype.update = function() {
    var vector = new Vector3();
    var vector2 = new Vector3();
    return function update() {
      this.light.updateMatrixWorld();
      var coneLength = this.light.distance ? this.light.distance : 1000;
      var coneWidth = coneLength * Math.tan(this.light.angle);
      this.cone.scale.set(coneWidth, coneWidth, coneLength);
      vector.setFromMatrixPosition(this.light.matrixWorld);
      vector2.setFromMatrixPosition(this.light.target.matrixWorld);
      this.cone.lookAt(vector2.sub(vector));
      if (this.color !== undefined) {
        this.cone.material.color.set(this.color);
      } else {
        this.cone.material.color.copy(this.light.color);
      }
    };
  }();
  function getBoneList(object) {
    var boneList = [];
    if (object && object.isBone) {
      boneList.push(object);
    }
    for (var i = 0; i < object.children.length; i++) {
      boneList.push.apply(boneList, getBoneList(object.children[i]));
    }
    return boneList;
  }
  function SkeletonHelper(object) {
    var bones = getBoneList(object);
    var geometry = new BufferGeometry();
    var vertices = [];
    var colors = [];
    var color1 = new Color(0, 0, 1);
    var color2 = new Color(0, 1, 0);
    for (var i = 0; i < bones.length; i++) {
      var bone = bones[i];
      if (bone.parent && bone.parent.isBone) {
        vertices.push(0, 0, 0);
        vertices.push(0, 0, 0);
        colors.push(color1.r, color1.g, color1.b);
        colors.push(color2.r, color2.g, color2.b);
      }
    }
    geometry.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    geometry.addAttribute('color', new Float32BufferAttribute(colors, 3));
    var material = new LineBasicMaterial({
      vertexColors: VertexColors,
      depthTest: false,
      depthWrite: false,
      transparent: true
    });
    LineSegments.call(this, geometry, material);
    this.root = object;
    this.bones = bones;
    this.matrix = object.matrixWorld;
    this.matrixAutoUpdate = false;
  }
  SkeletonHelper.prototype = Object.create(LineSegments.prototype);
  SkeletonHelper.prototype.constructor = SkeletonHelper;
  SkeletonHelper.prototype.updateMatrixWorld = function() {
    var vector = new Vector3();
    var boneMatrix = new Matrix4();
    var matrixWorldInv = new Matrix4();
    return function updateMatrixWorld(force) {
      var bones = this.bones;
      var geometry = this.geometry;
      var position = geometry.getAttribute('position');
      matrixWorldInv.getInverse(this.root.matrixWorld);
      for (var i = 0,
          j = 0; i < bones.length; i++) {
        var bone = bones[i];
        if (bone.parent && bone.parent.isBone) {
          boneMatrix.multiplyMatrices(matrixWorldInv, bone.matrixWorld);
          vector.setFromMatrixPosition(boneMatrix);
          position.setXYZ(j, vector.x, vector.y, vector.z);
          boneMatrix.multiplyMatrices(matrixWorldInv, bone.parent.matrixWorld);
          vector.setFromMatrixPosition(boneMatrix);
          position.setXYZ(j + 1, vector.x, vector.y, vector.z);
          j += 2;
        }
      }
      geometry.getAttribute('position').needsUpdate = true;
      Object3D.prototype.updateMatrixWorld.call(this, force);
    };
  }();
  function PointLightHelper(light, sphereSize, color) {
    this.light = light;
    this.light.updateMatrixWorld();
    this.color = color;
    var geometry = new SphereBufferGeometry(sphereSize, 4, 2);
    var material = new MeshBasicMaterial({
      wireframe: true,
      fog: false
    });
    Mesh.call(this, geometry, material);
    this.matrix = this.light.matrixWorld;
    this.matrixAutoUpdate = false;
    this.update();
  }
  PointLightHelper.prototype = Object.create(Mesh.prototype);
  PointLightHelper.prototype.constructor = PointLightHelper;
  PointLightHelper.prototype.dispose = function() {
    this.geometry.dispose();
    this.material.dispose();
  };
  PointLightHelper.prototype.update = function() {
    if (this.color !== undefined) {
      this.material.color.set(this.color);
    } else {
      this.material.color.copy(this.light.color);
    }
  };
  function RectAreaLightHelper(light, color) {
    Object3D.call(this);
    this.light = light;
    this.light.updateMatrixWorld();
    this.matrix = light.matrixWorld;
    this.matrixAutoUpdate = false;
    this.color = color;
    var material = new LineBasicMaterial({fog: false});
    var geometry = new BufferGeometry();
    geometry.addAttribute('position', new BufferAttribute(new Float32Array(5 * 3), 3));
    this.line = new Line(geometry, material);
    this.add(this.line);
    this.update();
  }
  RectAreaLightHelper.prototype = Object.create(Object3D.prototype);
  RectAreaLightHelper.prototype.constructor = RectAreaLightHelper;
  RectAreaLightHelper.prototype.dispose = function() {
    this.children[0].geometry.dispose();
    this.children[0].material.dispose();
  };
  RectAreaLightHelper.prototype.update = function() {
    var hx = this.light.width * 0.5;
    var hy = this.light.height * 0.5;
    var position = this.line.geometry.attributes.position;
    var array = position.array;
    array[0] = hx;
    array[1] = -hy;
    array[2] = 0;
    array[3] = hx;
    array[4] = hy;
    array[5] = 0;
    array[6] = -hx;
    array[7] = hy;
    array[8] = 0;
    array[9] = -hx;
    array[10] = -hy;
    array[11] = 0;
    array[12] = hx;
    array[13] = -hy;
    array[14] = 0;
    position.needsUpdate = true;
    if (this.color !== undefined) {
      this.line.material.color.set(this.color);
    } else {
      this.line.material.color.copy(this.light.color);
    }
  };
  function HemisphereLightHelper(light, size, color) {
    Object3D.call(this);
    this.light = light;
    this.light.updateMatrixWorld();
    this.matrix = light.matrixWorld;
    this.matrixAutoUpdate = false;
    this.color = color;
    var geometry = new OctahedronBufferGeometry(size);
    geometry.rotateY(Math.PI * 0.5);
    this.material = new MeshBasicMaterial({
      wireframe: true,
      fog: false
    });
    if (this.color === undefined)
      this.material.vertexColors = VertexColors;
    var position = geometry.getAttribute('position');
    var colors = new Float32Array(position.count * 3);
    geometry.addAttribute('color', new BufferAttribute(colors, 3));
    this.add(new Mesh(geometry, this.material));
    this.update();
  }
  HemisphereLightHelper.prototype = Object.create(Object3D.prototype);
  HemisphereLightHelper.prototype.constructor = HemisphereLightHelper;
  HemisphereLightHelper.prototype.dispose = function() {
    this.children[0].geometry.dispose();
    this.children[0].material.dispose();
  };
  HemisphereLightHelper.prototype.update = function() {
    var vector = new Vector3();
    var color1 = new Color();
    var color2 = new Color();
    return function update() {
      var mesh = this.children[0];
      if (this.color !== undefined) {
        this.material.color.set(this.color);
      } else {
        var colors = mesh.geometry.getAttribute('color');
        color1.copy(this.light.color);
        color2.copy(this.light.groundColor);
        for (var i = 0,
            l = colors.count; i < l; i++) {
          var color = (i < (l / 2)) ? color1 : color2;
          colors.setXYZ(i, color.r, color.g, color.b);
        }
        colors.needsUpdate = true;
      }
      mesh.lookAt(vector.setFromMatrixPosition(this.light.matrixWorld).negate());
    };
  }();
  function GridHelper(size, divisions, color1, color2) {
    size = size || 10;
    divisions = divisions || 10;
    color1 = new Color(color1 !== undefined ? color1 : 0x444444);
    color2 = new Color(color2 !== undefined ? color2 : 0x888888);
    var center = divisions / 2;
    var step = size / divisions;
    var halfSize = size / 2;
    var vertices = [],
        colors = [];
    for (var i = 0,
        j = 0,
        k = -halfSize; i <= divisions; i++, k += step) {
      vertices.push(-halfSize, 0, k, halfSize, 0, k);
      vertices.push(k, 0, -halfSize, k, 0, halfSize);
      var color = i === center ? color1 : color2;
      color.toArray(colors, j);
      j += 3;
      color.toArray(colors, j);
      j += 3;
      color.toArray(colors, j);
      j += 3;
      color.toArray(colors, j);
      j += 3;
    }
    var geometry = new BufferGeometry();
    geometry.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    geometry.addAttribute('color', new Float32BufferAttribute(colors, 3));
    var material = new LineBasicMaterial({vertexColors: VertexColors});
    LineSegments.call(this, geometry, material);
  }
  GridHelper.prototype = Object.create(LineSegments.prototype);
  GridHelper.prototype.constructor = GridHelper;
  function PolarGridHelper(radius, radials, circles, divisions, color1, color2) {
    radius = radius || 10;
    radials = radials || 16;
    circles = circles || 8;
    divisions = divisions || 64;
    color1 = new Color(color1 !== undefined ? color1 : 0x444444);
    color2 = new Color(color2 !== undefined ? color2 : 0x888888);
    var vertices = [];
    var colors = [];
    var x,
        z;
    var v,
        i,
        j,
        r,
        color;
    for (i = 0; i <= radials; i++) {
      v = (i / radials) * (Math.PI * 2);
      x = Math.sin(v) * radius;
      z = Math.cos(v) * radius;
      vertices.push(0, 0, 0);
      vertices.push(x, 0, z);
      color = (i & 1) ? color1 : color2;
      colors.push(color.r, color.g, color.b);
      colors.push(color.r, color.g, color.b);
    }
    for (i = 0; i <= circles; i++) {
      color = (i & 1) ? color1 : color2;
      r = radius - (radius / circles * i);
      for (j = 0; j < divisions; j++) {
        v = (j / divisions) * (Math.PI * 2);
        x = Math.sin(v) * r;
        z = Math.cos(v) * r;
        vertices.push(x, 0, z);
        colors.push(color.r, color.g, color.b);
        v = ((j + 1) / divisions) * (Math.PI * 2);
        x = Math.sin(v) * r;
        z = Math.cos(v) * r;
        vertices.push(x, 0, z);
        colors.push(color.r, color.g, color.b);
      }
    }
    var geometry = new BufferGeometry();
    geometry.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    geometry.addAttribute('color', new Float32BufferAttribute(colors, 3));
    var material = new LineBasicMaterial({vertexColors: VertexColors});
    LineSegments.call(this, geometry, material);
  }
  PolarGridHelper.prototype = Object.create(LineSegments.prototype);
  PolarGridHelper.prototype.constructor = PolarGridHelper;
  function FaceNormalsHelper(object, size, hex, linewidth) {
    this.object = object;
    this.size = (size !== undefined) ? size : 1;
    var color = (hex !== undefined) ? hex : 0xffff00;
    var width = (linewidth !== undefined) ? linewidth : 1;
    var nNormals = 0;
    var objGeometry = this.object.geometry;
    if (objGeometry && objGeometry.isGeometry) {
      nNormals = objGeometry.faces.length;
    } else {
      console.warn('THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.');
    }
    var geometry = new BufferGeometry();
    var positions = new Float32BufferAttribute(nNormals * 2 * 3, 3);
    geometry.addAttribute('position', positions);
    LineSegments.call(this, geometry, new LineBasicMaterial({
      color: color,
      linewidth: width
    }));
    this.matrixAutoUpdate = false;
    this.update();
  }
  FaceNormalsHelper.prototype = Object.create(LineSegments.prototype);
  FaceNormalsHelper.prototype.constructor = FaceNormalsHelper;
  FaceNormalsHelper.prototype.update = (function() {
    var v1 = new Vector3();
    var v2 = new Vector3();
    var normalMatrix = new Matrix3();
    return function update() {
      this.object.updateMatrixWorld(true);
      normalMatrix.getNormalMatrix(this.object.matrixWorld);
      var matrixWorld = this.object.matrixWorld;
      var position = this.geometry.attributes.position;
      var objGeometry = this.object.geometry;
      var vertices = objGeometry.vertices;
      var faces = objGeometry.faces;
      var idx = 0;
      for (var i = 0,
          l = faces.length; i < l; i++) {
        var face = faces[i];
        var normal = face.normal;
        v1.copy(vertices[face.a]).add(vertices[face.b]).add(vertices[face.c]).divideScalar(3).applyMatrix4(matrixWorld);
        v2.copy(normal).applyMatrix3(normalMatrix).normalize().multiplyScalar(this.size).add(v1);
        position.setXYZ(idx, v1.x, v1.y, v1.z);
        idx = idx + 1;
        position.setXYZ(idx, v2.x, v2.y, v2.z);
        idx = idx + 1;
      }
      position.needsUpdate = true;
    };
  }());
  function DirectionalLightHelper(light, size, color) {
    Object3D.call(this);
    this.light = light;
    this.light.updateMatrixWorld();
    this.matrix = light.matrixWorld;
    this.matrixAutoUpdate = false;
    this.color = color;
    if (size === undefined)
      size = 1;
    var geometry = new BufferGeometry();
    geometry.addAttribute('position', new Float32BufferAttribute([-size, size, 0, size, size, 0, size, -size, 0, -size, -size, 0, -size, size, 0], 3));
    var material = new LineBasicMaterial({fog: false});
    this.lightPlane = new Line(geometry, material);
    this.add(this.lightPlane);
    geometry = new BufferGeometry();
    geometry.addAttribute('position', new Float32BufferAttribute([0, 0, 0, 0, 0, 1], 3));
    this.targetLine = new Line(geometry, material);
    this.add(this.targetLine);
    this.update();
  }
  DirectionalLightHelper.prototype = Object.create(Object3D.prototype);
  DirectionalLightHelper.prototype.constructor = DirectionalLightHelper;
  DirectionalLightHelper.prototype.dispose = function() {
    this.lightPlane.geometry.dispose();
    this.lightPlane.material.dispose();
    this.targetLine.geometry.dispose();
    this.targetLine.material.dispose();
  };
  DirectionalLightHelper.prototype.update = function() {
    var v1 = new Vector3();
    var v2 = new Vector3();
    var v3 = new Vector3();
    return function update() {
      v1.setFromMatrixPosition(this.light.matrixWorld);
      v2.setFromMatrixPosition(this.light.target.matrixWorld);
      v3.subVectors(v2, v1);
      this.lightPlane.lookAt(v3);
      if (this.color !== undefined) {
        this.lightPlane.material.color.set(this.color);
        this.targetLine.material.color.set(this.color);
      } else {
        this.lightPlane.material.color.copy(this.light.color);
        this.targetLine.material.color.copy(this.light.color);
      }
      this.targetLine.lookAt(v3);
      this.targetLine.scale.z = v3.length();
    };
  }();
  function CameraHelper(camera) {
    var geometry = new BufferGeometry();
    var material = new LineBasicMaterial({
      color: 0xffffff,
      vertexColors: FaceColors
    });
    var vertices = [];
    var colors = [];
    var pointMap = {};
    var colorFrustum = new Color(0xffaa00);
    var colorCone = new Color(0xff0000);
    var colorUp = new Color(0x00aaff);
    var colorTarget = new Color(0xffffff);
    var colorCross = new Color(0x333333);
    addLine('n1', 'n2', colorFrustum);
    addLine('n2', 'n4', colorFrustum);
    addLine('n4', 'n3', colorFrustum);
    addLine('n3', 'n1', colorFrustum);
    addLine('f1', 'f2', colorFrustum);
    addLine('f2', 'f4', colorFrustum);
    addLine('f4', 'f3', colorFrustum);
    addLine('f3', 'f1', colorFrustum);
    addLine('n1', 'f1', colorFrustum);
    addLine('n2', 'f2', colorFrustum);
    addLine('n3', 'f3', colorFrustum);
    addLine('n4', 'f4', colorFrustum);
    addLine('p', 'n1', colorCone);
    addLine('p', 'n2', colorCone);
    addLine('p', 'n3', colorCone);
    addLine('p', 'n4', colorCone);
    addLine('u1', 'u2', colorUp);
    addLine('u2', 'u3', colorUp);
    addLine('u3', 'u1', colorUp);
    addLine('c', 't', colorTarget);
    addLine('p', 'c', colorCross);
    addLine('cn1', 'cn2', colorCross);
    addLine('cn3', 'cn4', colorCross);
    addLine('cf1', 'cf2', colorCross);
    addLine('cf3', 'cf4', colorCross);
    function addLine(a, b, color) {
      addPoint(a, color);
      addPoint(b, color);
    }
    function addPoint(id, color) {
      vertices.push(0, 0, 0);
      colors.push(color.r, color.g, color.b);
      if (pointMap[id] === undefined) {
        pointMap[id] = [];
      }
      pointMap[id].push((vertices.length / 3) - 1);
    }
    geometry.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    geometry.addAttribute('color', new Float32BufferAttribute(colors, 3));
    LineSegments.call(this, geometry, material);
    this.camera = camera;
    if (this.camera.updateProjectionMatrix)
      this.camera.updateProjectionMatrix();
    this.matrix = camera.matrixWorld;
    this.matrixAutoUpdate = false;
    this.pointMap = pointMap;
    this.update();
  }
  CameraHelper.prototype = Object.create(LineSegments.prototype);
  CameraHelper.prototype.constructor = CameraHelper;
  CameraHelper.prototype.update = function() {
    var geometry,
        pointMap;
    var vector = new Vector3();
    var camera = new Camera();
    function setPoint(point, x, y, z) {
      vector.set(x, y, z).unproject(camera);
      var points = pointMap[point];
      if (points !== undefined) {
        var position = geometry.getAttribute('position');
        for (var i = 0,
            l = points.length; i < l; i++) {
          position.setXYZ(points[i], vector.x, vector.y, vector.z);
        }
      }
    }
    return function update() {
      geometry = this.geometry;
      pointMap = this.pointMap;
      var w = 1,
          h = 1;
      camera.projectionMatrix.copy(this.camera.projectionMatrix);
      setPoint('c', 0, 0, -1);
      setPoint('t', 0, 0, 1);
      setPoint('n1', -w, -h, -1);
      setPoint('n2', w, -h, -1);
      setPoint('n3', -w, h, -1);
      setPoint('n4', w, h, -1);
      setPoint('f1', -w, -h, 1);
      setPoint('f2', w, -h, 1);
      setPoint('f3', -w, h, 1);
      setPoint('f4', w, h, 1);
      setPoint('u1', w * 0.7, h * 1.1, -1);
      setPoint('u2', -w * 0.7, h * 1.1, -1);
      setPoint('u3', 0, h * 2, -1);
      setPoint('cf1', -w, 0, 1);
      setPoint('cf2', w, 0, 1);
      setPoint('cf3', 0, -h, 1);
      setPoint('cf4', 0, h, 1);
      setPoint('cn1', -w, 0, -1);
      setPoint('cn2', w, 0, -1);
      setPoint('cn3', 0, -h, -1);
      setPoint('cn4', 0, h, -1);
      geometry.getAttribute('position').needsUpdate = true;
    };
  }();
  function BoxHelper(object, color) {
    this.object = object;
    if (color === undefined)
      color = 0xffff00;
    var indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]);
    var positions = new Float32Array(8 * 3);
    var geometry = new BufferGeometry();
    geometry.setIndex(new BufferAttribute(indices, 1));
    geometry.addAttribute('position', new BufferAttribute(positions, 3));
    LineSegments.call(this, geometry, new LineBasicMaterial({color: color}));
    this.matrixAutoUpdate = false;
    this.update();
  }
  BoxHelper.prototype = Object.create(LineSegments.prototype);
  BoxHelper.prototype.constructor = BoxHelper;
  BoxHelper.prototype.update = (function() {
    var box = new Box3();
    return function update(object) {
      if (object !== undefined) {
        console.warn('THREE.BoxHelper: .update() has no longer arguments.');
      }
      if (this.object !== undefined) {
        box.setFromObject(this.object);
      }
      if (box.isEmpty())
        return;
      var min = box.min;
      var max = box.max;
      var position = this.geometry.attributes.position;
      var array = position.array;
      array[0] = max.x;
      array[1] = max.y;
      array[2] = max.z;
      array[3] = min.x;
      array[4] = max.y;
      array[5] = max.z;
      array[6] = min.x;
      array[7] = min.y;
      array[8] = max.z;
      array[9] = max.x;
      array[10] = min.y;
      array[11] = max.z;
      array[12] = max.x;
      array[13] = max.y;
      array[14] = min.z;
      array[15] = min.x;
      array[16] = max.y;
      array[17] = min.z;
      array[18] = min.x;
      array[19] = min.y;
      array[20] = min.z;
      array[21] = max.x;
      array[22] = min.y;
      array[23] = min.z;
      position.needsUpdate = true;
      this.geometry.computeBoundingSphere();
    };
  })();
  BoxHelper.prototype.setFromObject = function(object) {
    this.object = object;
    this.update();
    return this;
  };
  function Box3Helper(box, hex) {
    this.type = 'Box3Helper';
    this.box = box;
    var color = (hex !== undefined) ? hex : 0xffff00;
    var indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]);
    var positions = [1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1];
    var geometry = new BufferGeometry();
    geometry.setIndex(new BufferAttribute(indices, 1));
    geometry.addAttribute('position', new Float32BufferAttribute(positions, 3));
    LineSegments.call(this, geometry, new LineBasicMaterial({color: color}));
    this.geometry.computeBoundingSphere();
  }
  Box3Helper.prototype = Object.create(LineSegments.prototype);
  Box3Helper.prototype.constructor = Box3Helper;
  Box3Helper.prototype.updateMatrixWorld = function(force) {
    var box = this.box;
    if (box.isEmpty())
      return;
    box.getCenter(this.position);
    box.getSize(this.scale);
    this.scale.multiplyScalar(0.5);
    Object3D.prototype.updateMatrixWorld.call(this, force);
  };
  function PlaneHelper(plane, size, hex) {
    this.type = 'PlaneHelper';
    this.plane = plane;
    this.size = (size === undefined) ? 1 : size;
    var color = (hex !== undefined) ? hex : 0xffff00;
    var positions = [1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0];
    var geometry = new BufferGeometry();
    geometry.addAttribute('position', new Float32BufferAttribute(positions, 3));
    geometry.computeBoundingSphere();
    Line.call(this, geometry, new LineBasicMaterial({color: color}));
    var positions2 = [1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1];
    var geometry2 = new BufferGeometry();
    geometry2.addAttribute('position', new Float32BufferAttribute(positions2, 3));
    geometry2.computeBoundingSphere();
    this.add(new Mesh(geometry2, new MeshBasicMaterial({
      color: color,
      opacity: 0.2,
      transparent: true,
      depthWrite: false
    })));
  }
  PlaneHelper.prototype = Object.create(Line.prototype);
  PlaneHelper.prototype.constructor = PlaneHelper;
  PlaneHelper.prototype.updateMatrixWorld = function(force) {
    var scale = -this.plane.constant;
    if (Math.abs(scale) < 1e-8)
      scale = 1e-8;
    this.scale.set(0.5 * this.size, 0.5 * this.size, scale);
    this.lookAt(this.plane.normal);
    Object3D.prototype.updateMatrixWorld.call(this, force);
  };
  var lineGeometry;
  var coneGeometry;
  function ArrowHelper(dir, origin, length, color, headLength, headWidth) {
    Object3D.call(this);
    if (color === undefined)
      color = 0xffff00;
    if (length === undefined)
      length = 1;
    if (headLength === undefined)
      headLength = 0.2 * length;
    if (headWidth === undefined)
      headWidth = 0.2 * headLength;
    if (lineGeometry === undefined) {
      lineGeometry = new BufferGeometry();
      lineGeometry.addAttribute('position', new Float32BufferAttribute([0, 0, 0, 0, 1, 0], 3));
      coneGeometry = new CylinderBufferGeometry(0, 0.5, 1, 5, 1);
      coneGeometry.translate(0, -0.5, 0);
    }
    this.position.copy(origin);
    this.line = new Line(lineGeometry, new LineBasicMaterial({color: color}));
    this.line.matrixAutoUpdate = false;
    this.add(this.line);
    this.cone = new Mesh(coneGeometry, new MeshBasicMaterial({color: color}));
    this.cone.matrixAutoUpdate = false;
    this.add(this.cone);
    this.setDirection(dir);
    this.setLength(length, headLength, headWidth);
  }
  ArrowHelper.prototype = Object.create(Object3D.prototype);
  ArrowHelper.prototype.constructor = ArrowHelper;
  ArrowHelper.prototype.setDirection = (function() {
    var axis = new Vector3();
    var radians;
    return function setDirection(dir) {
      if (dir.y > 0.99999) {
        this.quaternion.set(0, 0, 0, 1);
      } else if (dir.y < -0.99999) {
        this.quaternion.set(1, 0, 0, 0);
      } else {
        axis.set(dir.z, 0, -dir.x).normalize();
        radians = Math.acos(dir.y);
        this.quaternion.setFromAxisAngle(axis, radians);
      }
    };
  }());
  ArrowHelper.prototype.setLength = function(length, headLength, headWidth) {
    if (headLength === undefined)
      headLength = 0.2 * length;
    if (headWidth === undefined)
      headWidth = 0.2 * headLength;
    this.line.scale.set(1, Math.max(0, length - headLength), 1);
    this.line.updateMatrix();
    this.cone.scale.set(headWidth, headLength, headWidth);
    this.cone.position.y = length;
    this.cone.updateMatrix();
  };
  ArrowHelper.prototype.setColor = function(color) {
    this.line.material.color.copy(color);
    this.cone.material.color.copy(color);
  };
  function AxesHelper(size) {
    size = size || 1;
    var vertices = [0, 0, 0, size, 0, 0, 0, 0, 0, 0, size, 0, 0, 0, 0, 0, 0, size];
    var colors = [1, 0, 0, 1, 0.6, 0, 0, 1, 0, 0.6, 1, 0, 0, 0, 1, 0, 0.6, 1];
    var geometry = new BufferGeometry();
    geometry.addAttribute('position', new Float32BufferAttribute(vertices, 3));
    geometry.addAttribute('color', new Float32BufferAttribute(colors, 3));
    var material = new LineBasicMaterial({vertexColors: VertexColors});
    LineSegments.call(this, geometry, material);
  }
  AxesHelper.prototype = Object.create(LineSegments.prototype);
  AxesHelper.prototype.constructor = AxesHelper;
  function CubicPoly() {
    var c0 = 0,
        c1 = 0,
        c2 = 0,
        c3 = 0;
    function init(x0, x1, t0, t1) {
      c0 = x0;
      c1 = t0;
      c2 = -3 * x0 + 3 * x1 - 2 * t0 - t1;
      c3 = 2 * x0 - 2 * x1 + t0 + t1;
    }
    return {
      initCatmullRom: function(x0, x1, x2, x3, tension) {
        init(x1, x2, tension * (x2 - x0), tension * (x3 - x1));
      },
      initNonuniformCatmullRom: function(x0, x1, x2, x3, dt0, dt1, dt2) {
        var t1 = (x1 - x0) / dt0 - (x2 - x0) / (dt0 + dt1) + (x2 - x1) / dt1;
        var t2 = (x2 - x1) / dt1 - (x3 - x1) / (dt1 + dt2) + (x3 - x2) / dt2;
        t1 *= dt1;
        t2 *= dt1;
        init(x1, x2, t1, t2);
      },
      calc: function(t) {
        var t2 = t * t;
        var t3 = t2 * t;
        return c0 + c1 * t + c2 * t2 + c3 * t3;
      }
    };
  }
  var tmp = new Vector3();
  var px = new CubicPoly();
  var py = new CubicPoly();
  var pz = new CubicPoly();
  function CatmullRomCurve3(points, closed, curveType, tension) {
    Curve.call(this);
    this.type = 'CatmullRomCurve3';
    this.points = points || [];
    this.closed = closed || false;
    this.curveType = curveType || 'centripetal';
    this.tension = tension || 0.5;
  }
  CatmullRomCurve3.prototype = Object.create(Curve.prototype);
  CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
  CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
  CatmullRomCurve3.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector3();
    var points = this.points;
    var l = points.length;
    var p = (l - (this.closed ? 0 : 1)) * t;
    var intPoint = Math.floor(p);
    var weight = p - intPoint;
    if (this.closed) {
      intPoint += intPoint > 0 ? 0 : (Math.floor(Math.abs(intPoint) / points.length) + 1) * points.length;
    } else if (weight === 0 && intPoint === l - 1) {
      intPoint = l - 2;
      weight = 1;
    }
    var p0,
        p1,
        p2,
        p3;
    if (this.closed || intPoint > 0) {
      p0 = points[(intPoint - 1) % l];
    } else {
      tmp.subVectors(points[0], points[1]).add(points[0]);
      p0 = tmp;
    }
    p1 = points[intPoint % l];
    p2 = points[(intPoint + 1) % l];
    if (this.closed || intPoint + 2 < l) {
      p3 = points[(intPoint + 2) % l];
    } else {
      tmp.subVectors(points[l - 1], points[l - 2]).add(points[l - 1]);
      p3 = tmp;
    }
    if (this.curveType === 'centripetal' || this.curveType === 'chordal') {
      var pow = this.curveType === 'chordal' ? 0.5 : 0.25;
      var dt0 = Math.pow(p0.distanceToSquared(p1), pow);
      var dt1 = Math.pow(p1.distanceToSquared(p2), pow);
      var dt2 = Math.pow(p2.distanceToSquared(p3), pow);
      if (dt1 < 1e-4)
        dt1 = 1.0;
      if (dt0 < 1e-4)
        dt0 = dt1;
      if (dt2 < 1e-4)
        dt2 = dt1;
      px.initNonuniformCatmullRom(p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2);
      py.initNonuniformCatmullRom(p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2);
      pz.initNonuniformCatmullRom(p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2);
    } else if (this.curveType === 'catmullrom') {
      px.initCatmullRom(p0.x, p1.x, p2.x, p3.x, this.tension);
      py.initCatmullRom(p0.y, p1.y, p2.y, p3.y, this.tension);
      pz.initCatmullRom(p0.z, p1.z, p2.z, p3.z, this.tension);
    }
    point.set(px.calc(weight), py.calc(weight), pz.calc(weight));
    return point;
  };
  CatmullRomCurve3.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.points = [];
    for (var i = 0,
        l = source.points.length; i < l; i++) {
      var point = source.points[i];
      this.points.push(point.clone());
    }
    this.closed = source.closed;
    this.curveType = source.curveType;
    this.tension = source.tension;
    return this;
  };
  function CubicBezierCurve3(v0, v1, v2, v3) {
    Curve.call(this);
    this.type = 'CubicBezierCurve3';
    this.v0 = v0 || new Vector3();
    this.v1 = v1 || new Vector3();
    this.v2 = v2 || new Vector3();
    this.v3 = v3 || new Vector3();
  }
  CubicBezierCurve3.prototype = Object.create(Curve.prototype);
  CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
  CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
  CubicBezierCurve3.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector3();
    var v0 = this.v0,
        v1 = this.v1,
        v2 = this.v2,
        v3 = this.v3;
    point.set(CubicBezier(t, v0.x, v1.x, v2.x, v3.x), CubicBezier(t, v0.y, v1.y, v2.y, v3.y), CubicBezier(t, v0.z, v1.z, v2.z, v3.z));
    return point;
  };
  CubicBezierCurve3.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.v0.copy(source.v0);
    this.v1.copy(source.v1);
    this.v2.copy(source.v2);
    this.v3.copy(source.v3);
    return this;
  };
  function QuadraticBezierCurve3(v0, v1, v2) {
    Curve.call(this);
    this.type = 'QuadraticBezierCurve3';
    this.v0 = v0 || new Vector3();
    this.v1 = v1 || new Vector3();
    this.v2 = v2 || new Vector3();
  }
  QuadraticBezierCurve3.prototype = Object.create(Curve.prototype);
  QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
  QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
  QuadraticBezierCurve3.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector3();
    var v0 = this.v0,
        v1 = this.v1,
        v2 = this.v2;
    point.set(QuadraticBezier(t, v0.x, v1.x, v2.x), QuadraticBezier(t, v0.y, v1.y, v2.y), QuadraticBezier(t, v0.z, v1.z, v2.z));
    return point;
  };
  QuadraticBezierCurve3.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.v0.copy(source.v0);
    this.v1.copy(source.v1);
    this.v2.copy(source.v2);
    return this;
  };
  function LineCurve3(v1, v2) {
    Curve.call(this);
    this.type = 'LineCurve3';
    this.v1 = v1 || new Vector3();
    this.v2 = v2 || new Vector3();
  }
  LineCurve3.prototype = Object.create(Curve.prototype);
  LineCurve3.prototype.constructor = LineCurve3;
  LineCurve3.prototype.isLineCurve3 = true;
  LineCurve3.prototype.getPoint = function(t, optionalTarget) {
    var point = optionalTarget || new Vector3();
    if (t === 1) {
      point.copy(this.v2);
    } else {
      point.copy(this.v2).sub(this.v1);
      point.multiplyScalar(t).add(this.v1);
    }
    return point;
  };
  LineCurve3.prototype.getPointAt = function(u, optionalTarget) {
    return this.getPoint(u, optionalTarget);
  };
  LineCurve3.prototype.copy = function(source) {
    Curve.prototype.copy.call(this, source);
    this.v1.copy(source.v1);
    this.v2.copy(source.v2);
    return this;
  };
  function ArcCurve(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
    EllipseCurve.call(this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
    this.type = 'ArcCurve';
  }
  ArcCurve.prototype = Object.create(EllipseCurve.prototype);
  ArcCurve.prototype.constructor = ArcCurve;
  ArcCurve.prototype.isArcCurve = true;
  var SceneUtils = {
    createMultiMaterialObject: function(geometry, materials) {
      var group = new Group();
      for (var i = 0,
          l = materials.length; i < l; i++) {
        group.add(new Mesh(geometry, materials[i]));
      }
      return group;
    },
    detach: function(child, parent, scene) {
      child.applyMatrix(parent.matrixWorld);
      parent.remove(child);
      scene.add(child);
    },
    attach: function(child, scene, parent) {
      child.applyMatrix(new Matrix4().getInverse(parent.matrixWorld));
      scene.remove(child);
      parent.add(child);
    }
  };
  function Face4(a, b, c, d, normal, color, materialIndex) {
    console.warn('THREE.Face4 has been removed. A THREE.Face3 will be created instead.');
    return new Face3(a, b, c, normal, color, materialIndex);
  }
  var LineStrip = 0;
  var LinePieces = 1;
  function MeshFaceMaterial(materials) {
    console.warn('THREE.MeshFaceMaterial has been removed. Use an Array instead.');
    return materials;
  }
  function MultiMaterial(materials) {
    if (materials === undefined)
      materials = [];
    console.warn('THREE.MultiMaterial has been removed. Use an Array instead.');
    materials.isMultiMaterial = true;
    materials.materials = materials;
    materials.clone = function() {
      return materials.slice();
    };
    return materials;
  }
  function PointCloud(geometry, material) {
    console.warn('THREE.PointCloud has been renamed to THREE.Points.');
    return new Points(geometry, material);
  }
  function Particle(material) {
    console.warn('THREE.Particle has been renamed to THREE.Sprite.');
    return new Sprite(material);
  }
  function ParticleSystem(geometry, material) {
    console.warn('THREE.ParticleSystem has been renamed to THREE.Points.');
    return new Points(geometry, material);
  }
  function PointCloudMaterial(parameters) {
    console.warn('THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.');
    return new PointsMaterial(parameters);
  }
  function ParticleBasicMaterial(parameters) {
    console.warn('THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.');
    return new PointsMaterial(parameters);
  }
  function ParticleSystemMaterial(parameters) {
    console.warn('THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.');
    return new PointsMaterial(parameters);
  }
  function Vertex(x, y, z) {
    console.warn('THREE.Vertex has been removed. Use THREE.Vector3 instead.');
    return new Vector3(x, y, z);
  }
  function DynamicBufferAttribute(array, itemSize) {
    console.warn('THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.');
    return new BufferAttribute(array, itemSize).setDynamic(true);
  }
  function Int8Attribute(array, itemSize) {
    console.warn('THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.');
    return new Int8BufferAttribute(array, itemSize);
  }
  function Uint8Attribute(array, itemSize) {
    console.warn('THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.');
    return new Uint8BufferAttribute(array, itemSize);
  }
  function Uint8ClampedAttribute(array, itemSize) {
    console.warn('THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.');
    return new Uint8ClampedBufferAttribute(array, itemSize);
  }
  function Int16Attribute(array, itemSize) {
    console.warn('THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.');
    return new Int16BufferAttribute(array, itemSize);
  }
  function Uint16Attribute(array, itemSize) {
    console.warn('THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.');
    return new Uint16BufferAttribute(array, itemSize);
  }
  function Int32Attribute(array, itemSize) {
    console.warn('THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.');
    return new Int32BufferAttribute(array, itemSize);
  }
  function Uint32Attribute(array, itemSize) {
    console.warn('THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.');
    return new Uint32BufferAttribute(array, itemSize);
  }
  function Float32Attribute(array, itemSize) {
    console.warn('THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.');
    return new Float32BufferAttribute(array, itemSize);
  }
  function Float64Attribute(array, itemSize) {
    console.warn('THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.');
    return new Float64BufferAttribute(array, itemSize);
  }
  Curve.create = function(construct, getPoint) {
    console.log('THREE.Curve.create() has been deprecated');
    construct.prototype = Object.create(Curve.prototype);
    construct.prototype.constructor = construct;
    construct.prototype.getPoint = getPoint;
    return construct;
  };
  Object.assign(CurvePath.prototype, {
    createPointsGeometry: function(divisions) {
      console.warn('THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.');
      var pts = this.getPoints(divisions);
      return this.createGeometry(pts);
    },
    createSpacedPointsGeometry: function(divisions) {
      console.warn('THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.');
      var pts = this.getSpacedPoints(divisions);
      return this.createGeometry(pts);
    },
    createGeometry: function(points) {
      console.warn('THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.');
      var geometry = new Geometry();
      for (var i = 0,
          l = points.length; i < l; i++) {
        var point = points[i];
        geometry.vertices.push(new Vector3(point.x, point.y, point.z || 0));
      }
      return geometry;
    }
  });
  Object.assign(Path.prototype, {fromPoints: function(points) {
      console.warn('THREE.Path: .fromPoints() has been renamed to .setFromPoints().');
      this.setFromPoints(points);
    }});
  function ClosedSplineCurve3(points) {
    console.warn('THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.');
    CatmullRomCurve3.call(this, points);
    this.type = 'catmullrom';
    this.closed = true;
  }
  ClosedSplineCurve3.prototype = Object.create(CatmullRomCurve3.prototype);
  function SplineCurve3(points) {
    console.warn('THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.');
    CatmullRomCurve3.call(this, points);
    this.type = 'catmullrom';
  }
  SplineCurve3.prototype = Object.create(CatmullRomCurve3.prototype);
  function Spline(points) {
    console.warn('THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.');
    CatmullRomCurve3.call(this, points);
    this.type = 'catmullrom';
  }
  Spline.prototype = Object.create(CatmullRomCurve3.prototype);
  Object.assign(Spline.prototype, {
    initFromArray: function() {
      console.error('THREE.Spline: .initFromArray() has been removed.');
    },
    getControlPointsArray: function() {
      console.error('THREE.Spline: .getControlPointsArray() has been removed.');
    },
    reparametrizeByArcLength: function() {
      console.error('THREE.Spline: .reparametrizeByArcLength() has been removed.');
    }
  });
  function AxisHelper(size) {
    console.warn('THREE.AxisHelper has been renamed to THREE.AxesHelper.');
    return new AxesHelper(size);
  }
  function BoundingBoxHelper(object, color) {
    console.warn('THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.');
    return new BoxHelper(object, color);
  }
  function EdgesHelper(object, hex) {
    console.warn('THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.');
    return new LineSegments(new EdgesGeometry(object.geometry), new LineBasicMaterial({color: hex !== undefined ? hex : 0xffffff}));
  }
  GridHelper.prototype.setColors = function() {
    console.error('THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.');
  };
  SkeletonHelper.prototype.update = function() {
    console.error('THREE.SkeletonHelper: update() no longer needs to be called.');
  };
  function WireframeHelper(object, hex) {
    console.warn('THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.');
    return new LineSegments(new WireframeGeometry(object.geometry), new LineBasicMaterial({color: hex !== undefined ? hex : 0xffffff}));
  }
  function XHRLoader(manager) {
    console.warn('THREE.XHRLoader has been renamed to THREE.FileLoader.');
    return new FileLoader(manager);
  }
  function BinaryTextureLoader(manager) {
    console.warn('THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.');
    return new DataTextureLoader(manager);
  }
  Object.assign(Box2.prototype, {
    center: function(optionalTarget) {
      console.warn('THREE.Box2: .center() has been renamed to .getCenter().');
      return this.getCenter(optionalTarget);
    },
    empty: function() {
      console.warn('THREE.Box2: .empty() has been renamed to .isEmpty().');
      return this.isEmpty();
    },
    isIntersectionBox: function(box) {
      console.warn('THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().');
      return this.intersectsBox(box);
    },
    size: function(optionalTarget) {
      console.warn('THREE.Box2: .size() has been renamed to .getSize().');
      return this.getSize(optionalTarget);
    }
  });
  Object.assign(Box3.prototype, {
    center: function(optionalTarget) {
      console.warn('THREE.Box3: .center() has been renamed to .getCenter().');
      return this.getCenter(optionalTarget);
    },
    empty: function() {
      console.warn('THREE.Box3: .empty() has been renamed to .isEmpty().');
      return this.isEmpty();
    },
    isIntersectionBox: function(box) {
      console.warn('THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().');
      return this.intersectsBox(box);
    },
    isIntersectionSphere: function(sphere) {
      console.warn('THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().');
      return this.intersectsSphere(sphere);
    },
    size: function(optionalTarget) {
      console.warn('THREE.Box3: .size() has been renamed to .getSize().');
      return this.getSize(optionalTarget);
    }
  });
  Line3.prototype.center = function(optionalTarget) {
    console.warn('THREE.Line3: .center() has been renamed to .getCenter().');
    return this.getCenter(optionalTarget);
  };
  Object.assign(_Math, {
    random16: function() {
      console.warn('THREE.Math: .random16() has been deprecated. Use Math.random() instead.');
      return Math.random();
    },
    nearestPowerOfTwo: function(value) {
      console.warn('THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().');
      return _Math.floorPowerOfTwo(value);
    },
    nextPowerOfTwo: function(value) {
      console.warn('THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().');
      return _Math.ceilPowerOfTwo(value);
    }
  });
  Object.assign(Matrix3.prototype, {
    flattenToArrayOffset: function(array, offset) {
      console.warn("THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");
      return this.toArray(array, offset);
    },
    multiplyVector3: function(vector) {
      console.warn('THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.');
      return vector.applyMatrix3(this);
    },
    multiplyVector3Array: function() {
      console.error('THREE.Matrix3: .multiplyVector3Array() has been removed.');
    },
    applyToBuffer: function(buffer) {
      console.warn('THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.');
      return this.applyToBufferAttribute(buffer);
    },
    applyToVector3Array: function() {
      console.error('THREE.Matrix3: .applyToVector3Array() has been removed.');
    }
  });
  Object.assign(Matrix4.prototype, {
    extractPosition: function(m) {
      console.warn('THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().');
      return this.copyPosition(m);
    },
    flattenToArrayOffset: function(array, offset) {
      console.warn("THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.");
      return this.toArray(array, offset);
    },
    getPosition: function() {
      var v1;
      return function getPosition() {
        if (v1 === undefined)
          v1 = new Vector3();
        console.warn('THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.');
        return v1.setFromMatrixColumn(this, 3);
      };
    }(),
    setRotationFromQuaternion: function(q) {
      console.warn('THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().');
      return this.makeRotationFromQuaternion(q);
    },
    multiplyToArray: function() {
      console.warn('THREE.Matrix4: .multiplyToArray() has been removed.');
    },
    multiplyVector3: function(vector) {
      console.warn('THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.');
      return vector.applyMatrix4(this);
    },
    multiplyVector4: function(vector) {
      console.warn('THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.');
      return vector.applyMatrix4(this);
    },
    multiplyVector3Array: function() {
      console.error('THREE.Matrix4: .multiplyVector3Array() has been removed.');
    },
    rotateAxis: function(v) {
      console.warn('THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.');
      v.transformDirection(this);
    },
    crossVector: function(vector) {
      console.warn('THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.');
      return vector.applyMatrix4(this);
    },
    translate: function() {
      console.error('THREE.Matrix4: .translate() has been removed.');
    },
    rotateX: function() {
      console.error('THREE.Matrix4: .rotateX() has been removed.');
    },
    rotateY: function() {
      console.error('THREE.Matrix4: .rotateY() has been removed.');
    },
    rotateZ: function() {
      console.error('THREE.Matrix4: .rotateZ() has been removed.');
    },
    rotateByAxis: function() {
      console.error('THREE.Matrix4: .rotateByAxis() has been removed.');
    },
    applyToBuffer: function(buffer) {
      console.warn('THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.');
      return this.applyToBufferAttribute(buffer);
    },
    applyToVector3Array: function() {
      console.error('THREE.Matrix4: .applyToVector3Array() has been removed.');
    },
    makeFrustum: function(left, right, bottom, top, near, far) {
      console.warn('THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.');
      return this.makePerspective(left, right, top, bottom, near, far);
    }
  });
  Plane.prototype.isIntersectionLine = function(line) {
    console.warn('THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().');
    return this.intersectsLine(line);
  };
  Quaternion.prototype.multiplyVector3 = function(vector) {
    console.warn('THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.');
    return vector.applyQuaternion(this);
  };
  Object.assign(Ray.prototype, {
    isIntersectionBox: function(box) {
      console.warn('THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().');
      return this.intersectsBox(box);
    },
    isIntersectionPlane: function(plane) {
      console.warn('THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().');
      return this.intersectsPlane(plane);
    },
    isIntersectionSphere: function(sphere) {
      console.warn('THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().');
      return this.intersectsSphere(sphere);
    }
  });
  Object.assign(Shape.prototype, {
    extractAllPoints: function(divisions) {
      console.warn('THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.');
      return this.extractPoints(divisions);
    },
    extrude: function(options) {
      console.warn('THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.');
      return new ExtrudeGeometry(this, options);
    },
    makeGeometry: function(options) {
      console.warn('THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.');
      return new ShapeGeometry(this, options);
    }
  });
  Object.assign(Vector2.prototype, {
    fromAttribute: function(attribute, index, offset) {
      console.warn('THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().');
      return this.fromBufferAttribute(attribute, index, offset);
    },
    distanceToManhattan: function(v) {
      console.warn('THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().');
      return this.manhattanDistanceTo(v);
    },
    lengthManhattan: function() {
      console.warn('THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().');
      return this.manhattanLength();
    }
  });
  Object.assign(Vector3.prototype, {
    setEulerFromRotationMatrix: function() {
      console.error('THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.');
    },
    setEulerFromQuaternion: function() {
      console.error('THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.');
    },
    getPositionFromMatrix: function(m) {
      console.warn('THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().');
      return this.setFromMatrixPosition(m);
    },
    getScaleFromMatrix: function(m) {
      console.warn('THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().');
      return this.setFromMatrixScale(m);
    },
    getColumnFromMatrix: function(index, matrix) {
      console.warn('THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().');
      return this.setFromMatrixColumn(matrix, index);
    },
    applyProjection: function(m) {
      console.warn('THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.');
      return this.applyMatrix4(m);
    },
    fromAttribute: function(attribute, index, offset) {
      console.warn('THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().');
      return this.fromBufferAttribute(attribute, index, offset);
    },
    distanceToManhattan: function(v) {
      console.warn('THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().');
      return this.manhattanDistanceTo(v);
    },
    lengthManhattan: function() {
      console.warn('THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().');
      return this.manhattanLength();
    }
  });
  Object.assign(Vector4.prototype, {
    fromAttribute: function(attribute, index, offset) {
      console.warn('THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().');
      return this.fromBufferAttribute(attribute, index, offset);
    },
    lengthManhattan: function() {
      console.warn('THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().');
      return this.manhattanLength();
    }
  });
  Geometry.prototype.computeTangents = function() {
    console.warn('THREE.Geometry: .computeTangents() has been removed.');
  };
  Object.assign(Object3D.prototype, {
    getChildByName: function(name) {
      console.warn('THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().');
      return this.getObjectByName(name);
    },
    renderDepth: function() {
      console.warn('THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.');
    },
    translate: function(distance, axis) {
      console.warn('THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.');
      return this.translateOnAxis(axis, distance);
    }
  });
  Object.defineProperties(Object3D.prototype, {
    eulerOrder: {
      get: function() {
        console.warn('THREE.Object3D: .eulerOrder is now .rotation.order.');
        return this.rotation.order;
      },
      set: function(value) {
        console.warn('THREE.Object3D: .eulerOrder is now .rotation.order.');
        this.rotation.order = value;
      }
    },
    useQuaternion: {
      get: function() {
        console.warn('THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.');
      },
      set: function() {
        console.warn('THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.');
      }
    }
  });
  Object.defineProperties(LOD.prototype, {objects: {get: function() {
        console.warn('THREE.LOD: .objects has been renamed to .levels.');
        return this.levels;
      }}});
  Object.defineProperty(Skeleton.prototype, 'useVertexTexture', {
    get: function() {
      console.warn('THREE.Skeleton: useVertexTexture has been removed.');
    },
    set: function() {
      console.warn('THREE.Skeleton: useVertexTexture has been removed.');
    }
  });
  Object.defineProperty(Curve.prototype, '__arcLengthDivisions', {
    get: function() {
      console.warn('THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.');
      return this.arcLengthDivisions;
    },
    set: function(value) {
      console.warn('THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.');
      this.arcLengthDivisions = value;
    }
  });
  PerspectiveCamera.prototype.setLens = function(focalLength, filmGauge) {
    console.warn("THREE.PerspectiveCamera.setLens is deprecated. " + "Use .setFocalLength and .filmGauge for a photographic setup.");
    if (filmGauge !== undefined)
      this.filmGauge = filmGauge;
    this.setFocalLength(focalLength);
  };
  Object.defineProperties(Light.prototype, {
    onlyShadow: {set: function() {
        console.warn('THREE.Light: .onlyShadow has been removed.');
      }},
    shadowCameraFov: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraFov is now .shadow.camera.fov.');
        this.shadow.camera.fov = value;
      }},
    shadowCameraLeft: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraLeft is now .shadow.camera.left.');
        this.shadow.camera.left = value;
      }},
    shadowCameraRight: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraRight is now .shadow.camera.right.');
        this.shadow.camera.right = value;
      }},
    shadowCameraTop: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraTop is now .shadow.camera.top.');
        this.shadow.camera.top = value;
      }},
    shadowCameraBottom: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.');
        this.shadow.camera.bottom = value;
      }},
    shadowCameraNear: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraNear is now .shadow.camera.near.');
        this.shadow.camera.near = value;
      }},
    shadowCameraFar: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraFar is now .shadow.camera.far.');
        this.shadow.camera.far = value;
      }},
    shadowCameraVisible: {set: function() {
        console.warn('THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.');
      }},
    shadowBias: {set: function(value) {
        console.warn('THREE.Light: .shadowBias is now .shadow.bias.');
        this.shadow.bias = value;
      }},
    shadowDarkness: {set: function() {
        console.warn('THREE.Light: .shadowDarkness has been removed.');
      }},
    shadowMapWidth: {set: function(value) {
        console.warn('THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.');
        this.shadow.mapSize.width = value;
      }},
    shadowMapHeight: {set: function(value) {
        console.warn('THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.');
        this.shadow.mapSize.height = value;
      }}
  });
  Object.defineProperties(BufferAttribute.prototype, {length: {get: function() {
        console.warn('THREE.BufferAttribute: .length has been deprecated. Use .count instead.');
        return this.array.length;
      }}});
  Object.assign(BufferGeometry.prototype, {
    addIndex: function(index) {
      console.warn('THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().');
      this.setIndex(index);
    },
    addDrawCall: function(start, count, indexOffset) {
      if (indexOffset !== undefined) {
        console.warn('THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.');
      }
      console.warn('THREE.BufferGeometry: .addDrawCall() is now .addGroup().');
      this.addGroup(start, count);
    },
    clearDrawCalls: function() {
      console.warn('THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().');
      this.clearGroups();
    },
    computeTangents: function() {
      console.warn('THREE.BufferGeometry: .computeTangents() has been removed.');
    },
    computeOffsets: function() {
      console.warn('THREE.BufferGeometry: .computeOffsets() has been removed.');
    }
  });
  Object.defineProperties(BufferGeometry.prototype, {
    drawcalls: {get: function() {
        console.error('THREE.BufferGeometry: .drawcalls has been renamed to .groups.');
        return this.groups;
      }},
    offsets: {get: function() {
        console.warn('THREE.BufferGeometry: .offsets has been renamed to .groups.');
        return this.groups;
      }}
  });
  Object.defineProperties(Uniform.prototype, {
    dynamic: {set: function() {
        console.warn('THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.');
      }},
    onUpdate: {value: function() {
        console.warn('THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.');
        return this;
      }}
  });
  Object.defineProperties(Material.prototype, {
    wrapAround: {
      get: function() {
        console.warn('THREE.Material: .wrapAround has been removed.');
      },
      set: function() {
        console.warn('THREE.Material: .wrapAround has been removed.');
      }
    },
    wrapRGB: {get: function() {
        console.warn('THREE.Material: .wrapRGB has been removed.');
        return new Color();
      }},
    shading: {
      get: function() {
        console.error('THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.');
      },
      set: function(value) {
        console.warn('THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.');
        this.flatShading = (value === FlatShading);
      }
    }
  });
  Object.defineProperties(MeshPhongMaterial.prototype, {metal: {
      get: function() {
        console.warn('THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.');
        return false;
      },
      set: function() {
        console.warn('THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead');
      }
    }});
  Object.defineProperties(ShaderMaterial.prototype, {derivatives: {
      get: function() {
        console.warn('THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.');
        return this.extensions.derivatives;
      },
      set: function(value) {
        console.warn('THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.');
        this.extensions.derivatives = value;
      }
    }});
  Object.assign(WebGLRenderer.prototype, {
    getCurrentRenderTarget: function() {
      console.warn('THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().');
      return this.getRenderTarget();
    },
    getMaxAnisotropy: function() {
      console.warn('THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().');
      return this.capabilities.getMaxAnisotropy();
    },
    getPrecision: function() {
      console.warn('THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.');
      return this.capabilities.precision;
    },
    resetGLState: function() {
      console.warn('THREE.WebGLRenderer: .resetGLState() is now .state.reset().');
      return this.state.reset();
    },
    supportsFloatTextures: function() {
      console.warn('THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).');
      return this.extensions.get('OES_texture_float');
    },
    supportsHalfFloatTextures: function() {
      console.warn('THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).');
      return this.extensions.get('OES_texture_half_float');
    },
    supportsStandardDerivatives: function() {
      console.warn('THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).');
      return this.extensions.get('OES_standard_derivatives');
    },
    supportsCompressedTextureS3TC: function() {
      console.warn('THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).');
      return this.extensions.get('WEBGL_compressed_texture_s3tc');
    },
    supportsCompressedTexturePVRTC: function() {
      console.warn('THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).');
      return this.extensions.get('WEBGL_compressed_texture_pvrtc');
    },
    supportsBlendMinMax: function() {
      console.warn('THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).');
      return this.extensions.get('EXT_blend_minmax');
    },
    supportsVertexTextures: function() {
      console.warn('THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.');
      return this.capabilities.vertexTextures;
    },
    supportsInstancedArrays: function() {
      console.warn('THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).');
      return this.extensions.get('ANGLE_instanced_arrays');
    },
    enableScissorTest: function(boolean) {
      console.warn('THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().');
      this.setScissorTest(boolean);
    },
    initMaterial: function() {
      console.warn('THREE.WebGLRenderer: .initMaterial() has been removed.');
    },
    addPrePlugin: function() {
      console.warn('THREE.WebGLRenderer: .addPrePlugin() has been removed.');
    },
    addPostPlugin: function() {
      console.warn('THREE.WebGLRenderer: .addPostPlugin() has been removed.');
    },
    updateShadowMap: function() {
      console.warn('THREE.WebGLRenderer: .updateShadowMap() has been removed.');
    }
  });
  Object.defineProperties(WebGLRenderer.prototype, {
    shadowMapEnabled: {
      get: function() {
        return this.shadowMap.enabled;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.');
        this.shadowMap.enabled = value;
      }
    },
    shadowMapType: {
      get: function() {
        return this.shadowMap.type;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.');
        this.shadowMap.type = value;
      }
    },
    shadowMapCullFace: {
      get: function() {
        return this.shadowMap.cullFace;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.');
        this.shadowMap.cullFace = value;
      }
    }
  });
  Object.defineProperties(WebGLShadowMap.prototype, {cullFace: {
      get: function() {
        return this.renderReverseSided ? CullFaceFront : CullFaceBack;
      },
      set: function(cullFace) {
        var value = (cullFace !== CullFaceBack);
        console.warn("WebGLRenderer: .shadowMap.cullFace is deprecated. Set .shadowMap.renderReverseSided to " + value + ".");
        this.renderReverseSided = value;
      }
    }});
  Object.defineProperties(WebGLRenderTarget.prototype, {
    wrapS: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.');
        return this.texture.wrapS;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.');
        this.texture.wrapS = value;
      }
    },
    wrapT: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.');
        return this.texture.wrapT;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.');
        this.texture.wrapT = value;
      }
    },
    magFilter: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.');
        return this.texture.magFilter;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.');
        this.texture.magFilter = value;
      }
    },
    minFilter: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.');
        return this.texture.minFilter;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.');
        this.texture.minFilter = value;
      }
    },
    anisotropy: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.');
        return this.texture.anisotropy;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.');
        this.texture.anisotropy = value;
      }
    },
    offset: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .offset is now .texture.offset.');
        return this.texture.offset;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .offset is now .texture.offset.');
        this.texture.offset = value;
      }
    },
    repeat: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .repeat is now .texture.repeat.');
        return this.texture.repeat;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .repeat is now .texture.repeat.');
        this.texture.repeat = value;
      }
    },
    format: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .format is now .texture.format.');
        return this.texture.format;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .format is now .texture.format.');
        this.texture.format = value;
      }
    },
    type: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .type is now .texture.type.');
        return this.texture.type;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .type is now .texture.type.');
        this.texture.type = value;
      }
    },
    generateMipmaps: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.');
        return this.texture.generateMipmaps;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.');
        this.texture.generateMipmaps = value;
      }
    }
  });
  Audio.prototype.load = function(file) {
    console.warn('THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.');
    var scope = this;
    var audioLoader = new AudioLoader();
    audioLoader.load(file, function(buffer) {
      scope.setBuffer(buffer);
    });
    return this;
  };
  AudioAnalyser.prototype.getData = function() {
    console.warn('THREE.AudioAnalyser: .getData() is now .getFrequencyData().');
    return this.getFrequencyData();
  };
  CubeCamera.prototype.updateCubeMap = function(renderer, scene) {
    console.warn('THREE.CubeCamera: .updateCubeMap() is now .update().');
    return this.update(renderer, scene);
  };
  var GeometryUtils = {
    merge: function(geometry1, geometry2, materialIndexOffset) {
      console.warn('THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.');
      var matrix;
      if (geometry2.isMesh) {
        geometry2.matrixAutoUpdate && geometry2.updateMatrix();
        matrix = geometry2.matrix;
        geometry2 = geometry2.geometry;
      }
      geometry1.merge(geometry2, matrix, materialIndexOffset);
    },
    center: function(geometry) {
      console.warn('THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.');
      return geometry.center();
    }
  };
  var ImageUtils = {
    crossOrigin: undefined,
    loadTexture: function(url, mapping, onLoad, onError) {
      console.warn('THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.');
      var loader = new TextureLoader();
      loader.setCrossOrigin(this.crossOrigin);
      var texture = loader.load(url, onLoad, undefined, onError);
      if (mapping)
        texture.mapping = mapping;
      return texture;
    },
    loadTextureCube: function(urls, mapping, onLoad, onError) {
      console.warn('THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.');
      var loader = new CubeTextureLoader();
      loader.setCrossOrigin(this.crossOrigin);
      var texture = loader.load(urls, onLoad, undefined, onError);
      if (mapping)
        texture.mapping = mapping;
      return texture;
    },
    loadCompressedTexture: function() {
      console.error('THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.');
    },
    loadCompressedTextureCube: function() {
      console.error('THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.');
    }
  };
  function Projector() {
    console.error('THREE.Projector has been moved to /examples/js/renderers/Projector.js.');
    this.projectVector = function(vector, camera) {
      console.warn('THREE.Projector: .projectVector() is now vector.project().');
      vector.project(camera);
    };
    this.unprojectVector = function(vector, camera) {
      console.warn('THREE.Projector: .unprojectVector() is now vector.unproject().');
      vector.unproject(camera);
    };
    this.pickingRay = function() {
      console.error('THREE.Projector: .pickingRay() is now raycaster.setFromCamera().');
    };
  }
  function CanvasRenderer() {
    console.error('THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js');
    this.domElement = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
    this.clear = function() {};
    this.render = function() {};
    this.setClearColor = function() {};
    this.setSize = function() {};
  }
  exports.WebGLRenderTargetCube = WebGLRenderTargetCube;
  exports.WebGLRenderTarget = WebGLRenderTarget;
  exports.WebGLRenderer = WebGLRenderer;
  exports.ShaderLib = ShaderLib;
  exports.UniformsLib = UniformsLib;
  exports.UniformsUtils = UniformsUtils;
  exports.ShaderChunk = ShaderChunk;
  exports.FogExp2 = FogExp2;
  exports.Fog = Fog;
  exports.Scene = Scene;
  exports.LensFlare = LensFlare;
  exports.Sprite = Sprite;
  exports.LOD = LOD;
  exports.SkinnedMesh = SkinnedMesh;
  exports.Skeleton = Skeleton;
  exports.Bone = Bone;
  exports.Mesh = Mesh;
  exports.LineSegments = LineSegments;
  exports.LineLoop = LineLoop;
  exports.Line = Line;
  exports.Points = Points;
  exports.Group = Group;
  exports.VideoTexture = VideoTexture;
  exports.DataTexture = DataTexture;
  exports.CompressedTexture = CompressedTexture;
  exports.CubeTexture = CubeTexture;
  exports.CanvasTexture = CanvasTexture;
  exports.DepthTexture = DepthTexture;
  exports.Texture = Texture;
  exports.CompressedTextureLoader = CompressedTextureLoader;
  exports.DataTextureLoader = DataTextureLoader;
  exports.CubeTextureLoader = CubeTextureLoader;
  exports.TextureLoader = TextureLoader;
  exports.ObjectLoader = ObjectLoader;
  exports.MaterialLoader = MaterialLoader;
  exports.BufferGeometryLoader = BufferGeometryLoader;
  exports.DefaultLoadingManager = DefaultLoadingManager;
  exports.LoadingManager = LoadingManager;
  exports.JSONLoader = JSONLoader;
  exports.ImageLoader = ImageLoader;
  exports.FontLoader = FontLoader;
  exports.FileLoader = FileLoader;
  exports.Loader = Loader;
  exports.Cache = Cache;
  exports.AudioLoader = AudioLoader;
  exports.SpotLightShadow = SpotLightShadow;
  exports.SpotLight = SpotLight;
  exports.PointLight = PointLight;
  exports.RectAreaLight = RectAreaLight;
  exports.HemisphereLight = HemisphereLight;
  exports.DirectionalLightShadow = DirectionalLightShadow;
  exports.DirectionalLight = DirectionalLight;
  exports.AmbientLight = AmbientLight;
  exports.LightShadow = LightShadow;
  exports.Light = Light;
  exports.StereoCamera = StereoCamera;
  exports.PerspectiveCamera = PerspectiveCamera;
  exports.OrthographicCamera = OrthographicCamera;
  exports.CubeCamera = CubeCamera;
  exports.ArrayCamera = ArrayCamera;
  exports.Camera = Camera;
  exports.AudioListener = AudioListener;
  exports.PositionalAudio = PositionalAudio;
  exports.AudioContext = AudioContext;
  exports.AudioAnalyser = AudioAnalyser;
  exports.Audio = Audio;
  exports.VectorKeyframeTrack = VectorKeyframeTrack;
  exports.StringKeyframeTrack = StringKeyframeTrack;
  exports.QuaternionKeyframeTrack = QuaternionKeyframeTrack;
  exports.NumberKeyframeTrack = NumberKeyframeTrack;
  exports.ColorKeyframeTrack = ColorKeyframeTrack;
  exports.BooleanKeyframeTrack = BooleanKeyframeTrack;
  exports.PropertyMixer = PropertyMixer;
  exports.PropertyBinding = PropertyBinding;
  exports.KeyframeTrack = KeyframeTrack;
  exports.AnimationUtils = AnimationUtils;
  exports.AnimationObjectGroup = AnimationObjectGroup;
  exports.AnimationMixer = AnimationMixer;
  exports.AnimationClip = AnimationClip;
  exports.Uniform = Uniform;
  exports.InstancedBufferGeometry = InstancedBufferGeometry;
  exports.BufferGeometry = BufferGeometry;
  exports.Geometry = Geometry;
  exports.InterleavedBufferAttribute = InterleavedBufferAttribute;
  exports.InstancedInterleavedBuffer = InstancedInterleavedBuffer;
  exports.InterleavedBuffer = InterleavedBuffer;
  exports.InstancedBufferAttribute = InstancedBufferAttribute;
  exports.Face3 = Face3;
  exports.Object3D = Object3D;
  exports.Raycaster = Raycaster;
  exports.Layers = Layers;
  exports.EventDispatcher = EventDispatcher;
  exports.Clock = Clock;
  exports.QuaternionLinearInterpolant = QuaternionLinearInterpolant;
  exports.LinearInterpolant = LinearInterpolant;
  exports.DiscreteInterpolant = DiscreteInterpolant;
  exports.CubicInterpolant = CubicInterpolant;
  exports.Interpolant = Interpolant;
  exports.Triangle = Triangle;
  exports.Math = _Math;
  exports.Spherical = Spherical;
  exports.Cylindrical = Cylindrical;
  exports.Plane = Plane;
  exports.Frustum = Frustum;
  exports.Sphere = Sphere;
  exports.Ray = Ray;
  exports.Matrix4 = Matrix4;
  exports.Matrix3 = Matrix3;
  exports.Box3 = Box3;
  exports.Box2 = Box2;
  exports.Line3 = Line3;
  exports.Euler = Euler;
  exports.Vector4 = Vector4;
  exports.Vector3 = Vector3;
  exports.Vector2 = Vector2;
  exports.Quaternion = Quaternion;
  exports.Color = Color;
  exports.ImmediateRenderObject = ImmediateRenderObject;
  exports.VertexNormalsHelper = VertexNormalsHelper;
  exports.SpotLightHelper = SpotLightHelper;
  exports.SkeletonHelper = SkeletonHelper;
  exports.PointLightHelper = PointLightHelper;
  exports.RectAreaLightHelper = RectAreaLightHelper;
  exports.HemisphereLightHelper = HemisphereLightHelper;
  exports.GridHelper = GridHelper;
  exports.PolarGridHelper = PolarGridHelper;
  exports.FaceNormalsHelper = FaceNormalsHelper;
  exports.DirectionalLightHelper = DirectionalLightHelper;
  exports.CameraHelper = CameraHelper;
  exports.BoxHelper = BoxHelper;
  exports.Box3Helper = Box3Helper;
  exports.PlaneHelper = PlaneHelper;
  exports.ArrowHelper = ArrowHelper;
  exports.AxesHelper = AxesHelper;
  exports.CatmullRomCurve3 = CatmullRomCurve3;
  exports.CubicBezierCurve3 = CubicBezierCurve3;
  exports.QuadraticBezierCurve3 = QuadraticBezierCurve3;
  exports.LineCurve3 = LineCurve3;
  exports.ArcCurve = ArcCurve;
  exports.EllipseCurve = EllipseCurve;
  exports.SplineCurve = SplineCurve;
  exports.CubicBezierCurve = CubicBezierCurve;
  exports.QuadraticBezierCurve = QuadraticBezierCurve;
  exports.LineCurve = LineCurve;
  exports.Shape = Shape;
  exports.Path = Path;
  exports.ShapePath = ShapePath;
  exports.Font = Font;
  exports.CurvePath = CurvePath;
  exports.Curve = Curve;
  exports.ShapeUtils = ShapeUtils;
  exports.SceneUtils = SceneUtils;
  exports.WebGLUtils = WebGLUtils;
  exports.WireframeGeometry = WireframeGeometry;
  exports.ParametricGeometry = ParametricGeometry;
  exports.ParametricBufferGeometry = ParametricBufferGeometry;
  exports.TetrahedronGeometry = TetrahedronGeometry;
  exports.TetrahedronBufferGeometry = TetrahedronBufferGeometry;
  exports.OctahedronGeometry = OctahedronGeometry;
  exports.OctahedronBufferGeometry = OctahedronBufferGeometry;
  exports.IcosahedronGeometry = IcosahedronGeometry;
  exports.IcosahedronBufferGeometry = IcosahedronBufferGeometry;
  exports.DodecahedronGeometry = DodecahedronGeometry;
  exports.DodecahedronBufferGeometry = DodecahedronBufferGeometry;
  exports.PolyhedronGeometry = PolyhedronGeometry;
  exports.PolyhedronBufferGeometry = PolyhedronBufferGeometry;
  exports.TubeGeometry = TubeGeometry;
  exports.TubeBufferGeometry = TubeBufferGeometry;
  exports.TorusKnotGeometry = TorusKnotGeometry;
  exports.TorusKnotBufferGeometry = TorusKnotBufferGeometry;
  exports.TorusGeometry = TorusGeometry;
  exports.TorusBufferGeometry = TorusBufferGeometry;
  exports.TextGeometry = TextGeometry;
  exports.TextBufferGeometry = TextBufferGeometry;
  exports.SphereGeometry = SphereGeometry;
  exports.SphereBufferGeometry = SphereBufferGeometry;
  exports.RingGeometry = RingGeometry;
  exports.RingBufferGeometry = RingBufferGeometry;
  exports.PlaneGeometry = PlaneGeometry;
  exports.PlaneBufferGeometry = PlaneBufferGeometry;
  exports.LatheGeometry = LatheGeometry;
  exports.LatheBufferGeometry = LatheBufferGeometry;
  exports.ShapeGeometry = ShapeGeometry;
  exports.ShapeBufferGeometry = ShapeBufferGeometry;
  exports.ExtrudeGeometry = ExtrudeGeometry;
  exports.ExtrudeBufferGeometry = ExtrudeBufferGeometry;
  exports.EdgesGeometry = EdgesGeometry;
  exports.ConeGeometry = ConeGeometry;
  exports.ConeBufferGeometry = ConeBufferGeometry;
  exports.CylinderGeometry = CylinderGeometry;
  exports.CylinderBufferGeometry = CylinderBufferGeometry;
  exports.CircleGeometry = CircleGeometry;
  exports.CircleBufferGeometry = CircleBufferGeometry;
  exports.BoxGeometry = BoxGeometry;
  exports.BoxBufferGeometry = BoxBufferGeometry;
  exports.ShadowMaterial = ShadowMaterial;
  exports.SpriteMaterial = SpriteMaterial;
  exports.RawShaderMaterial = RawShaderMaterial;
  exports.ShaderMaterial = ShaderMaterial;
  exports.PointsMaterial = PointsMaterial;
  exports.MeshPhysicalMaterial = MeshPhysicalMaterial;
  exports.MeshStandardMaterial = MeshStandardMaterial;
  exports.MeshPhongMaterial = MeshPhongMaterial;
  exports.MeshToonMaterial = MeshToonMaterial;
  exports.MeshNormalMaterial = MeshNormalMaterial;
  exports.MeshLambertMaterial = MeshLambertMaterial;
  exports.MeshDepthMaterial = MeshDepthMaterial;
  exports.MeshDistanceMaterial = MeshDistanceMaterial;
  exports.MeshBasicMaterial = MeshBasicMaterial;
  exports.LineDashedMaterial = LineDashedMaterial;
  exports.LineBasicMaterial = LineBasicMaterial;
  exports.Material = Material;
  exports.Float64BufferAttribute = Float64BufferAttribute;
  exports.Float32BufferAttribute = Float32BufferAttribute;
  exports.Uint32BufferAttribute = Uint32BufferAttribute;
  exports.Int32BufferAttribute = Int32BufferAttribute;
  exports.Uint16BufferAttribute = Uint16BufferAttribute;
  exports.Int16BufferAttribute = Int16BufferAttribute;
  exports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute;
  exports.Uint8BufferAttribute = Uint8BufferAttribute;
  exports.Int8BufferAttribute = Int8BufferAttribute;
  exports.BufferAttribute = BufferAttribute;
  exports.REVISION = REVISION;
  exports.MOUSE = MOUSE;
  exports.CullFaceNone = CullFaceNone;
  exports.CullFaceBack = CullFaceBack;
  exports.CullFaceFront = CullFaceFront;
  exports.CullFaceFrontBack = CullFaceFrontBack;
  exports.FrontFaceDirectionCW = FrontFaceDirectionCW;
  exports.FrontFaceDirectionCCW = FrontFaceDirectionCCW;
  exports.BasicShadowMap = BasicShadowMap;
  exports.PCFShadowMap = PCFShadowMap;
  exports.PCFSoftShadowMap = PCFSoftShadowMap;
  exports.FrontSide = FrontSide;
  exports.BackSide = BackSide;
  exports.DoubleSide = DoubleSide;
  exports.FlatShading = FlatShading;
  exports.SmoothShading = SmoothShading;
  exports.NoColors = NoColors;
  exports.FaceColors = FaceColors;
  exports.VertexColors = VertexColors;
  exports.NoBlending = NoBlending;
  exports.NormalBlending = NormalBlending;
  exports.AdditiveBlending = AdditiveBlending;
  exports.SubtractiveBlending = SubtractiveBlending;
  exports.MultiplyBlending = MultiplyBlending;
  exports.CustomBlending = CustomBlending;
  exports.AddEquation = AddEquation;
  exports.SubtractEquation = SubtractEquation;
  exports.ReverseSubtractEquation = ReverseSubtractEquation;
  exports.MinEquation = MinEquation;
  exports.MaxEquation = MaxEquation;
  exports.ZeroFactor = ZeroFactor;
  exports.OneFactor = OneFactor;
  exports.SrcColorFactor = SrcColorFactor;
  exports.OneMinusSrcColorFactor = OneMinusSrcColorFactor;
  exports.SrcAlphaFactor = SrcAlphaFactor;
  exports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor;
  exports.DstAlphaFactor = DstAlphaFactor;
  exports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;
  exports.DstColorFactor = DstColorFactor;
  exports.OneMinusDstColorFactor = OneMinusDstColorFactor;
  exports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor;
  exports.NeverDepth = NeverDepth;
  exports.AlwaysDepth = AlwaysDepth;
  exports.LessDepth = LessDepth;
  exports.LessEqualDepth = LessEqualDepth;
  exports.EqualDepth = EqualDepth;
  exports.GreaterEqualDepth = GreaterEqualDepth;
  exports.GreaterDepth = GreaterDepth;
  exports.NotEqualDepth = NotEqualDepth;
  exports.MultiplyOperation = MultiplyOperation;
  exports.MixOperation = MixOperation;
  exports.AddOperation = AddOperation;
  exports.NoToneMapping = NoToneMapping;
  exports.LinearToneMapping = LinearToneMapping;
  exports.ReinhardToneMapping = ReinhardToneMapping;
  exports.Uncharted2ToneMapping = Uncharted2ToneMapping;
  exports.CineonToneMapping = CineonToneMapping;
  exports.UVMapping = UVMapping;
  exports.CubeReflectionMapping = CubeReflectionMapping;
  exports.CubeRefractionMapping = CubeRefractionMapping;
  exports.EquirectangularReflectionMapping = EquirectangularReflectionMapping;
  exports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;
  exports.SphericalReflectionMapping = SphericalReflectionMapping;
  exports.CubeUVReflectionMapping = CubeUVReflectionMapping;
  exports.CubeUVRefractionMapping = CubeUVRefractionMapping;
  exports.RepeatWrapping = RepeatWrapping;
  exports.ClampToEdgeWrapping = ClampToEdgeWrapping;
  exports.MirroredRepeatWrapping = MirroredRepeatWrapping;
  exports.NearestFilter = NearestFilter;
  exports.NearestMipMapNearestFilter = NearestMipMapNearestFilter;
  exports.NearestMipMapLinearFilter = NearestMipMapLinearFilter;
  exports.LinearFilter = LinearFilter;
  exports.LinearMipMapNearestFilter = LinearMipMapNearestFilter;
  exports.LinearMipMapLinearFilter = LinearMipMapLinearFilter;
  exports.UnsignedByteType = UnsignedByteType;
  exports.ByteType = ByteType;
  exports.ShortType = ShortType;
  exports.UnsignedShortType = UnsignedShortType;
  exports.IntType = IntType;
  exports.UnsignedIntType = UnsignedIntType;
  exports.FloatType = FloatType;
  exports.HalfFloatType = HalfFloatType;
  exports.UnsignedShort4444Type = UnsignedShort4444Type;
  exports.UnsignedShort5551Type = UnsignedShort5551Type;
  exports.UnsignedShort565Type = UnsignedShort565Type;
  exports.UnsignedInt248Type = UnsignedInt248Type;
  exports.AlphaFormat = AlphaFormat;
  exports.RGBFormat = RGBFormat;
  exports.RGBAFormat = RGBAFormat;
  exports.LuminanceFormat = LuminanceFormat;
  exports.LuminanceAlphaFormat = LuminanceAlphaFormat;
  exports.RGBEFormat = RGBEFormat;
  exports.DepthFormat = DepthFormat;
  exports.DepthStencilFormat = DepthStencilFormat;
  exports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format;
  exports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format;
  exports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format;
  exports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format;
  exports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format;
  exports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format;
  exports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format;
  exports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format;
  exports.RGB_ETC1_Format = RGB_ETC1_Format;
  exports.LoopOnce = LoopOnce;
  exports.LoopRepeat = LoopRepeat;
  exports.LoopPingPong = LoopPingPong;
  exports.InterpolateDiscrete = InterpolateDiscrete;
  exports.InterpolateLinear = InterpolateLinear;
  exports.InterpolateSmooth = InterpolateSmooth;
  exports.ZeroCurvatureEnding = ZeroCurvatureEnding;
  exports.ZeroSlopeEnding = ZeroSlopeEnding;
  exports.WrapAroundEnding = WrapAroundEnding;
  exports.TrianglesDrawMode = TrianglesDrawMode;
  exports.TriangleStripDrawMode = TriangleStripDrawMode;
  exports.TriangleFanDrawMode = TriangleFanDrawMode;
  exports.LinearEncoding = LinearEncoding;
  exports.sRGBEncoding = sRGBEncoding;
  exports.GammaEncoding = GammaEncoding;
  exports.RGBEEncoding = RGBEEncoding;
  exports.LogLuvEncoding = LogLuvEncoding;
  exports.RGBM7Encoding = RGBM7Encoding;
  exports.RGBM16Encoding = RGBM16Encoding;
  exports.RGBDEncoding = RGBDEncoding;
  exports.BasicDepthPacking = BasicDepthPacking;
  exports.RGBADepthPacking = RGBADepthPacking;
  exports.CubeGeometry = BoxGeometry;
  exports.Face4 = Face4;
  exports.LineStrip = LineStrip;
  exports.LinePieces = LinePieces;
  exports.MeshFaceMaterial = MeshFaceMaterial;
  exports.MultiMaterial = MultiMaterial;
  exports.PointCloud = PointCloud;
  exports.Particle = Particle;
  exports.ParticleSystem = ParticleSystem;
  exports.PointCloudMaterial = PointCloudMaterial;
  exports.ParticleBasicMaterial = ParticleBasicMaterial;
  exports.ParticleSystemMaterial = ParticleSystemMaterial;
  exports.Vertex = Vertex;
  exports.DynamicBufferAttribute = DynamicBufferAttribute;
  exports.Int8Attribute = Int8Attribute;
  exports.Uint8Attribute = Uint8Attribute;
  exports.Uint8ClampedAttribute = Uint8ClampedAttribute;
  exports.Int16Attribute = Int16Attribute;
  exports.Uint16Attribute = Uint16Attribute;
  exports.Int32Attribute = Int32Attribute;
  exports.Uint32Attribute = Uint32Attribute;
  exports.Float32Attribute = Float32Attribute;
  exports.Float64Attribute = Float64Attribute;
  exports.ClosedSplineCurve3 = ClosedSplineCurve3;
  exports.SplineCurve3 = SplineCurve3;
  exports.Spline = Spline;
  exports.AxisHelper = AxisHelper;
  exports.BoundingBoxHelper = BoundingBoxHelper;
  exports.EdgesHelper = EdgesHelper;
  exports.WireframeHelper = WireframeHelper;
  exports.XHRLoader = XHRLoader;
  exports.BinaryTextureLoader = BinaryTextureLoader;
  exports.GeometryUtils = GeometryUtils;
  exports.ImageUtils = ImageUtils;
  exports.Projector = Projector;
  exports.CanvasRenderer = CanvasRenderer;
  Object.defineProperty(exports, '__esModule', {value: true});
})));

})();
(function() {
var define = $__System.amdDefine;
define("3", ["4d"], function(main) {
  return main;
});

})();
(function() {
var define = $__System.amdDefine;
(function(global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) : typeof define === 'function' && define.amd ? define("4e", ["exports", "3"], factory) : (factory((global.POSTPROCESSING = {}), global.THREE));
}(this, (function(exports, three) {
  'use strict';
  var fragment = "uniform sampler2D tPreviousLum;\r\nuniform sampler2D tCurrentLum;\r\nuniform float minLuminance;\r\nuniform float delta;\r\nuniform float tau;\r\n\r\nvarying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tfloat previousLum = texture2D(tPreviousLum, vUv, MIP_LEVEL_1X1).r;\r\n\tfloat currentLum = texture2D(tCurrentLum, vUv, MIP_LEVEL_1X1).r;\r\n\r\n\tpreviousLum = max(minLuminance, previousLum);\r\n\tcurrentLum = max(minLuminance, currentLum);\r\n\r\n\t// Adapt the luminance using Pattanaik's technique.\r\n\tfloat adaptedLum = previousLum + (currentLum - previousLum) * (1.0 - exp(-delta * tau));\r\n\r\n\tgl_FragColor.r = adaptedLum;\r\n\r\n}\r\n";
  var vertex = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var asyncGenerator = function() {
    function AwaitValue(value) {
      this.value = value;
    }
    function AsyncGenerator(gen) {
      var front,
          back;
      function send(key, arg) {
        return new Promise(function(resolve, reject) {
          var request = {
            key: key,
            arg: arg,
            resolve: resolve,
            reject: reject,
            next: null
          };
          if (back) {
            back = back.next = request;
          } else {
            front = back = request;
            resume(key, arg);
          }
        });
      }
      function resume(key, arg) {
        try {
          var result = gen[key](arg);
          var value = result.value;
          if (value instanceof AwaitValue) {
            Promise.resolve(value.value).then(function(arg) {
              resume("next", arg);
            }, function(arg) {
              resume("throw", arg);
            });
          } else {
            settle(result.done ? "return" : "normal", result.value);
          }
        } catch (err) {
          settle("throw", err);
        }
      }
      function settle(type, value) {
        switch (type) {
          case "return":
            front.resolve({
              value: value,
              done: true
            });
            break;
          case "throw":
            front.reject(value);
            break;
          default:
            front.resolve({
              value: value,
              done: false
            });
            break;
        }
        front = front.next;
        if (front) {
          resume(front.key, front.arg);
        } else {
          back = null;
        }
      }
      this._invoke = send;
      if (typeof gen.return !== "function") {
        this.return = undefined;
      }
    }
    if (typeof Symbol === "function" && Symbol.asyncIterator) {
      AsyncGenerator.prototype[Symbol.asyncIterator] = function() {
        return this;
      };
    }
    AsyncGenerator.prototype.next = function(arg) {
      return this._invoke("next", arg);
    };
    AsyncGenerator.prototype.throw = function(arg) {
      return this._invoke("throw", arg);
    };
    AsyncGenerator.prototype.return = function(arg) {
      return this._invoke("return", arg);
    };
    return {
      wrap: function(fn) {
        return function() {
          return new AsyncGenerator(fn.apply(this, arguments));
        };
      },
      await: function(value) {
        return new AwaitValue(value);
      }
    };
  }();
  var classCallCheck = function(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  };
  var createClass = function() {
    function defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor)
          descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
      }
    }
    return function(Constructor, protoProps, staticProps) {
      if (protoProps)
        defineProperties(Constructor.prototype, protoProps);
      if (staticProps)
        defineProperties(Constructor, staticProps);
      return Constructor;
    };
  }();
  var inherits = function(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }});
    if (superClass)
      Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  };
  var possibleConstructorReturn = function(self, call) {
    if (!self) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
    return call && (typeof call === "object" || typeof call === "function") ? call : self;
  };
  var AdaptiveLuminosityMaterial = function(_ShaderMaterial) {
    inherits(AdaptiveLuminosityMaterial, _ShaderMaterial);
    function AdaptiveLuminosityMaterial() {
      classCallCheck(this, AdaptiveLuminosityMaterial);
      return possibleConstructorReturn(this, (AdaptiveLuminosityMaterial.__proto__ || Object.getPrototypeOf(AdaptiveLuminosityMaterial)).call(this, {
        type: "AdaptiveLuminosityMaterial",
        defines: {MIP_LEVEL_1X1: "0.0"},
        uniforms: {
          tPreviousLum: new three.Uniform(null),
          tCurrentLum: new three.Uniform(null),
          minLuminance: new three.Uniform(0.01),
          delta: new three.Uniform(0.0),
          tau: new three.Uniform(1.0)
        },
        fragmentShader: fragment,
        vertexShader: vertex,
        depthWrite: false,
        depthTest: false
      }));
    }
    return AdaptiveLuminosityMaterial;
  }(three.ShaderMaterial);
  var fragment$1 = "uniform sampler2D tDiffuse;\r\nuniform sampler2D tDepth;\r\n\r\nuniform float focus;\r\nuniform float dof;\r\nuniform float aspect;\r\nuniform float aperture;\r\nuniform float maxBlur;\r\n\r\nvarying vec2 vUv;\r\n\r\n#ifndef USE_LOGDEPTHBUF\r\n\r\n\t#include <packing>\r\n\r\n\tuniform float cameraNear;\r\n\tuniform float cameraFar;\r\n\r\n\tfloat readDepth(sampler2D depthSampler, vec2 coord) {\r\n\r\n\t\tfloat fragCoordZ = texture2D(depthSampler, coord).x;\r\n\t\tfloat viewZ = perspectiveDepthToViewZ(fragCoordZ, cameraNear, cameraFar);\r\n\r\n\t\treturn viewZToOrthographicDepth(viewZ, cameraNear, cameraFar);\r\n\r\n\t}\r\n\r\n#endif\r\n\r\nvoid main() {\r\n\r\n\tvec2 aspectCorrection = vec2(1.0, aspect);\r\n\r\n\t#ifdef USE_LOGDEPTHBUF\r\n\r\n\t\tfloat depth = texture2D(tDepth, vUv).x;\r\n\r\n\t#else\r\n\r\n\t\tfloat depth = readDepth(tDepth, vUv);\r\n\r\n\t#endif\r\n\r\n\tfloat focusNear = clamp(focus - dof, 0.0, 1.0);\r\n\tfloat focusFar = clamp(focus + dof, 0.0, 1.0);\r\n\r\n\t// Calculate a DoF mask.\r\n\tfloat low = step(depth, focusNear);\r\n\tfloat high = step(focusFar, depth);\r\n\r\n\tfloat factor = (depth - focusNear) * low + (depth - focusFar) * high;\r\n\r\n\tvec2 dofBlur = vec2(clamp(factor * aperture, -maxBlur, maxBlur));\r\n\r\n\tvec2 dofblur9 = dofBlur * 0.9;\r\n\tvec2 dofblur7 = dofBlur * 0.7;\r\n\tvec2 dofblur4 = dofBlur * 0.4;\r\n\r\n\tvec4 color = vec4(0.0);\r\n\r\n\tcolor += texture2D(tDiffuse, vUv);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.0,   0.4 ) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.15,  0.37) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.29,  0.29) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.37,  0.15) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.40,  0.0 ) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.37, -0.15) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.29, -0.29) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.15, -0.37) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.0,  -0.4 ) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.15,  0.37) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.29,  0.29) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.37,  0.15) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.4,   0.0 ) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.37, -0.15) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.29, -0.29) * aspectCorrection) * dofBlur);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.15, -0.37) * aspectCorrection) * dofBlur);\r\n\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.15,  0.37) * aspectCorrection) * dofblur9);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.37,  0.15) * aspectCorrection) * dofblur9);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.37, -0.15) * aspectCorrection) * dofblur9);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.15, -0.37) * aspectCorrection) * dofblur9);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.15,  0.37) * aspectCorrection) * dofblur9);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.37,  0.15) * aspectCorrection) * dofblur9);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.37, -0.15) * aspectCorrection) * dofblur9);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.15, -0.37) * aspectCorrection) * dofblur9);\r\n\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.29,  0.29) * aspectCorrection) * dofblur7);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.40,  0.0 ) * aspectCorrection) * dofblur7);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.29, -0.29) * aspectCorrection) * dofblur7);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.0,  -0.4 ) * aspectCorrection) * dofblur7);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.29,  0.29) * aspectCorrection) * dofblur7);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.4,   0.0 ) * aspectCorrection) * dofblur7);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.29, -0.29) * aspectCorrection) * dofblur7);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.0,   0.4 ) * aspectCorrection) * dofblur7);\r\n\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.29,  0.29) * aspectCorrection) * dofblur4);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.4,   0.0 ) * aspectCorrection) * dofblur4);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.29, -0.29) * aspectCorrection) * dofblur4);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.0,  -0.4 ) * aspectCorrection) * dofblur4);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.29,  0.29) * aspectCorrection) * dofblur4);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.4,   0.0 ) * aspectCorrection) * dofblur4);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2(-0.29, -0.29) * aspectCorrection) * dofblur4);\r\n\tcolor += texture2D(tDiffuse, vUv + (vec2( 0.0,   0.4 ) * aspectCorrection) * dofblur4);\r\n\r\n\tgl_FragColor = color / 41.0;\r\n\r\n}\r\n";
  var vertex$1 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var BokehMaterial = function(_ShaderMaterial) {
    inherits(BokehMaterial, _ShaderMaterial);
    function BokehMaterial() {
      var camera = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      classCallCheck(this, BokehMaterial);
      if (options.focus === undefined) {
        options.focus = 1.0;
      }
      if (options.dof === undefined) {
        options.dof = 0.02;
      }
      if (options.aperture === undefined) {
        options.aperture = 0.025;
      }
      if (options.maxBlur === undefined) {
        options.maxBlur = 1.0;
      }
      var _this = possibleConstructorReturn(this, (BokehMaterial.__proto__ || Object.getPrototypeOf(BokehMaterial)).call(this, {
        type: "BokehMaterial",
        uniforms: {
          cameraNear: new three.Uniform(0.1),
          cameraFar: new three.Uniform(2000),
          aspect: new three.Uniform(1.0),
          tDiffuse: new three.Uniform(null),
          tDepth: new three.Uniform(null),
          focus: new three.Uniform(options.focus),
          dof: new three.Uniform(options.dof),
          aperture: new three.Uniform(options.aperture),
          maxBlur: new three.Uniform(options.maxBlur)
        },
        fragmentShader: fragment$1,
        vertexShader: vertex$1,
        depthWrite: false,
        depthTest: false
      }));
      if (camera !== null) {
        _this.adoptCameraSettings(camera);
      }
      return _this;
    }
    createClass(BokehMaterial, [{
      key: "adoptCameraSettings",
      value: function adoptCameraSettings(camera) {
        this.uniforms.cameraNear.value = camera.near;
        this.uniforms.cameraFar.value = camera.far;
        this.uniforms.aspect.value = camera.aspect;
      }
    }]);
    return BokehMaterial;
  }(three.ShaderMaterial);
  var fragment$2 = "#include <common>\r\n\r\nuniform sampler2D tDiffuse;\r\nuniform sampler2D tDepth;\r\n\r\nuniform vec2 texelSize;\r\nuniform vec2 halfTexelSize;\r\n\r\nuniform float cameraNear;\r\nuniform float cameraFar;\r\n\r\nuniform float focalLength;\r\nuniform float focalStop;\r\n\r\nuniform float maxBlur;\r\nuniform float luminanceThreshold;\r\nuniform float luminanceGain;\r\nuniform float bias;\r\nuniform float fringe;\r\nuniform float ditherStrength;\r\n\r\n#ifdef SHADER_FOCUS\r\n\r\n\tuniform vec2 focusCoords;\r\n\r\n#else\r\n\r\n\tuniform float focalDepth;\r\n\r\n#endif\r\n\r\nvarying vec2 vUv;\r\n\r\n#ifndef USE_LOGDEPTHBUF\r\n\r\n\t#include <packing>\r\n\r\n\tfloat readDepth(sampler2D depthSampler, vec2 coord) {\r\n\r\n\t\tfloat fragCoordZ = texture2D(depthSampler, coord).x;\r\n\t\tfloat viewZ = perspectiveDepthToViewZ(fragCoordZ, cameraNear, cameraFar);\r\n\r\n\t\treturn viewZToOrthographicDepth(viewZ, cameraNear, cameraFar);\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#ifdef PENTAGON\r\n\r\n\tfloat penta(vec2 coords) {\r\n\r\n\t\tconst vec4 HS0 = vec4( 1.0,          0.0,         0.0, 1.0);\r\n\t\tconst vec4 HS1 = vec4( 0.309016994,  0.951056516, 0.0, 1.0);\r\n\t\tconst vec4 HS2 = vec4(-0.809016994,  0.587785252, 0.0, 1.0);\r\n\t\tconst vec4 HS3 = vec4(-0.809016994, -0.587785252, 0.0, 1.0);\r\n\t\tconst vec4 HS4 = vec4( 0.309016994, -0.951056516, 0.0, 1.0);\r\n\t\tconst vec4 HS5 = vec4( 0.0,          0.0,         1.0, 1.0);\r\n\r\n\t\tconst vec4 ONE = vec4(1.0);\r\n\r\n\t\tconst float P_FEATHER = 0.4;\r\n\t\tconst float N_FEATHER = -P_FEATHER;\r\n\r\n\t\tfloat inOrOut = -4.0;\r\n\r\n\t\tvec4 P = vec4(coords, vec2(RINGS_FLOAT - 1.3));\r\n\r\n\t\tvec4 dist = vec4(\r\n\t\t\tdot(P, HS0),\r\n\t\t\tdot(P, HS1),\r\n\t\t\tdot(P, HS2),\r\n\t\t\tdot(P, HS3)\r\n\t\t);\r\n\r\n\t\tdist = smoothstep(N_FEATHER, P_FEATHER, dist);\r\n\r\n\t\tinOrOut += dot(dist, ONE);\r\n\r\n\t\tdist.x = dot(P, HS4);\r\n\t\tdist.y = HS5.w - abs(P.z);\r\n\r\n\t\tdist = smoothstep(N_FEATHER, P_FEATHER, dist);\r\n\t\tinOrOut += dist.x;\r\n\r\n\t\treturn clamp(inOrOut, 0.0, 1.0);\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#ifdef SHOW_FOCUS\r\n\r\n\tvec3 debugFocus(vec3 c, float blur, float depth) {\r\n\r\n\t\tfloat edge = 0.002 * depth;\r\n\t\tfloat m = clamp(smoothstep(0.0, edge, blur), 0.0, 1.0);\r\n\t\tfloat e = clamp(smoothstep(1.0 - edge, 1.0, blur), 0.0, 1.0);\r\n\r\n\t\tc = mix(c, vec3(1.0, 0.5, 0.0), (1.0 - m) * 0.6);\r\n\t\tc = mix(c, vec3(0.0, 0.5, 1.0), ((1.0 - e) - (1.0 - m)) * 0.2);\r\n\r\n\t\treturn c;\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#ifdef VIGNETTE\r\n\r\n\tfloat vignette() {\r\n\r\n\t\tconst vec2 CENTER = vec2(0.5);\r\n\r\n\t\tconst float VIGNETTE_OUT = 1.3;\r\n\t\tconst float VIGNETTE_IN = 0.0;\r\n\t\tconst float VIGNETTE_FADE = 22.0; \r\n\r\n\t\tfloat d = distance(vUv, CENTER);\r\n\t\td = smoothstep(VIGNETTE_OUT + (focalStop / VIGNETTE_FADE), VIGNETTE_IN + (focalStop / VIGNETTE_FADE), d);\r\n\r\n\t\treturn clamp(d, 0.0, 1.0);\r\n\r\n\t}\r\n\r\n#endif\r\n\r\nvec2 rand2(vec2 coord) {\r\n\r\n\tvec2 noise;\r\n\r\n\t#ifdef NOISE\r\n\r\n\t\tconst float a = 12.9898;\r\n\t\tconst float b = 78.233;\r\n\t\tconst float c = 43758.5453;\r\n\r\n\t\tnoise.x = clamp(fract(sin(mod(dot(coord, vec2(a, b)), 3.14)) * c), 0.0, 1.0) * 2.0 - 1.0;\r\n\t\tnoise.y = clamp(fract(sin(mod(dot(coord, vec2(a, b) * 2.0), 3.14)) * c), 0.0, 1.0) * 2.0 - 1.0;\r\n\r\n\t#else\r\n\r\n\t\tnoise.x = ((fract(1.0 - coord.s * halfTexelSize.x) * 0.25) + (fract(coord.t * halfTexelSize.y) * 0.75)) * 2.0 - 1.0;\r\n\t\tnoise.y = ((fract(1.0 - coord.s * halfTexelSize.x) * 0.75) + (fract(coord.t * halfTexelSize.y) * 0.25)) * 2.0 - 1.0;\r\n\r\n\t#endif\r\n\r\n\treturn noise;\r\n\r\n}\r\n\r\nvec3 processTexel(vec2 coords, float blur) {\r\n\r\n\tvec3 c;\r\n\tc.r = texture2D(tDiffuse, coords + vec2(0.0, 1.0) * texelSize * fringe * blur).r;\r\n\tc.g = texture2D(tDiffuse, coords + vec2(-0.866, -0.5) * texelSize * fringe * blur).g;\r\n\tc.b = texture2D(tDiffuse, coords + vec2(0.866, -0.5) * texelSize * fringe * blur).b;\r\n\r\n\t// Calculate the luminance of the constructed colour.\r\n\tfloat luminance = linearToRelativeLuminance(c);\r\n\tfloat threshold = max((luminance - luminanceThreshold) * luminanceGain, 0.0);\r\n\r\n\treturn c + mix(vec3(0.0), c, threshold * blur);\r\n\r\n}\r\n\r\nfloat linearize(float depth) {\r\n\r\n\treturn -cameraFar * cameraNear / (depth * (cameraFar - cameraNear) - cameraFar);\r\n\r\n}\r\n\r\nfloat gather(float i, float j, float ringSamples, inout vec3 color, float w, float h, float blur) {\r\n\r\n\tconst float TWO_PI = 6.28318531;\r\n\r\n\tfloat step = TWO_PI / ringSamples;\r\n\tfloat pw = cos(j * step) * i;\r\n\tfloat ph = sin(j * step) * i;\r\n\r\n\t#ifdef PENTAGON\r\n\r\n\t\tfloat p = penta(vec2(pw, ph));\r\n\r\n\t#else\r\n\r\n\t\tfloat p = 1.0;\r\n\r\n\t#endif\r\n\r\n\tcolor += processTexel(vUv + vec2(pw * w, ph * h), blur) * mix(1.0, i / RINGS_FLOAT, bias) * p;\r\n\r\n\treturn mix(1.0, i / RINGS_FLOAT, bias) * p;\r\n\r\n}\r\n\r\nvoid main() {\r\n\r\n\t#ifdef USE_LOGDEPTHBUF\r\n\r\n\t\tfloat depth = linearize(texture2D(tDepth, vUv).x);\r\n\r\n\t#else\r\n\r\n\t\tfloat depth = linearize(readDepth(tDepth, vUv));\r\n\r\n\t#endif\r\n\r\n\t#ifdef SHADER_FOCUS\r\n\r\n\t\t#ifdef USE_LOGDEPTHBUF\r\n\r\n\t\t\tfloat fDepth = linearize(texture2D(tDepth, focusCoords).x);\r\n\r\n\t\t#else\r\n\r\n\t\t\tfloat fDepth = linearize(readDepth(tDepth, focusCoords));\r\n\r\n\t\t#endif\r\n\r\n\t#else\r\n\r\n\t\tfloat fDepth = focalDepth;\r\n\r\n\t#endif\r\n\r\n\t#ifdef MANUAL_DOF\r\n\r\n\t\tconst float nDoFStart = 1.0; \r\n\t\tconst float nDoFDist = 2.0;\r\n\t\tconst float fDoFStart = 1.0;\r\n\t\tconst float fDoFDist = 3.0;\r\n\r\n\t\tfloat focalPlane = depth - fDepth;\r\n\t\tfloat farDoF = (focalPlane - fDoFStart) / fDoFDist;\r\n\t\tfloat nearDoF = (-focalPlane - nDoFStart) / nDoFDist;\r\n\r\n\t\tfloat blur = (focalPlane > 0.0) ? farDoF : nearDoF;\r\n\r\n\t#else\r\n\r\n\t\tconst float CIRCLE_OF_CONFUSION = 0.03; // 35mm film = 0.03mm CoC.\r\n\r\n\t\tfloat focalPlaneMM = fDepth * 1000.0;\r\n\t\tfloat depthMM = depth * 1000.0;\r\n\r\n\t\tfloat focalPlane = (depthMM * focalLength) / (depthMM - focalLength);\r\n\t\tfloat farDoF = (focalPlaneMM * focalLength) / (focalPlaneMM - focalLength);\r\n\t\tfloat nearDoF = (focalPlaneMM - focalLength) / (focalPlaneMM * focalStop * CIRCLE_OF_CONFUSION);\r\n\r\n\t\tfloat blur = abs(focalPlane - farDoF) * nearDoF;\r\n\r\n\t#endif\r\n\r\n\tblur = clamp(blur, 0.0, 1.0);\r\n\r\n\t// Dithering.\r\n\tvec2 noise = rand2(vUv) * ditherStrength * blur;\r\n\r\n\tfloat blurFactorX = texelSize.x * blur * maxBlur + noise.x;\r\n\tfloat blurFactorY = texelSize.y * blur * maxBlur + noise.y;\r\n\r\n\tconst int MAX_RING_SAMPLES = RINGS_INT * SAMPLES_INT;\r\n\r\n\t// Calculation of final color.\r\n\tvec4 color;\r\n\r\n\tif(blur < 0.05) {\r\n\r\n\t\tcolor = texture2D(tDiffuse, vUv);\r\n\r\n\t} else {\r\n\r\n\t\tcolor = texture2D(tDiffuse, vUv);\r\n\r\n\t\tfloat s = 1.0;\r\n\t\tint ringSamples;\r\n\r\n\t\tfor(int i = 1; i <= RINGS_INT; ++i) {\r\n\r\n\t\t\tringSamples = i * SAMPLES_INT;\r\n\r\n\t\t\t// Constant loop.\r\n\t\t\tfor(int j = 0; j < MAX_RING_SAMPLES; ++j) {\r\n\r\n\t\t\t\t// Break earlier.\r\n\t\t\t\tif(j >= ringSamples) { break; }\r\n\r\n\t\t\t\ts += gather(float(i), float(j), float(ringSamples), color.rgb, blurFactorX, blurFactorY, blur);\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tcolor.rgb /= s; // Divide by sample count.\r\n\r\n\t}\r\n\r\n\t#ifdef SHOW_FOCUS\r\n\r\n\t\tcolor.rgb = debugFocus(color.rgb, blur, depth);\r\n\r\n\t#endif\r\n\r\n\t#ifdef VIGNETTE\r\n\r\n\t\tcolor.rgb *= vignette();\r\n\r\n\t#endif\r\n\r\n\tgl_FragColor = color;\r\n\r\n}\r\n";
  var vertex$2 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var Bokeh2Material = function(_ShaderMaterial) {
    inherits(Bokeh2Material, _ShaderMaterial);
    function Bokeh2Material() {
      var camera = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      classCallCheck(this, Bokeh2Material);
      if (options.rings === undefined) {
        options.rings = 3;
      }
      if (options.samples === undefined) {
        options.samples = 2;
      }
      if (options.showFocus === undefined) {
        options.showFocus = false;
      }
      if (options.showFocus === undefined) {
        options.showFocus = false;
      }
      if (options.manualDoF === undefined) {
        options.manualDoF = false;
      }
      if (options.vignette === undefined) {
        options.vignette = false;
      }
      if (options.pentagon === undefined) {
        options.pentagon = false;
      }
      if (options.shaderFocus === undefined) {
        options.shaderFocus = true;
      }
      if (options.noise === undefined) {
        options.noise = true;
      }
      var _this = possibleConstructorReturn(this, (Bokeh2Material.__proto__ || Object.getPrototypeOf(Bokeh2Material)).call(this, {
        type: "Bokeh2Material",
        defines: {
          RINGS_INT: options.rings.toFixed(0),
          RINGS_FLOAT: options.rings.toFixed(1),
          SAMPLES_INT: options.samples.toFixed(0),
          SAMPLES_FLOAT: options.samples.toFixed(1)
        },
        uniforms: {
          tDiffuse: new three.Uniform(null),
          tDepth: new three.Uniform(null),
          texelSize: new three.Uniform(new three.Vector2()),
          halfTexelSize: new three.Uniform(new three.Vector2()),
          cameraNear: new three.Uniform(0.1),
          cameraFar: new three.Uniform(2000),
          focalLength: new three.Uniform(24.0),
          focalStop: new three.Uniform(0.9),
          maxBlur: new three.Uniform(1.0),
          luminanceThreshold: new three.Uniform(0.5),
          luminanceGain: new three.Uniform(2.0),
          bias: new three.Uniform(0.5),
          fringe: new three.Uniform(0.7),
          ditherStrength: new three.Uniform(0.0001),
          focusCoords: new three.Uniform(new three.Vector2(0.5, 0.5)),
          focalDepth: new three.Uniform(1.0)
        },
        fragmentShader: fragment$2,
        vertexShader: vertex$2,
        depthWrite: false,
        depthTest: false
      }));
      if (options.showFocus) {
        _this.defines.SHOW_FOCUS = "1";
      }
      if (options.manualDoF) {
        _this.defines.MANUAL_DOF = "1";
      }
      if (options.vignette) {
        _this.defines.VIGNETTE = "1";
      }
      if (options.pentagon) {
        _this.defines.PENTAGON = "1";
      }
      if (options.shaderFocus) {
        _this.defines.SHADER_FOCUS = "1";
      }
      if (options.noise) {
        _this.defines.NOISE = "1";
      }
      if (options.texelSize !== undefined) {
        _this.setTexelSize(options.texelSize.x, options.texelSize.y);
      }
      if (camera !== null) {
        _this.adoptCameraSettings(camera);
      }
      return _this;
    }
    createClass(Bokeh2Material, [{
      key: "setTexelSize",
      value: function setTexelSize(x, y) {
        this.uniforms.texelSize.value.set(x, y);
        this.uniforms.halfTexelSize.value.set(x, y).multiplyScalar(0.5);
      }
    }, {
      key: "adoptCameraSettings",
      value: function adoptCameraSettings(camera) {
        this.uniforms.cameraNear.value = camera.near;
        this.uniforms.cameraFar.value = camera.far;
        this.uniforms.focalLength.value = camera.getFocalLength();
      }
    }]);
    return Bokeh2Material;
  }(three.ShaderMaterial);
  var fragment$3 = "uniform sampler2D texture1;\r\nuniform sampler2D texture2;\r\n\r\nuniform float opacity1;\r\nuniform float opacity2;\r\n\r\nvarying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvec4 texel1 = opacity1 * texture2D(texture1, vUv);\r\n\tvec4 texel2 = opacity2 * texture2D(texture2, vUv);\r\n\r\n\t#ifdef SCREEN_MODE\r\n\r\n\t\tvec3 invTexel1 = vec3(1.0) - texel1.rgb;\r\n\t\tvec3 invTexel2 = vec3(1.0) - texel2.rgb;\r\n\r\n\t\tvec4 color = vec4(\r\n\t\t\tvec3(1.0) - invTexel1 * invTexel2,\r\n\t\t\ttexel1.a + texel2.a\r\n\t\t);\r\n\r\n\t#else\r\n\r\n\t\tvec4 color = texel1 + texel2;\r\n\r\n\t#endif\r\n\r\n\tgl_FragColor = color;\r\n\r\n}\r\n";
  var vertex$3 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var CombineMaterial = function(_ShaderMaterial) {
    inherits(CombineMaterial, _ShaderMaterial);
    function CombineMaterial() {
      var screenMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      classCallCheck(this, CombineMaterial);
      var _this = possibleConstructorReturn(this, (CombineMaterial.__proto__ || Object.getPrototypeOf(CombineMaterial)).call(this, {
        type: "CombineMaterial",
        uniforms: {
          texture1: new three.Uniform(null),
          texture2: new three.Uniform(null),
          opacity1: new three.Uniform(1.0),
          opacity2: new three.Uniform(1.0)
        },
        fragmentShader: fragment$3,
        vertexShader: vertex$3,
        depthWrite: false,
        depthTest: false
      }));
      if (screenMode) {
        _this.defines.SCREEN_MODE = "1";
      }
      return _this;
    }
    return CombineMaterial;
  }(three.ShaderMaterial);
  var fragment$4 = "uniform sampler2D tDiffuse;\r\n\r\nvarying vec2 vUv0;\r\nvarying vec2 vUv1;\r\nvarying vec2 vUv2;\r\nvarying vec2 vUv3;\r\n\r\nvoid main() {\r\n\r\n\t// Sample top left texel.\r\n\tvec4 sum = texture2D(tDiffuse, vUv0);\r\n\r\n\t// Sample top right texel.\r\n\tsum += texture2D(tDiffuse, vUv1);\r\n\r\n\t// Sample bottom right texel.\r\n\tsum += texture2D(tDiffuse, vUv2);\r\n\r\n\t// Sample bottom left texel.\r\n\tsum += texture2D(tDiffuse, vUv3);\r\n\r\n\t// Compute the average.\r\n\tgl_FragColor = sum * 0.25;\r\n\r\n}\r\n";
  var vertex$4 = "uniform vec2 texelSize;\r\nuniform vec2 halfTexelSize;\r\nuniform float kernel;\r\n\r\nvarying vec2 vUv0;\r\nvarying vec2 vUv1;\r\nvarying vec2 vUv2;\r\nvarying vec2 vUv3;\r\n\r\nvoid main() {\r\n\r\n\tvec2 dUv = (texelSize * vec2(kernel)) + halfTexelSize;\r\n\r\n\tvUv0 = vec2(uv.x - dUv.x, uv.y + dUv.y);\r\n\tvUv1 = vec2(uv.x + dUv.x, uv.y + dUv.y);\r\n\tvUv2 = vec2(uv.x + dUv.x, uv.y - dUv.y);\r\n\tvUv3 = vec2(uv.x - dUv.x, uv.y - dUv.y);\r\n\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var ConvolutionMaterial = function(_ShaderMaterial) {
    inherits(ConvolutionMaterial, _ShaderMaterial);
    function ConvolutionMaterial() {
      var texelSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new three.Vector2();
      classCallCheck(this, ConvolutionMaterial);
      var _this = possibleConstructorReturn(this, (ConvolutionMaterial.__proto__ || Object.getPrototypeOf(ConvolutionMaterial)).call(this, {
        type: "ConvolutionMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          texelSize: new three.Uniform(new three.Vector2()),
          halfTexelSize: new three.Uniform(new three.Vector2()),
          kernel: new three.Uniform(0.0)
        },
        fragmentShader: fragment$4,
        vertexShader: vertex$4,
        depthWrite: false,
        depthTest: false
      }));
      _this.setTexelSize(texelSize.x, texelSize.y);
      _this.kernelSize = KernelSize.LARGE;
      return _this;
    }
    createClass(ConvolutionMaterial, [{
      key: "getKernel",
      value: function getKernel() {
        return kernelPresets[this.kernelSize];
      }
    }, {
      key: "setTexelSize",
      value: function setTexelSize(x, y) {
        this.uniforms.texelSize.value.set(x, y);
        this.uniforms.halfTexelSize.value.set(x, y).multiplyScalar(0.5);
      }
    }]);
    return ConvolutionMaterial;
  }(three.ShaderMaterial);
  var kernelPresets = [new Float32Array([0.0, 0.0]), new Float32Array([0.0, 1.0, 1.0]), new Float32Array([0.0, 1.0, 1.0, 2.0]), new Float32Array([0.0, 1.0, 2.0, 2.0, 3.0]), new Float32Array([0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 5.0]), new Float32Array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 8.0, 9.0, 10.0])];
  var KernelSize = {
    VERY_SMALL: 0,
    SMALL: 1,
    MEDIUM: 2,
    LARGE: 3,
    VERY_LARGE: 4,
    HUGE: 5
  };
  var fragment$5 = "uniform sampler2D tDiffuse;\r\nuniform float opacity;\r\n\r\nvarying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvec4 texel = texture2D(tDiffuse, vUv);\r\n\tgl_FragColor = opacity * texel;\r\n\r\n}\r\n";
  var vertex$5 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var CopyMaterial = function(_ShaderMaterial) {
    inherits(CopyMaterial, _ShaderMaterial);
    function CopyMaterial() {
      classCallCheck(this, CopyMaterial);
      return possibleConstructorReturn(this, (CopyMaterial.__proto__ || Object.getPrototypeOf(CopyMaterial)).call(this, {
        type: "CopyMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          opacity: new three.Uniform(1.0)
        },
        fragmentShader: fragment$5,
        vertexShader: vertex$5,
        depthWrite: false,
        depthTest: false
      }));
    }
    return CopyMaterial;
  }(three.ShaderMaterial);
  var fragment$6 = "uniform sampler2D tDiffuse;\r\n\r\nuniform float angle;\r\nuniform float scale;\r\nuniform float intensity;\r\n\r\nvarying vec2 vUv;\r\nvarying vec2 vUvPattern;\r\n\r\nfloat pattern() {\r\n\r\n\tfloat s = sin(angle);\r\n\tfloat c = cos(angle);\r\n\r\n\tvec2 point = vec2(c * vUvPattern.x - s * vUvPattern.y, s * vUvPattern.x + c * vUvPattern.y) * scale;\r\n\r\n\treturn (sin(point.x) * sin(point.y)) * 4.0;\r\n\r\n}\r\n\r\nvoid main() {\r\n\r\n\tvec4 texel = texture2D(tDiffuse, vUv);\r\n\tvec3 color = texel.rgb;\r\n\r\n\t#ifdef AVERAGE\r\n\r\n\t\tcolor = vec3((color.r + color.g + color.b) / 3.0);\r\n\r\n\t#endif\r\n\r\n\tcolor = vec3(color * 10.0 - 5.0 + pattern());\r\n\tcolor = texel.rgb + (color - texel.rgb) * intensity;\r\n\r\n\tgl_FragColor = vec4(color, texel.a);\r\n\r\n}\r\n";
  var vertex$6 = "uniform vec4 offsetRepeat;\r\n\r\nvarying vec2 vUv;\r\nvarying vec2 vUvPattern;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tvUvPattern = uv * offsetRepeat.zw + offsetRepeat.xy;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var DotScreenMaterial = function(_ShaderMaterial) {
    inherits(DotScreenMaterial, _ShaderMaterial);
    function DotScreenMaterial() {
      var average = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      classCallCheck(this, DotScreenMaterial);
      var _this = possibleConstructorReturn(this, (DotScreenMaterial.__proto__ || Object.getPrototypeOf(DotScreenMaterial)).call(this, {
        type: "DotScreenMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          angle: new three.Uniform(1.57),
          scale: new three.Uniform(1.0),
          intensity: new three.Uniform(1.0),
          offsetRepeat: new three.Uniform(new three.Vector4(0.5, 0.5, 1.0, 1.0))
        },
        fragmentShader: fragment$6,
        vertexShader: vertex$6,
        depthWrite: false,
        depthTest: false
      }));
      if (average) {
        _this.defines.AVERAGE = "1";
      }
      return _this;
    }
    return DotScreenMaterial;
  }(three.ShaderMaterial);
  var fragment$7 = "uniform sampler2D tDiffuse;\r\nuniform float time;\r\n\r\nvarying vec2 vUv;\r\n\r\n#ifdef NOISE\r\n\r\n\tuniform float noiseIntensity;\r\n\r\n#endif\r\n\r\n#ifdef SCANLINES\r\n\r\n\tuniform float scanlineIntensity;\r\n\tuniform float scanlineCount;\r\n\r\n#endif\r\n\r\n#ifdef GREYSCALE\r\n\r\n\t#include <common>\r\n\r\n\tuniform float greyscaleIntensity;\r\n\r\n#elif defined(SEPIA)\r\n\r\n\tuniform float sepiaIntensity;\r\n\r\n#endif\r\n\r\n#ifdef VIGNETTE\r\n\r\n\tuniform float vignetteOffset;\r\n\tuniform float vignetteDarkness;\r\n\r\n#endif\r\n\r\nvoid main() {\r\n\r\n\tvec4 texel = texture2D(tDiffuse, vUv);\r\n\tvec3 color = texel.rgb;\r\n\r\n\t#ifdef SCREEN_MODE\r\n\r\n\t\tvec3 invColor;\r\n\r\n\t#endif\r\n\r\n\t#ifdef NOISE\r\n\r\n\t\tfloat x = vUv.x * vUv.y * time * 1000.0;\r\n\t\tx = mod(x, 13.0) * mod(x, 123.0);\r\n\t\tx = mod(x, 0.01);\r\n\r\n\t\tvec3 noise = texel.rgb * clamp(0.1 + x * 100.0, 0.0, 1.0) * noiseIntensity;\r\n\r\n\t\t#ifdef SCREEN_MODE\r\n\r\n\t\t\tinvColor = vec3(1.0) - color;\r\n\t\t\tvec3 invNoise = vec3(1.0) - noise;\r\n\r\n\t\t\tcolor = vec3(1.0) - invColor * invNoise;\r\n\r\n\t\t#else\r\n\r\n\t\t\tcolor += noise;\r\n\r\n\t\t#endif\r\n\r\n\t#endif\r\n\r\n\t#ifdef SCANLINES\r\n\r\n\t\tvec2 sl = vec2(sin(vUv.y * scanlineCount), cos(vUv.y * scanlineCount));\r\n\t\tvec3 scanlines = texel.rgb * vec3(sl.x, sl.y, sl.x) * scanlineIntensity;\r\n\r\n\t\t#ifdef SCREEN_MODE\r\n\r\n\t\t\tinvColor = vec3(1.0) - color;\r\n\t\t\tvec3 invScanlines = vec3(1.0) - scanlines;\r\n\r\n\t\t\tcolor = vec3(1.0) - invColor * invScanlines;\r\n\r\n\t\t#else\r\n\r\n\t\t\tcolor += scanlines;\r\n\r\n\t\t#endif\r\n\r\n\t#endif\r\n\r\n\t#ifdef GREYSCALE\r\n\r\n\t\tcolor = mix(color, vec3(linearToRelativeLuminance(color)), greyscaleIntensity);\r\n\r\n\t#elif defined(SEPIA)\r\n\r\n\t\tvec3 c = color.rgb;\r\n\r\n\t\tcolor.r = dot(c, vec3(1.0 - 0.607 * sepiaIntensity, 0.769 * sepiaIntensity, 0.189 * sepiaIntensity));\r\n\t\tcolor.g = dot(c, vec3(0.349 * sepiaIntensity, 1.0 - 0.314 * sepiaIntensity, 0.168 * sepiaIntensity));\r\n\t\tcolor.b = dot(c, vec3(0.272 * sepiaIntensity, 0.534 * sepiaIntensity, 1.0 - 0.869 * sepiaIntensity));\r\n\r\n\t#endif\r\n\r\n\t#ifdef VIGNETTE\r\n\r\n\t\tconst vec2 center = vec2(0.5);\r\n\r\n\t\t#ifdef ESKIL\r\n\r\n\t\t\tvec2 uv = (vUv - center) * vec2(vignetteOffset);\r\n\t\t\tcolor = mix(color.rgb, vec3(1.0 - vignetteDarkness), dot(uv, uv));\r\n\r\n\t\t#else\r\n\r\n\t\t\tfloat dist = distance(vUv, center);\r\n\t\t\tcolor *= smoothstep(0.8, vignetteOffset * 0.799, dist * (vignetteDarkness + vignetteOffset));\r\n\r\n\t\t#endif\t\t\r\n\r\n\t#endif\r\n\r\n\tgl_FragColor = vec4(clamp(color, 0.0, 1.0), texel.a);\r\n\r\n}\r\n";
  var vertex$7 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var FilmMaterial = function(_ShaderMaterial) {
    inherits(FilmMaterial, _ShaderMaterial);
    function FilmMaterial() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, FilmMaterial);
      if (options.screenMode === undefined) {
        options.screenMode = true;
      }
      if (options.noise === undefined) {
        options.noise = true;
      }
      if (options.scanlines === undefined) {
        options.scanlines = true;
      }
      if (options.greyscale === undefined) {
        options.greyscale = false;
      }
      if (options.sepia === undefined) {
        options.sepia = false;
      }
      if (options.vignette === undefined) {
        options.vignette = false;
      }
      if (options.eskil === undefined) {
        options.eskil = false;
      }
      if (options.noiseIntensity === undefined) {
        options.noiseIntensity = 0.5;
      }
      if (options.scanlineIntensity === undefined) {
        options.scanlineIntensity = 0.05;
      }
      if (options.greyscaleIntensity === undefined) {
        options.greyscaleIntensity = 1.0;
      }
      if (options.sepiaIntensity === undefined) {
        options.sepiaIntensity = 1.0;
      }
      if (options.vignetteOffset === undefined) {
        options.vignetteOffset = 1.0;
      }
      if (options.vignetteDarkness === undefined) {
        options.vignetteDarkness = 1.0;
      }
      var _this = possibleConstructorReturn(this, (FilmMaterial.__proto__ || Object.getPrototypeOf(FilmMaterial)).call(this, {
        type: "FilmMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          time: new three.Uniform(0.0),
          noiseIntensity: new three.Uniform(options.noiseIntensity),
          scanlineIntensity: new three.Uniform(options.scanlineIntensity),
          scanlineCount: new three.Uniform(0.0),
          greyscaleIntensity: new three.Uniform(options.greyscaleIntensity),
          sepiaIntensity: new three.Uniform(options.sepiaIntensity),
          vignetteOffset: new three.Uniform(options.vignetteOffset),
          vignetteDarkness: new three.Uniform(options.vignetteDarkness)
        },
        fragmentShader: fragment$7,
        vertexShader: vertex$7,
        depthWrite: false,
        depthTest: false
      }));
      if (options.greyscale) {
        _this.defines.GREYSCALE = "1";
      }
      if (options.sepia) {
        _this.defines.SEPIA = "1";
      }
      if (options.vignette) {
        _this.defines.VIGNETTE = "1";
      }
      if (options.eskil) {
        _this.defines.ESKIL = "1";
      }
      if (options.screenMode) {
        _this.defines.SCREEN_MODE = "1";
      }
      if (options.noise) {
        _this.defines.NOISE = "1";
      }
      if (options.scanlines) {
        _this.defines.SCANLINES = "1";
      }
      return _this;
    }
    return FilmMaterial;
  }(three.ShaderMaterial);
  var fragment$8 = "uniform sampler2D tDiffuse;\r\nuniform sampler2D tPerturb;\r\n\r\nuniform bool active;\r\n\r\nuniform float amount;\r\nuniform float angle;\r\nuniform float seed;\r\nuniform float seedX;\r\nuniform float seedY;\r\nuniform float distortionX;\r\nuniform float distortionY;\r\nuniform float colS;\r\n\r\nvarying vec2 vUv;\r\n\r\nfloat rand(vec2 tc) {\r\n\r\n\tconst float a = 12.9898;\r\n\tconst float b = 78.233;\r\n\tconst float c = 43758.5453;\r\n\r\n\tfloat dt = dot(tc, vec2(a, b));\r\n\tfloat sn = mod(dt, 3.14);\r\n\r\n\treturn fract(sin(sn) * c);\r\n\r\n}\r\n\r\nvoid main() {\r\n\r\n\tvec2 coord = vUv;\r\n\r\n\tfloat xs, ys;\r\n\tvec4 normal;\r\n\r\n\tvec2 offset;\r\n\tvec4 cr, cga, cb;\r\n\tvec4 snow, color;\r\n\r\n\tfloat sx, sy;\r\n\r\n\tif(active) {\r\n\r\n\t\txs = floor(gl_FragCoord.x / 0.5);\r\n\t\tys = floor(gl_FragCoord.y / 0.5);\r\n\r\n\t\tnormal = texture2D(tPerturb, coord * seed * seed);\r\n\r\n\t\tif(coord.y < distortionX + colS && coord.y > distortionX - colS * seed) {\r\n\r\n\t\t\tsx = clamp(ceil(seedX), 0.0, 1.0);\r\n\t\t\tcoord.y = sx * (1.0 - (coord.y + distortionY)) + (1.0 - sx) * distortionY;\r\n\r\n\t\t}\r\n\r\n\t\tif(coord.x < distortionY + colS && coord.x > distortionY - colS * seed) {\r\n\r\n\t\t\tsy = clamp(ceil(seedY), 0.0, 1.0);\r\n\t\t\tcoord.x = sy * distortionX + (1.0 - sy) * (1.0 - (coord.x + distortionX));\r\n\r\n\t\t}\r\n\r\n\t\tcoord.x += normal.x * seedX * (seed / 5.0);\r\n\t\tcoord.y += normal.y * seedY * (seed / 5.0);\r\n\r\n\t\toffset = amount * vec2(cos(angle), sin(angle));\r\n\r\n\t\tcr = texture2D(tDiffuse, coord + offset);\r\n\t\tcga = texture2D(tDiffuse, coord);\r\n\t\tcb = texture2D(tDiffuse, coord - offset);\r\n\r\n\t\tcolor = vec4(cr.r, cga.g, cb.b, cga.a);\r\n\t\tsnow = 200.0 * amount * vec4(rand(vec2(xs * seed, ys * seed * 50.0)) * 0.2);\r\n\t\tcolor += snow;\r\n\r\n\t} else {\r\n\r\n\t\tcolor = texture2D(tDiffuse, vUv);\r\n\r\n\t}\r\n\r\n\tgl_FragColor = color;\r\n\r\n}\r\n";
  var vertex$8 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var GlitchMaterial = function(_ShaderMaterial) {
    inherits(GlitchMaterial, _ShaderMaterial);
    function GlitchMaterial() {
      classCallCheck(this, GlitchMaterial);
      return possibleConstructorReturn(this, (GlitchMaterial.__proto__ || Object.getPrototypeOf(GlitchMaterial)).call(this, {
        type: "GlitchMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          tPerturb: new three.Uniform(null),
          active: new three.Uniform(1),
          amount: new three.Uniform(0.8),
          angle: new three.Uniform(0.02),
          seed: new three.Uniform(0.02),
          seedX: new three.Uniform(0.02),
          seedY: new three.Uniform(0.02),
          distortionX: new three.Uniform(0.5),
          distortionY: new three.Uniform(0.6),
          colS: new three.Uniform(0.05)
        },
        fragmentShader: fragment$8,
        vertexShader: vertex$8,
        depthWrite: false,
        depthTest: false
      }));
    }
    return GlitchMaterial;
  }(three.ShaderMaterial);
  var fragment$9 = "uniform sampler2D tDiffuse;\r\nuniform vec3 lightPosition;\r\n\r\nuniform float exposure;\r\nuniform float decay;\r\nuniform float density;\r\nuniform float weight;\r\nuniform float clampMax;\r\n\r\nvarying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvec2 texCoord = vUv;\r\n\r\n\t// Calculate vector from pixel to light source in screen space.\r\n\tvec2 deltaTexCoord = texCoord - lightPosition.st;\r\n\tdeltaTexCoord *= 1.0 / NUM_SAMPLES_FLOAT * density;\r\n\r\n\t// A decreasing illumination factor.\r\n\tfloat illuminationDecay = 1.0;\r\n\r\n\tvec4 sample;\r\n\tvec4 color = vec4(0.0);\r\n\r\n\t// Estimate the probability of occlusion at each pixel by summing samples along a ray to the light source.\r\n\tfor(int i = 0; i < NUM_SAMPLES_INT; ++i) {\r\n\r\n\t\ttexCoord -= deltaTexCoord;\r\n\t\tsample = texture2D(tDiffuse, texCoord);\r\n\r\n\t\t// Apply sample attenuation scale/decay factors.\r\n\t\tsample *= illuminationDecay * weight;\r\n\r\n\t\tcolor += sample;\r\n\r\n\t\t// Update exponential decay factor.\r\n\t\tilluminationDecay *= decay;\r\n\r\n\t}\r\n\r\n\tgl_FragColor = clamp(color * exposure, 0.0, clampMax);\r\n\r\n}\r\n";
  var vertex$9 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var GodRaysMaterial = function(_ShaderMaterial) {
    inherits(GodRaysMaterial, _ShaderMaterial);
    function GodRaysMaterial() {
      classCallCheck(this, GodRaysMaterial);
      return possibleConstructorReturn(this, (GodRaysMaterial.__proto__ || Object.getPrototypeOf(GodRaysMaterial)).call(this, {
        type: "GodRaysMaterial",
        defines: {
          NUM_SAMPLES_FLOAT: "60.0",
          NUM_SAMPLES_INT: "60"
        },
        uniforms: {
          tDiffuse: new three.Uniform(null),
          lightPosition: new three.Uniform(null),
          exposure: new three.Uniform(0.6),
          decay: new three.Uniform(0.93),
          density: new three.Uniform(0.96),
          weight: new three.Uniform(0.4),
          clampMax: new three.Uniform(1.0)
        },
        fragmentShader: fragment$9,
        vertexShader: vertex$9,
        depthWrite: false,
        depthTest: false
      }));
    }
    return GodRaysMaterial;
  }(three.ShaderMaterial);
  var fragment$10 = "#include <common>\r\n\r\nuniform sampler2D tDiffuse;\r\nuniform float distinction;\r\nuniform vec2 range;\r\n\r\nvarying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvec4 texel = texture2D(tDiffuse, vUv);\r\n\tfloat l = linearToRelativeLuminance(texel.rgb);\r\n\r\n\t#ifdef RANGE\r\n\r\n\t\tfloat low = step(range.x, l);\r\n\t\tfloat high = step(l, range.y);\r\n\r\n\t\t// Apply the mask.\r\n\t\tl *= low * high;\r\n\r\n\t#endif\r\n\r\n\tl = pow(abs(l), distinction);\r\n\r\n\t#ifdef COLOR\r\n\r\n\t\tgl_FragColor = vec4(texel.rgb * l, texel.a);\r\n\r\n\t#else\r\n\r\n\t\tgl_FragColor = vec4(l, l, l, texel.a);\r\n\r\n\t#endif\r\n\r\n}\r\n";
  var vertex$10 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var LuminosityMaterial = function(_ShaderMaterial) {
    inherits(LuminosityMaterial, _ShaderMaterial);
    function LuminosityMaterial() {
      var color = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      var range = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      classCallCheck(this, LuminosityMaterial);
      var _this = possibleConstructorReturn(this, (LuminosityMaterial.__proto__ || Object.getPrototypeOf(LuminosityMaterial)).call(this, {
        type: "LuminosityMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          distinction: new three.Uniform(1.0),
          range: new three.Uniform(range !== null ? range : new three.Vector2())
        },
        fragmentShader: fragment$10,
        vertexShader: vertex$10
      }));
      if (color) {
        _this.defines.COLOR = "1";
      }
      if (range !== null) {
        _this.defines.RANGE = "1";
      }
      return _this;
    }
    return LuminosityMaterial;
  }(three.ShaderMaterial);
  var fragment$11 = "uniform sampler2D tDiffuse;\r\nuniform float granularity;\r\nuniform float dx;\r\nuniform float dy;\r\n\r\nvarying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvec4 texel;\r\n\r\n\tif(granularity > 0.0) {\r\n\r\n\t\tvec2 coord = vec2(\r\n\t\t\tdx * (floor(vUv.x / dx) + 0.5),\r\n\t\t\tdy * (floor(vUv.y / dy) + 0.5)\r\n\t\t);\r\n\r\n\t\ttexel = texture2D(tDiffuse, coord);\r\n\r\n\t} else {\r\n\r\n\t\ttexel = texture2D(tDiffuse, vUv);\r\n\r\n\t}\r\n\r\n\tgl_FragColor = texel;\r\n\r\n}\r\n";
  var vertex$11 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var PixelationMaterial = function(_ShaderMaterial) {
    inherits(PixelationMaterial, _ShaderMaterial);
    function PixelationMaterial() {
      classCallCheck(this, PixelationMaterial);
      return possibleConstructorReturn(this, (PixelationMaterial.__proto__ || Object.getPrototypeOf(PixelationMaterial)).call(this, {
        type: "PixelationMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          granularity: new three.Uniform(1.0),
          resolution: new three.Uniform(new three.Vector2(1.0, 1.0)),
          dx: new three.Uniform(1.0),
          dy: new three.Uniform(1.0)
        },
        fragmentShader: fragment$11,
        vertexShader: vertex$11,
        depthWrite: false,
        depthTest: false
      }));
    }
    createClass(PixelationMaterial, [{
      key: "setResolution",
      value: function setResolution(width, height) {
        this.uniforms.resolution.value.set(width, height);
        this.granularity = this.granularity;
      }
    }, {
      key: "granularity",
      get: function get$$1() {
        return this.uniforms.granularity.value;
      },
      set: function set$$1(x) {
        var uniforms = this.uniforms;
        var resolution = uniforms.resolution.value;
        uniforms.granularity.value = x;
        uniforms.dx.value = x / resolution.x;
        uniforms.dy.value = x / resolution.y;
      }
    }]);
    return PixelationMaterial;
  }(three.ShaderMaterial);
  var fragment$12 = "#include <common>\r\n\r\nuniform sampler2D tDiffuse;\r\nuniform vec2 center;\r\nuniform float aspect;\r\nuniform float waveSize;\r\nuniform float radius;\r\nuniform float maxRadius;\r\nuniform float amplitude;\r\n\r\nvarying vec2 vUv;\r\nvarying float vSize;\r\n\r\nvoid main() {\r\n\r\n\tvec2 aspectCorrection = vec2(aspect, 1.0);\r\n\r\n\tvec2 difference = vUv * aspectCorrection - center * aspectCorrection;\r\n\tfloat distance = sqrt(dot(difference, difference)) * vSize;\r\n\r\n\tvec2 displacement = vec2(0.0);\r\n\r\n\tif(distance > radius) {\r\n\r\n\t\tif(distance < radius + waveSize) {\r\n\r\n\t\t\tfloat angle = (distance - radius) * PI2 / waveSize;\r\n\t\t\tfloat cosSin = (1.0 - cos(angle)) * 0.5;\r\n\r\n\t\t\tfloat extent = maxRadius + waveSize;\r\n\t\t\tfloat decay = max(extent - distance * distance, 0.0) / extent;\r\n\r\n\t\t\tdisplacement = ((cosSin * amplitude * difference) / distance) * decay;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tgl_FragColor = texture2D(tDiffuse, vUv - displacement);\r\n\r\n}\r\n";
  var vertex$12 = "uniform float size;\r\nuniform float scale;\r\nuniform float cameraDistance;\r\n\r\nvarying vec2 vUv;\r\nvarying float vSize;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tvSize = (0.1 * cameraDistance) / size;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var ShockWaveMaterial = function(_ShaderMaterial) {
    inherits(ShockWaveMaterial, _ShaderMaterial);
    function ShockWaveMaterial() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, ShockWaveMaterial);
      if (options.maxRadius === undefined) {
        options.maxRadius = 1.0;
      }
      if (options.waveSize === undefined) {
        options.waveSize = 0.2;
      }
      if (options.amplitude === undefined) {
        options.amplitude = 0.05;
      }
      return possibleConstructorReturn(this, (ShockWaveMaterial.__proto__ || Object.getPrototypeOf(ShockWaveMaterial)).call(this, {
        type: "ShockWaveMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          center: new three.Uniform(new three.Vector2(0.5, 0.5)),
          aspect: new three.Uniform(1.0),
          cameraDistance: new three.Uniform(1.0),
          size: new three.Uniform(1.0),
          radius: new three.Uniform(-options.waveSize),
          maxRadius: new three.Uniform(options.maxRadius),
          waveSize: new three.Uniform(options.waveSize),
          amplitude: new three.Uniform(options.amplitude)
        },
        fragmentShader: fragment$12,
        vertexShader: vertex$12,
        depthWrite: false,
        depthTest: false
      }));
    }
    return ShockWaveMaterial;
  }(three.ShaderMaterial);
  var fragment$13 = "uniform sampler2D tDiffuse;\r\nuniform sampler2D tWeights;\r\n\r\nuniform vec2 texelSize;\r\n\r\nvarying vec2 vUv;\r\nvarying vec4 vOffset;\r\n\r\nvoid main() {\r\n\r\n\t// Fetch the blending weights for current pixel.\r\n\tvec4 a;\r\n\ta.xz = texture2D(tWeights, vUv).xz;\r\n\ta.y = texture2D(tWeights, vOffset.zw).g;\r\n\ta.w = texture2D(tWeights, vOffset.xy).a;\r\n\r\n\tvec4 color;\r\n\r\n\t// Check if there is any blending weight with a value greater than 0.0.\r\n\tif(dot(a, vec4(1.0)) < 1e-5) {\r\n\r\n\t\tcolor = texture2D(tDiffuse, vUv, 0.0);\r\n\r\n\t} else {\r\n\r\n\t\t/* Up to four lines can be crossing a pixel (one through each edge).\r\n\t\t * The line with the maximum weight for each direction is favoured.\r\n\t\t */\r\n\r\n\t\tvec2 offset;\r\n\t\toffset.x = a.a > a.b ? a.a : -a.b; // Left vs. right.\r\n\t\toffset.y = a.g > a.r ? -a.g : a.r; // Top vs. bottom (changed signs).\r\n\r\n\t\t// Go in the direction with the maximum weight (horizontal vs. vertical).\r\n\t\tif(abs(offset.x) > abs(offset.y)) {\r\n\r\n\t\t\toffset.y = 0.0;\r\n\r\n\t\t} else {\r\n\r\n\t\t\toffset.x = 0.0;\r\n\r\n\t\t}\r\n\r\n\t\t// Fetch the opposite color and lerp by hand.\r\n\t\tcolor = texture2D(tDiffuse, vUv, 0.0);\r\n\t\tvec2 coord = vUv + sign(offset) * texelSize;\r\n\t\tvec4 oppositeColor = texture2D(tDiffuse, coord, 0.0);\r\n\t\tfloat s = abs(offset.x) > abs(offset.y) ? abs(offset.x) : abs(offset.y);\r\n\r\n\t\t// Gamma correction.\r\n\t\tcolor.rgb = pow(abs(color.rgb), vec3(2.2));\r\n\t\toppositeColor.rgb = pow(abs(oppositeColor.rgb), vec3(2.2));\r\n\t\tcolor = mix(color, oppositeColor, s);\r\n\t\tcolor.rgb = pow(abs(color.rgb), vec3(1.0 / 2.2));\r\n\r\n\t}\r\n\r\n\tgl_FragColor = color;\r\n\r\n}\r\n";
  var vertex$13 = "uniform vec2 texelSize;\r\n\r\nvarying vec2 vUv;\r\nvarying vec4 vOffset;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\r\n\tvOffset = uv.xyxy + texelSize.xyxy * vec4(1.0, 0.0, 0.0, -1.0); // Changed sign in W component.\r\n\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var SMAABlendMaterial = function(_ShaderMaterial) {
    inherits(SMAABlendMaterial, _ShaderMaterial);
    function SMAABlendMaterial() {
      var texelSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new three.Vector2();
      classCallCheck(this, SMAABlendMaterial);
      return possibleConstructorReturn(this, (SMAABlendMaterial.__proto__ || Object.getPrototypeOf(SMAABlendMaterial)).call(this, {
        type: "SMAABlendMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          tWeights: new three.Uniform(null),
          texelSize: new three.Uniform(texelSize)
        },
        fragmentShader: fragment$13,
        vertexShader: vertex$13,
        depthWrite: false,
        depthTest: false
      }));
    }
    return SMAABlendMaterial;
  }(three.ShaderMaterial);
  var fragment$14 = "uniform sampler2D tDiffuse;\r\n\r\nvarying vec2 vUv;\r\nvarying vec4 vOffset[3];\r\n\r\nvoid main() {\r\n\r\n\tconst vec2 threshold = vec2(EDGE_THRESHOLD);\r\n\r\n\t// Calculate color deltas.\r\n\tvec4 delta;\r\n\tvec3 c = texture2D(tDiffuse, vUv).rgb;\r\n\r\n\tvec3 cLeft = texture2D(tDiffuse, vOffset[0].xy).rgb;\r\n\tvec3 t = abs(c - cLeft);\r\n\tdelta.x = max(max(t.r, t.g), t.b);\r\n\r\n\tvec3 cTop = texture2D(tDiffuse, vOffset[0].zw).rgb;\r\n\tt = abs(c - cTop);\r\n\tdelta.y = max(max(t.r, t.g), t.b);\r\n\r\n\t// We do the usual threshold.\r\n\tvec2 edges = step(threshold, delta.xy);\r\n\r\n\t// Then discard if there is no edge.\r\n\tif(dot(edges, vec2(1.0)) == 0.0) {\r\n\r\n\t\tdiscard;\r\n\r\n\t}\r\n\r\n\t// Calculate right and bottom deltas.\r\n\tvec3 cRight = texture2D(tDiffuse, vOffset[1].xy).rgb;\r\n\tt = abs(c - cRight);\r\n\tdelta.z = max(max(t.r, t.g), t.b);\r\n\r\n\tvec3 cBottom = texture2D(tDiffuse, vOffset[1].zw).rgb;\r\n\tt = abs(c - cBottom);\r\n\tdelta.w = max(max(t.r, t.g), t.b);\r\n\r\n\t// Calculate the maximum delta in the direct neighborhood.\r\n\tfloat maxDelta = max(max(max(delta.x, delta.y), delta.z), delta.w);\r\n\r\n\t// Calculate left-left and top-top deltas.\r\n\tvec3 cLeftLeft = texture2D(tDiffuse, vOffset[2].xy).rgb;\r\n\tt = abs(c - cLeftLeft);\r\n\tdelta.z = max(max(t.r, t.g), t.b);\r\n\r\n\tvec3 cTopTop = texture2D(tDiffuse, vOffset[2].zw).rgb;\r\n\tt = abs(c - cTopTop);\r\n\tdelta.w = max(max(t.r, t.g), t.b);\r\n\r\n\t// Calculate the final maximum delta.\r\n\tmaxDelta = max(max(maxDelta, delta.z), delta.w);\r\n\r\n\t// Local contrast adaptation in action.\r\n\tedges.xy *= step(0.5 * maxDelta, delta.xy);\r\n\r\n\tgl_FragColor = vec4(edges, 0.0, 0.0);\r\n\r\n}\r\n";
  var vertex$14 = "uniform vec2 texelSize;\r\n\r\nvarying vec2 vUv;\r\nvarying vec4 vOffset[3];\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\r\n\tvOffset[0] = uv.xyxy + texelSize.xyxy * vec4(-1.0, 0.0, 0.0, 1.0); // Changed sign in W component.\r\n\tvOffset[1] = uv.xyxy + texelSize.xyxy * vec4(1.0, 0.0, 0.0, -1.0); // Changed sign in W component.\r\n\tvOffset[2] = uv.xyxy + texelSize.xyxy * vec4(-2.0, 0.0, 0.0, 2.0); // Changed sign in W component.\r\n\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var SMAAColorEdgesMaterial = function(_ShaderMaterial) {
    inherits(SMAAColorEdgesMaterial, _ShaderMaterial);
    function SMAAColorEdgesMaterial() {
      var texelSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new three.Vector2();
      classCallCheck(this, SMAAColorEdgesMaterial);
      return possibleConstructorReturn(this, (SMAAColorEdgesMaterial.__proto__ || Object.getPrototypeOf(SMAAColorEdgesMaterial)).call(this, {
        type: "SMAAColorEdgesMaterial",
        defines: {EDGE_THRESHOLD: "0.1"},
        uniforms: {
          tDiffuse: new three.Uniform(null),
          texelSize: new three.Uniform(texelSize)
        },
        fragmentShader: fragment$14,
        vertexShader: vertex$14,
        depthWrite: false,
        depthTest: false
      }));
    }
    createClass(SMAAColorEdgesMaterial, [{
      key: "setEdgeDetectionThreshold",
      value: function setEdgeDetectionThreshold(threshold) {
        this.defines.EDGE_THRESHOLD = threshold.toFixed("2");
        this.needsUpdate = true;
      }
    }]);
    return SMAAColorEdgesMaterial;
  }(three.ShaderMaterial);
  var fragment$15 = "#define sampleLevelZeroOffset(t, coord, offset) texture2D(t, coord + float(offset) * texelSize, 0.0)\r\n\r\nuniform sampler2D tDiffuse;\r\nuniform sampler2D tArea;\r\nuniform sampler2D tSearch;\r\n\r\nuniform vec2 texelSize;\r\n\r\nvarying vec2 vUv;\r\nvarying vec4 vOffset[3];\r\nvarying vec2 vPixCoord;\r\n\r\nvec2 round(vec2 x) {\r\n\r\n\treturn sign(x) * floor(abs(x) + 0.5);\r\n\r\n}\r\n\r\nfloat searchLength(vec2 e, float bias, float scale) {\r\n\r\n\t// Not required if tSearch accesses are set to point.\r\n\t// const vec2 SEARCH_TEX_PIXEL_SIZE = 1.0 / vec2(66.0, 33.0);\r\n\t// e = vec2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE + e * vec2(scale, 1.0) * vec2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE;\r\n\r\n\te.r = bias + e.r * scale;\r\n\r\n\treturn 255.0 * texture2D(tSearch, e, 0.0).r;\r\n\r\n}\r\n\r\nfloat searchXLeft(vec2 texCoord, float end) {\r\n\r\n\t/* @PSEUDO_GATHER4\r\n\t * This texCoord has been offset by (-0.25, -0.125) in the vertex shader to\r\n\t * sample between edge, thus fetching four edges in a row.\r\n\t * Sampling with different offsets in each direction allows to disambiguate\r\n\t * which edges are active from the four fetched ones.\r\n\t */\r\n\r\n\tvec2 e = vec2(0.0, 1.0);\r\n\r\n\tfor(int i = 0; i < MAX_SEARCH_STEPS_INT; ++i) {\r\n\r\n\t\te = texture2D(tDiffuse, texCoord, 0.0).rg;\r\n\t\ttexCoord -= vec2(2.0, 0.0) * texelSize;\r\n\r\n\t\tif(!(texCoord.x > end && e.g > 0.8281 && e.r == 0.0)) { break; }\r\n\r\n\t}\r\n\r\n\t// Correct the previously applied offset (-0.25, -0.125).\r\n\ttexCoord.x += 0.25 * texelSize.x;\r\n\r\n\t// The searches are biased by 1, so adjust the coords accordingly.\r\n\ttexCoord.x += texelSize.x;\r\n\r\n\t// Disambiguate the length added by the last step.\r\n\ttexCoord.x += 2.0 * texelSize.x; // Undo last step.\r\n\ttexCoord.x -= texelSize.x * searchLength(e, 0.0, 0.5);\r\n\r\n\treturn texCoord.x;\r\n\r\n}\r\n\r\nfloat searchXRight(vec2 texCoord, float end) {\r\n\r\n\tvec2 e = vec2(0.0, 1.0);\r\n\r\n\tfor(int i = 0; i < MAX_SEARCH_STEPS_INT; ++i) {\r\n\r\n\t\te = texture2D(tDiffuse, texCoord, 0.0).rg;\r\n\t\ttexCoord += vec2(2.0, 0.0) * texelSize;\r\n\r\n\t\tif(!(texCoord.x < end && e.g > 0.8281 && e.r == 0.0)) { break; }\r\n\r\n\t}\r\n\r\n\ttexCoord.x -= 0.25 * texelSize.x;\r\n\ttexCoord.x -= texelSize.x;\r\n\ttexCoord.x -= 2.0 * texelSize.x;\r\n\ttexCoord.x += texelSize.x * searchLength(e, 0.5, 0.5);\r\n\r\n\treturn texCoord.x;\r\n\r\n}\r\n\r\nfloat searchYUp(vec2 texCoord, float end) {\r\n\r\n\tvec2 e = vec2(1.0, 0.0);\r\n\r\n\tfor(int i = 0; i < MAX_SEARCH_STEPS_INT; ++i) {\r\n\r\n\t\te = texture2D(tDiffuse, texCoord, 0.0).rg;\r\n\t\ttexCoord += vec2(0.0, 2.0) * texelSize; // Changed sign.\r\n\r\n\t\tif(!(texCoord.y > end && e.r > 0.8281 && e.g == 0.0)) { break; }\r\n\r\n\t}\r\n\r\n\ttexCoord.y -= 0.25 * texelSize.y; // Changed sign.\r\n\ttexCoord.y -= texelSize.y; // Changed sign.\r\n\ttexCoord.y -= 2.0 * texelSize.y; // Changed sign.\r\n\ttexCoord.y += texelSize.y * searchLength(e.gr, 0.0, 0.5); // Changed sign.\r\n\r\n\treturn texCoord.y;\r\n\r\n}\r\n\r\nfloat searchYDown(vec2 texCoord, float end) {\r\n\r\n\tvec2 e = vec2(1.0, 0.0);\r\n\r\n\tfor(int i = 0; i < MAX_SEARCH_STEPS_INT; ++i ) {\r\n\r\n\t\te = texture2D(tDiffuse, texCoord, 0.0).rg;\r\n\t\ttexCoord -= vec2(0.0, 2.0) * texelSize; // Changed sign.\r\n\r\n\t\tif(!(texCoord.y < end && e.r > 0.8281 && e.g == 0.0)) { break; }\r\n\r\n\t}\r\n\r\n\ttexCoord.y += 0.25 * texelSize.y; // Changed sign.\r\n\ttexCoord.y += texelSize.y; // Changed sign.\r\n\ttexCoord.y += 2.0 * texelSize.y; // Changed sign.\r\n\ttexCoord.y -= texelSize.y * searchLength(e.gr, 0.5, 0.5); // Changed sign.\r\n\r\n\treturn texCoord.y;\r\n\r\n}\r\n\r\nvec2 area(vec2 dist, float e1, float e2, float offset) {\r\n\r\n\t// Rounding prevents precision errors of bilinear filtering.\r\n\tvec2 texCoord = AREATEX_MAX_DISTANCE * round(4.0 * vec2(e1, e2)) + dist;\r\n\r\n\t// Scale and bias for texel space translation.\r\n\ttexCoord = AREATEX_PIXEL_SIZE * texCoord + (0.5 * AREATEX_PIXEL_SIZE);\r\n\r\n\t// Move to proper place, according to the subpixel offset.\r\n\ttexCoord.y += AREATEX_SUBTEX_SIZE * offset;\r\n\r\n\treturn texture2D(tArea, texCoord, 0.0).rg;\r\n\r\n}\r\n\r\nvoid main() {\r\n\r\n\tvec4 weights = vec4(0.0);\r\n\tvec4 subsampleIndices = vec4(0.0);\r\n\tvec2 e = texture2D(tDiffuse, vUv).rg;\r\n\r\n\tif(e.g > 0.0) {\r\n\r\n\t\t// Edge at north.\r\n\t\tvec2 d;\r\n\r\n\t\t// Find the distance to the left.\r\n\t\tvec2 coords;\r\n\t\tcoords.x = searchXLeft(vOffset[0].xy, vOffset[2].x);\r\n\t\tcoords.y = vOffset[1].y; // vOffset[1].y = vUv.y - 0.25 * texelSize.y (@CROSSING_OFFSET)\r\n\t\td.x = coords.x;\r\n\r\n\t\t/* Now fetch the left crossing edges, two at a time using bilinear\r\n\t\tfiltering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to discern what\r\n\t\tvalue each edge has. */\r\n\t\tfloat e1 = texture2D(tDiffuse, coords, 0.0).r;\r\n\r\n\t\t// Find the distance to the right.\r\n\t\tcoords.x = searchXRight(vOffset[0].zw, vOffset[2].y);\r\n\t\td.y = coords.x;\r\n\r\n\t\t/* Translate distances to pixel units for better interleave arithmetic and\r\n\t\tmemory accesses. */\r\n\t\td = d / texelSize.x - vPixCoord.x;\r\n\r\n\t\t// The area texture is compressed quadratically.\r\n\t\tvec2 sqrtD = sqrt(abs(d));\r\n\r\n\t\t// Fetch the right crossing edges.\r\n\t\tcoords.y -= texelSize.y; // WebGL port note: Added.\r\n\t\tfloat e2 = sampleLevelZeroOffset(tDiffuse, coords, ivec2(1, 0)).r;\r\n\r\n\t\t// Pattern recognised, now get the actual area.\r\n\t\tweights.rg = area(sqrtD, e1, e2, subsampleIndices.y);\r\n\r\n\t}\r\n\r\n\tif(e.r > 0.0) {\r\n\r\n\t\t// Edge at west.\r\n\t\tvec2 d;\r\n\r\n\t\t// Find the distance to the top.\r\n\t\tvec2 coords;\r\n\t\tcoords.y = searchYUp(vOffset[1].xy, vOffset[2].z);\r\n\t\tcoords.x = vOffset[0].x; // vOffset[1].x = vUv.x - 0.25 * texelSize.x;\r\n\t\td.x = coords.y;\r\n\r\n\t\t// Fetch the top crossing edges.\r\n\t\tfloat e1 = texture2D(tDiffuse, coords, 0.0).g;\r\n\r\n\t\t// Find the distance to the bottom.\r\n\t\tcoords.y = searchYDown(vOffset[1].zw, vOffset[2].w);\r\n\t\td.y = coords.y;\r\n\r\n\t\t// Distances in pixel units.\r\n\t\td = d / texelSize.y - vPixCoord.y;\r\n\r\n\t\t// The area texture is compressed quadratically.\r\n\t\tvec2 sqrtD = sqrt(abs(d));\r\n\r\n\t\t// Fetch the bottom crossing edges.\r\n\t\tcoords.y -= texelSize.y; // WebGL port note: Added.\r\n\t\tfloat e2 = sampleLevelZeroOffset(tDiffuse, coords, ivec2(0, 1)).g;\r\n\r\n\t\t// Get the area for this direction.\r\n\t\tweights.ba = area(sqrtD, e1, e2, subsampleIndices.x);\r\n\r\n\t}\r\n\r\n\tgl_FragColor = weights;\r\n\r\n}\r\n";
  var vertex$15 = "uniform vec2 texelSize;\r\n\r\nvarying vec2 vUv;\r\nvarying vec4 vOffset[3];\r\nvarying vec2 vPixCoord;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\r\n\tvPixCoord = uv / texelSize;\r\n\r\n\t// Offsets for the searches (see @PSEUDO_GATHER4).\r\n\tvOffset[0] = uv.xyxy + texelSize.xyxy * vec4(-0.25, 0.125, 1.25, 0.125); // Changed sign in Y and W components.\r\n\tvOffset[1] = uv.xyxy + texelSize.xyxy * vec4(-0.125, 0.25, -0.125, -1.25); //Changed sign in Y and W components.\r\n\r\n\t// This indicates the ends of the loops.\r\n\tvOffset[2] = vec4(vOffset[0].xz, vOffset[1].yw) + vec4(-2.0, 2.0, -2.0, 2.0) * texelSize.xxyy * MAX_SEARCH_STEPS_FLOAT;\r\n\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var SMAAWeightsMaterial = function(_ShaderMaterial) {
    inherits(SMAAWeightsMaterial, _ShaderMaterial);
    function SMAAWeightsMaterial() {
      var texelSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new three.Vector2();
      classCallCheck(this, SMAAWeightsMaterial);
      return possibleConstructorReturn(this, (SMAAWeightsMaterial.__proto__ || Object.getPrototypeOf(SMAAWeightsMaterial)).call(this, {
        type: "SMAAWeightsMaterial",
        defines: {
          MAX_SEARCH_STEPS_INT: "8",
          MAX_SEARCH_STEPS_FLOAT: "8.0",
          AREATEX_MAX_DISTANCE: "16.0",
          AREATEX_PIXEL_SIZE: "(1.0 / vec2(160.0, 560.0))",
          AREATEX_SUBTEX_SIZE: "(1.0 / 7.0)",
          SEARCHTEX_SIZE: "vec2(66.0, 33.0)",
          SEARCHTEX_PACKED_SIZE: "vec2(64.0, 16.0)"
        },
        uniforms: {
          tDiffuse: new three.Uniform(null),
          tArea: new three.Uniform(null),
          tSearch: new three.Uniform(null),
          texelSize: new three.Uniform(texelSize)
        },
        fragmentShader: fragment$15,
        vertexShader: vertex$15,
        depthWrite: false,
        depthTest: false
      }));
    }
    createClass(SMAAWeightsMaterial, [{
      key: "setOrthogonalSearchSteps",
      value: function setOrthogonalSearchSteps(steps) {
        this.defines.MAX_SEARCH_STEPS_INT = steps.toFixed("0");
        this.defines.MAX_SEARCH_STEPS_FLOAT = steps.toFixed("1");
        this.needsUpdate = true;
      }
    }]);
    return SMAAWeightsMaterial;
  }(three.ShaderMaterial);
  var fragment$16 = "#include <common>\r\n\r\nuniform sampler2D tDiffuse;\r\nuniform float middleGrey;\r\nuniform float maxLuminance;\r\n\r\n#ifdef ADAPTED_LUMINANCE\r\n\r\n\tuniform sampler2D luminanceMap;\r\n\r\n#else\r\n\r\n\tuniform float averageLuminance;\r\n\r\n#endif\r\n\r\nvarying vec2 vUv;\r\n\r\nvec3 toneMap(vec3 c) {\r\n\r\n\t#ifdef ADAPTED_LUMINANCE\r\n\r\n\t\t// Get the calculated average luminance by sampling the center.\r\n\t\tfloat lumAvg = texture2D(luminanceMap, vec2(0.5)).r;\r\n\r\n\t#else\r\n\r\n\t\tfloat lumAvg = averageLuminance;\r\n\r\n\t#endif\r\n\r\n\t// Calculate the luminance of the current pixel.\r\n\tfloat lumPixel = linearToRelativeLuminance(c);\r\n\r\n\t// Apply the modified operator (Reinhard Eq. 4).\r\n\tfloat lumScaled = (lumPixel * middleGrey) / lumAvg;\r\n\r\n\tfloat lumCompressed = (lumScaled * (1.0 + (lumScaled / (maxLuminance * maxLuminance)))) / (1.0 + lumScaled);\r\n\r\n\treturn lumCompressed * c;\r\n\r\n}\r\n\r\nvoid main() {\r\n\r\n\tvec4 texel = texture2D(tDiffuse, vUv);\r\n\tgl_FragColor = vec4(toneMap(texel.rgb), texel.a);\r\n\r\n}\r\n";
  var vertex$16 = "varying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n\r\n}\r\n";
  var ToneMappingMaterial = function(_ShaderMaterial) {
    inherits(ToneMappingMaterial, _ShaderMaterial);
    function ToneMappingMaterial() {
      classCallCheck(this, ToneMappingMaterial);
      return possibleConstructorReturn(this, (ToneMappingMaterial.__proto__ || Object.getPrototypeOf(ToneMappingMaterial)).call(this, {
        type: "ToneMappingMaterial",
        uniforms: {
          tDiffuse: new three.Uniform(null),
          luminanceMap: new three.Uniform(null),
          averageLuminance: new three.Uniform(1.0),
          maxLuminance: new three.Uniform(16.0),
          middleGrey: new three.Uniform(0.6)
        },
        fragmentShader: fragment$16,
        vertexShader: vertex$16,
        depthWrite: false,
        depthTest: false
      }));
    }
    return ToneMappingMaterial;
  }(three.ShaderMaterial);
  var Pass = function() {
    function Pass() {
      var scene = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new three.Scene();
      var camera = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new three.OrthographicCamera(-1, 1, 1, -1, 0, 1);
      var quad = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new three.Mesh(new three.PlaneBufferGeometry(2, 2), null);
      classCallCheck(this, Pass);
      this.name = "Pass";
      this.scene = scene;
      this.camera = camera;
      this.quad = quad;
      if (this.quad !== null) {
        this.quad.frustumCulled = false;
        if (this.scene !== null) {
          this.scene.add(this.quad);
        }
      }
      this.needsSwap = false;
      this.enabled = true;
      this.renderToScreen = false;
    }
    createClass(Pass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer, delta, maskActive) {
        throw new Error("Render method not implemented!");
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {}
    }, {
      key: "initialise",
      value: function initialise(renderer, alpha) {}
    }, {
      key: "dispose",
      value: function dispose() {
        var keys = Object.keys(this);
        var key = void 0;
        var _iteratorNormalCompletion = true;
        var _didIteratorError = false;
        var _iteratorError = undefined;
        try {
          for (var _iterator = keys[Symbol.iterator](),
              _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
            key = _step.value;
            if (this[key] !== null && typeof this[key].dispose === "function") {
              this[key].dispose();
              this[key] = null;
            }
          }
        } catch (err) {
          _didIteratorError = true;
          _iteratorError = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion && _iterator.return) {
              _iterator.return();
            }
          } finally {
            if (_didIteratorError) {
              throw _iteratorError;
            }
          }
        }
      }
    }]);
    return Pass;
  }();
  var BlurPass = function(_Pass) {
    inherits(BlurPass, _Pass);
    function BlurPass() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, BlurPass);
      var _this = possibleConstructorReturn(this, (BlurPass.__proto__ || Object.getPrototypeOf(BlurPass)).call(this));
      _this.name = "BlurPass";
      _this.needsSwap = true;
      _this.renderTargetX = new three.WebGLRenderTarget(1, 1, {
        minFilter: three.LinearFilter,
        magFilter: three.LinearFilter,
        stencilBuffer: false,
        depthBuffer: false
      });
      _this.renderTargetX.texture.name = "Blur.TargetX";
      _this.renderTargetX.texture.generateMipmaps = false;
      _this.renderTargetY = _this.renderTargetX.clone();
      _this.renderTargetY.texture.name = "Blur.TargetY";
      _this.resolutionScale = options.resolutionScale !== undefined ? options.resolutionScale : 0.5;
      _this.convolutionMaterial = new ConvolutionMaterial();
      _this.kernelSize = options.kernelSize;
      _this.quad.material = _this.convolutionMaterial;
      return _this;
    }
    createClass(BlurPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        var scene = this.scene;
        var camera = this.camera;
        var renderTargetX = this.renderTargetX;
        var renderTargetY = this.renderTargetY;
        var material = this.convolutionMaterial;
        var uniforms = material.uniforms;
        var kernel = material.getKernel();
        var lastRT = readBuffer;
        var destRT = void 0;
        var i = void 0,
            l = void 0;
        for (i = 0, l = kernel.length - 1; i < l; ++i) {
          destRT = i % 2 === 0 ? renderTargetX : renderTargetY;
          uniforms.kernel.value = kernel[i];
          uniforms.tDiffuse.value = lastRT.texture;
          renderer.render(scene, camera, destRT);
          lastRT = destRT;
        }
        uniforms.kernel.value = kernel[i];
        uniforms.tDiffuse.value = lastRT.texture;
        renderer.render(scene, camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "initialise",
      value: function initialise(renderer, alpha) {
        if (!alpha) {
          this.renderTargetX.texture.format = three.RGBFormat;
          this.renderTargetY.texture.format = three.RGBFormat;
        }
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        width = Math.max(1, Math.floor(width * this.resolutionScale));
        height = Math.max(1, Math.floor(height * this.resolutionScale));
        this.renderTargetX.setSize(width, height);
        this.renderTargetY.setSize(width, height);
        this.convolutionMaterial.setTexelSize(1.0 / width, 1.0 / height);
      }
    }, {
      key: "width",
      get: function get$$1() {
        return this.renderTargetX.width;
      }
    }, {
      key: "height",
      get: function get$$1() {
        return this.renderTargetX.height;
      }
    }, {
      key: "kernelSize",
      get: function get$$1() {
        return this.convolutionMaterial.kernelSize;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : KernelSize.LARGE;
        this.convolutionMaterial.kernelSize = value;
      }
    }]);
    return BlurPass;
  }(Pass);
  var BloomPass = function(_Pass) {
    inherits(BloomPass, _Pass);
    function BloomPass() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, BloomPass);
      var _this = possibleConstructorReturn(this, (BloomPass.__proto__ || Object.getPrototypeOf(BloomPass)).call(this));
      _this.name = "BloomPass";
      _this.needsSwap = true;
      _this.blurPass = new BlurPass(options);
      _this.renderTarget = new three.WebGLRenderTarget(1, 1, {
        minFilter: three.LinearFilter,
        magFilter: three.LinearFilter,
        stencilBuffer: false,
        depthBuffer: false
      });
      _this.renderTarget.texture.name = "Bloom.Target";
      _this.renderTarget.texture.generateMipmaps = false;
      _this.combineMaterial = new CombineMaterial(options.screenMode !== undefined ? options.screenMode : true);
      _this.intensity = options.intensity;
      _this.luminosityMaterial = new LuminosityMaterial(true);
      _this.distinction = options.distinction;
      return _this;
    }
    createClass(BloomPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        var quad = this.quad;
        var scene = this.scene;
        var camera = this.camera;
        var blurPass = this.blurPass;
        var luminosityMaterial = this.luminosityMaterial;
        var combineMaterial = this.combineMaterial;
        var renderTarget = this.renderTarget;
        quad.material = luminosityMaterial;
        luminosityMaterial.uniforms.tDiffuse.value = readBuffer.texture;
        renderer.render(scene, camera, renderTarget);
        blurPass.render(renderer, renderTarget, renderTarget);
        quad.material = combineMaterial;
        combineMaterial.uniforms.texture1.value = readBuffer.texture;
        combineMaterial.uniforms.texture2.value = renderTarget.texture;
        renderer.render(scene, camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "initialise",
      value: function initialise(renderer, alpha) {
        this.blurPass.initialise(renderer, alpha);
        if (!alpha) {
          this.renderTarget.texture.format = three.RGBFormat;
        }
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        this.blurPass.setSize(width, height);
        width = this.blurPass.width;
        height = this.blurPass.height;
        this.renderTarget.setSize(width, height);
      }
    }, {
      key: "resolutionScale",
      get: function get$$1() {
        return this.blurPass.resolutionScale;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.5;
        this.blurPass.resolutionScale = value;
      }
    }, {
      key: "kernelSize",
      get: function get$$1() {
        return this.blurPass.kernelSize;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : KernelSize.LARGE;
        this.blurPass.kernelSize = value;
      }
    }, {
      key: "intensity",
      get: function get$$1() {
        return this.combineMaterial.uniforms.opacity2.value;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1.0;
        this.combineMaterial.uniforms.opacity2.value = value;
      }
    }, {
      key: "distinction",
      get: function get$$1() {
        return this.luminosityMaterial.uniforms.distinction.value;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1.0;
        this.luminosityMaterial.uniforms.distinction.value = value;
      }
    }]);
    return BloomPass;
  }(Pass);
  var BokehPass = function(_Pass) {
    inherits(BokehPass, _Pass);
    function BokehPass(camera) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      classCallCheck(this, BokehPass);
      var _this = possibleConstructorReturn(this, (BokehPass.__proto__ || Object.getPrototypeOf(BokehPass)).call(this));
      _this.name = "BokehPass";
      _this.needsSwap = true;
      _this.bokehMaterial = new BokehMaterial(camera, options);
      _this.quad.material = _this.bokehMaterial;
      return _this;
    }
    createClass(BokehPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        this.bokehMaterial.uniforms.tDiffuse.value = readBuffer.texture;
        this.bokehMaterial.uniforms.tDepth.value = readBuffer.depthTexture;
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        this.bokehMaterial.uniforms.aspect.value = width / height;
      }
    }]);
    return BokehPass;
  }(Pass);
  var Bokeh2Pass = function(_Pass) {
    inherits(Bokeh2Pass, _Pass);
    function Bokeh2Pass(camera) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      classCallCheck(this, Bokeh2Pass);
      var _this = possibleConstructorReturn(this, (Bokeh2Pass.__proto__ || Object.getPrototypeOf(Bokeh2Pass)).call(this));
      _this.name = "Bokeh2Pass";
      _this.needsSwap = true;
      _this.bokehMaterial = new Bokeh2Material(camera, options);
      _this.quad.material = _this.bokehMaterial;
      return _this;
    }
    createClass(Bokeh2Pass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        this.bokehMaterial.uniforms.tDiffuse.value = readBuffer.texture;
        this.bokehMaterial.uniforms.tDepth.value = readBuffer.depthTexture;
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        this.bokehMaterial.setTexelSize(1.0 / width, 1.0 / height);
      }
    }]);
    return Bokeh2Pass;
  }(Pass);
  var ClearMaskPass = function(_Pass) {
    inherits(ClearMaskPass, _Pass);
    function ClearMaskPass() {
      classCallCheck(this, ClearMaskPass);
      var _this = possibleConstructorReturn(this, (ClearMaskPass.__proto__ || Object.getPrototypeOf(ClearMaskPass)).call(this, null, null, null));
      _this.name = "ClearMaskPass";
      return _this;
    }
    createClass(ClearMaskPass, [{
      key: "render",
      value: function render(renderer) {
        renderer.state.buffers.stencil.setTest(false);
      }
    }]);
    return ClearMaskPass;
  }(Pass);
  var color = new three.Color();
  var ClearPass = function(_Pass) {
    inherits(ClearPass, _Pass);
    function ClearPass() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, ClearPass);
      var _this = possibleConstructorReturn(this, (ClearPass.__proto__ || Object.getPrototypeOf(ClearPass)).call(this, null, null, null));
      _this.name = "ClearPass";
      _this.clearColor = options.clearColor !== undefined ? options.clearColor : null;
      _this.clearAlpha = options.clearAlpha !== undefined ? options.clearAlpha : 0.0;
      return _this;
    }
    createClass(ClearPass, [{
      key: "render",
      value: function render(renderer, readBuffer) {
        var clearColor = this.clearColor;
        var clearAlpha = void 0;
        if (clearColor !== null) {
          color.copy(renderer.getClearColor());
          clearAlpha = renderer.getClearAlpha();
          renderer.setClearColor(clearColor, this.clearAlpha);
        }
        renderer.setRenderTarget(this.renderToScreen ? null : readBuffer);
        renderer.clear();
        if (clearColor !== null) {
          renderer.setClearColor(color, clearAlpha);
        }
      }
    }]);
    return ClearPass;
  }(Pass);
  var DotScreenPass = function(_Pass) {
    inherits(DotScreenPass, _Pass);
    function DotScreenPass() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, DotScreenPass);
      var _this = possibleConstructorReturn(this, (DotScreenPass.__proto__ || Object.getPrototypeOf(DotScreenPass)).call(this));
      _this.name = "DotScreenPass";
      _this.needsSwap = true;
      _this.material = new DotScreenMaterial(options.average);
      if (options.angle !== undefined) {
        _this.material.uniforms.angle.value = options.angle;
      }
      if (options.scale !== undefined) {
        _this.material.uniforms.scale.value = options.scale;
      }
      if (options.intensity !== undefined) {
        _this.material.uniforms.intensity.value = options.intensity;
      }
      _this.quad.material = _this.material;
      return _this;
    }
    createClass(DotScreenPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        this.material.uniforms.tDiffuse.value = readBuffer.texture;
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        width = Math.max(1, width);
        height = Math.max(1, height);
        this.material.uniforms.offsetRepeat.value.z = width;
        this.material.uniforms.offsetRepeat.value.w = height;
      }
    }]);
    return DotScreenPass;
  }(Pass);
  var FilmPass = function(_Pass) {
    inherits(FilmPass, _Pass);
    function FilmPass() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, FilmPass);
      var _this = possibleConstructorReturn(this, (FilmPass.__proto__ || Object.getPrototypeOf(FilmPass)).call(this));
      _this.name = "FilmPass";
      _this.needsSwap = true;
      _this.material = new FilmMaterial(options);
      _this.quad.material = _this.material;
      _this.scanlineDensity = options.scanlineDensity === undefined ? 1.25 : options.scanlineDensity;
      return _this;
    }
    createClass(FilmPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer, delta) {
        this.material.uniforms.tDiffuse.value = readBuffer.texture;
        this.material.uniforms.time.value += delta;
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        this.material.uniforms.scanlineCount.value = Math.round(height * this.scanlineDensity);
      }
    }]);
    return FilmPass;
  }(Pass);
  function randomInt(low, high) {
    return low + Math.floor(Math.random() * (high - low + 1));
  }
  function randomFloat(low, high) {
    return low + Math.random() * (high - low);
  }
  var GlitchPass = function(_Pass) {
    inherits(GlitchPass, _Pass);
    function GlitchPass() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, GlitchPass);
      var _this = possibleConstructorReturn(this, (GlitchPass.__proto__ || Object.getPrototypeOf(GlitchPass)).call(this));
      _this.name = "GlitchPass";
      _this.needsSwap = true;
      _this.material = new GlitchMaterial();
      _this.quad.material = _this.material;
      _this.texture = null;
      _this.perturbMap = options.perturbMap !== undefined ? options.perturbMap : _this.generatePerturbMap(options.dtSize);
      _this.perturbMap.name = "Glitch.Perturbation";
      _this.perturbMap.generateMipmaps = false;
      _this.mode = GlitchMode.SPORADIC;
      _this.counter = 0;
      _this.breakPoint = randomInt(120, 240);
      return _this;
    }
    createClass(GlitchPass, [{
      key: "generatePerturbMap",
      value: function generatePerturbMap() {
        var size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 64;
        var pixels = size * size;
        var data = new Float32Array(pixels * 3);
        var dt = this.perturbMap;
        var i = void 0,
            x = void 0;
        for (i = 0; i < pixels; ++i) {
          x = Math.random();
          data[i * 3] = x;
          data[i * 3 + 1] = x;
          data[i * 3 + 2] = x;
        }
        if (dt !== null) {
          dt.dispose();
        }
        dt = new three.DataTexture(data, size, size, three.RGBFormat, three.FloatType);
        dt.needsUpdate = true;
        this.perturbMap = dt;
        return dt;
      }
    }, {
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        var mode = this.mode;
        var counter = this.counter;
        var breakPoint = this.breakPoint;
        var uniforms = this.material.uniforms;
        uniforms.tDiffuse.value = readBuffer.texture;
        uniforms.seed.value = Math.random();
        uniforms.active.value = true;
        if (counter % breakPoint === 0 || mode === GlitchMode.CONSTANT_WILD) {
          uniforms.amount.value = Math.random() / 30.0;
          uniforms.angle.value = randomFloat(-Math.PI, Math.PI);
          uniforms.seedX.value = randomFloat(-1.0, 1.0);
          uniforms.seedY.value = randomFloat(-1.0, 1.0);
          uniforms.distortionX.value = randomFloat(0.0, 1.0);
          uniforms.distortionY.value = randomFloat(0.0, 1.0);
          this.breakPoint = randomInt(120, 240);
          this.counter = 0;
        } else {
          if (counter % breakPoint < breakPoint / 5 || mode === GlitchMode.CONSTANT_MILD) {
            uniforms.amount.value = Math.random() / 90.0;
            uniforms.angle.value = randomFloat(-Math.PI, Math.PI);
            uniforms.distortionX.value = randomFloat(0.0, 1.0);
            uniforms.distortionY.value = randomFloat(0.0, 1.0);
            uniforms.seedX.value = randomFloat(-0.3, 0.3);
            uniforms.seedY.value = randomFloat(-0.3, 0.3);
          } else {
            uniforms.active.value = false;
          }
        }
        ++this.counter;
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "perturbMap",
      get: function get$$1() {
        return this.texture;
      },
      set: function set$$1(value) {
        this.texture = value;
        this.material.uniforms.tPerturb.value = value;
      }
    }]);
    return GlitchPass;
  }(Pass);
  var GlitchMode = {
    SPORADIC: 0,
    CONSTANT_MILD: 1,
    CONSTANT_WILD: 2
  };
  var RenderPass = function(_Pass) {
    inherits(RenderPass, _Pass);
    function RenderPass(scene, camera) {
      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      classCallCheck(this, RenderPass);
      var _this = possibleConstructorReturn(this, (RenderPass.__proto__ || Object.getPrototypeOf(RenderPass)).call(this, scene, camera, null));
      _this.name = "RenderPass";
      _this.clearPass = new ClearPass(options);
      _this.overrideMaterial = options.overrideMaterial !== undefined ? options.overrideMaterial : null;
      _this.clearDepth = options.clearDepth !== undefined ? options.clearDepth : false;
      _this.clear = options.clear !== undefined ? options.clear : true;
      return _this;
    }
    createClass(RenderPass, [{
      key: "render",
      value: function render(renderer, readBuffer) {
        var scene = this.scene;
        var target = this.renderToScreen ? null : readBuffer;
        if (this.clear) {
          this.clearPass.render(renderer, target);
        } else if (this.clearDepth) {
          renderer.setRenderTarget(target);
          renderer.clearDepth();
        }
        scene.overrideMaterial = this.overrideMaterial;
        renderer.render(scene, this.camera, target);
        scene.overrideMaterial = null;
      }
    }]);
    return RenderPass;
  }(Pass);
  function clamp(value, min, max) {
    return Math.max(min, Math.min(max, value));
  }
  var GodRaysPass = function(_Pass) {
    inherits(GodRaysPass, _Pass);
    function GodRaysPass(scene, camera, lightSource) {
      var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
      classCallCheck(this, GodRaysPass);
      var _this = possibleConstructorReturn(this, (GodRaysPass.__proto__ || Object.getPrototypeOf(GodRaysPass)).call(this));
      _this.name = "GodRaysPass";
      _this.needsSwap = true;
      _this.lightScene = new three.Scene();
      _this.mainScene = scene;
      _this.mainCamera = camera;
      _this.renderPassLight = new RenderPass(_this.lightScene, _this.mainCamera);
      _this.renderPassMask = new RenderPass(_this.mainScene, _this.mainCamera, {
        overrideMaterial: new three.MeshBasicMaterial({color: 0x000000}),
        clearColor: new three.Color(0x000000)
      });
      _this.renderPassMask.clear = false;
      _this.blurPass = new BlurPass(options);
      _this.renderTargetX = new three.WebGLRenderTarget(1, 1, {
        minFilter: three.LinearFilter,
        magFilter: three.LinearFilter,
        stencilBuffer: false,
        depthBuffer: false
      });
      _this.renderTargetX.texture.name = "GodRays.TargetX";
      _this.renderTargetX.texture.generateMipmaps = false;
      _this.renderTargetY = _this.renderTargetX.clone();
      _this.renderTargetY.texture.name = "GodRays.TargetY";
      _this.renderTargetMask = new three.WebGLRenderTarget(1, 1, {
        minFilter: three.LinearFilter,
        magFilter: three.LinearFilter
      });
      _this.renderTargetMask.texture.name = "GodRays.Mask";
      _this.renderTargetMask.texture.generateMipmaps = false;
      _this.lightSource = lightSource;
      _this.screenPosition = new three.Vector3();
      _this.godRaysMaterial = new GodRaysMaterial();
      _this.godRaysMaterial.uniforms.lightPosition.value = _this.screenPosition;
      if (options.exposure !== undefined) {
        _this.godRaysMaterial.uniforms.exposure.value = options.exposure;
      }
      if (options.density !== undefined) {
        _this.godRaysMaterial.uniforms.density.value = options.density;
      }
      if (options.decay !== undefined) {
        _this.godRaysMaterial.uniforms.decay.value = options.decay;
      }
      if (options.weight !== undefined) {
        _this.godRaysMaterial.uniforms.weight.value = options.weight;
      }
      if (options.clampMax !== undefined) {
        _this.godRaysMaterial.uniforms.clampMax.value = options.clampMax;
      }
      _this.samples = options.samples;
      _this.combineMaterial = new CombineMaterial(options.screenMode !== undefined ? options.screenMode : true);
      _this.intensity = options.intensity;
      return _this;
    }
    createClass(GodRaysPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        var quad = this.quad;
        var scene = this.scene;
        var camera = this.camera;
        var mainScene = this.mainScene;
        var lightSource = this.lightSource;
        var screenPosition = this.screenPosition;
        var godRaysMaterial = this.godRaysMaterial;
        var combineMaterial = this.combineMaterial;
        var renderTargetMask = this.renderTargetMask;
        var renderTargetX = this.renderTargetX;
        var renderTargetY = this.renderTargetY;
        var background = void 0,
            parent = void 0;
        screenPosition.copy(lightSource.position).project(this.mainCamera);
        screenPosition.x = clamp((screenPosition.x + 1.0) * 0.5, 0.0, 1.0);
        screenPosition.y = clamp((screenPosition.y + 1.0) * 0.5, 0.0, 1.0);
        parent = lightSource.parent;
        background = mainScene.background;
        mainScene.background = null;
        this.lightScene.add(lightSource);
        this.renderPassLight.render(renderer, renderTargetMask);
        this.renderPassMask.render(renderer, renderTargetMask);
        if (parent !== null) {
          parent.add(lightSource);
        }
        mainScene.background = background;
        this.blurPass.render(renderer, renderTargetMask, renderTargetX);
        quad.material = godRaysMaterial;
        godRaysMaterial.uniforms.tDiffuse.value = renderTargetX.texture;
        renderer.render(scene, camera, renderTargetY);
        quad.material = combineMaterial;
        combineMaterial.uniforms.texture1.value = readBuffer.texture;
        combineMaterial.uniforms.texture2.value = renderTargetY.texture;
        renderer.render(scene, camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "initialise",
      value: function initialise(renderer, alpha) {
        this.renderPassLight.initialise(renderer, alpha);
        this.renderPassMask.initialise(renderer, alpha);
        this.blurPass.initialise(renderer, alpha);
        if (!alpha) {
          this.renderTargetMask.texture.format = three.RGBFormat;
          this.renderTargetX.texture.format = three.RGBFormat;
          this.renderTargetY.texture.format = three.RGBFormat;
        }
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        this.renderPassLight.setSize(width, height);
        this.renderPassMask.setSize(width, height);
        this.blurPass.setSize(width, height);
        width = this.blurPass.width;
        height = this.blurPass.height;
        this.renderTargetMask.setSize(width, height);
        this.renderTargetX.setSize(width, height);
        this.renderTargetY.setSize(width, height);
      }
    }, {
      key: "resolutionScale",
      get: function get$$1() {
        return this.blurPass.resolutionScale;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.5;
        this.blurPass.resolutionScale = value;
      }
    }, {
      key: "kernelSize",
      get: function get$$1() {
        return this.blurPass.kernelSize;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : KernelSize.LARGE;
        this.blurPass.kernelSize = value;
      }
    }, {
      key: "intensity",
      get: function get$$1() {
        return this.combineMaterial.uniforms.opacity2.value;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1.0;
        this.combineMaterial.uniforms.opacity2.value = value;
      }
    }, {
      key: "samples",
      get: function get$$1() {
        return Number.parseInt(this.godRaysMaterial.defines.NUM_SAMPLES_INT);
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 60;
        value = Math.floor(value);
        this.godRaysMaterial.defines.NUM_SAMPLES_FLOAT = value.toFixed(1);
        this.godRaysMaterial.defines.NUM_SAMPLES_INT = value.toFixed(0);
        this.godRaysMaterial.needsUpdate = true;
      }
    }]);
    return GodRaysPass;
  }(Pass);
  var MaskPass = function(_Pass) {
    inherits(MaskPass, _Pass);
    function MaskPass(scene, camera) {
      classCallCheck(this, MaskPass);
      var _this = possibleConstructorReturn(this, (MaskPass.__proto__ || Object.getPrototypeOf(MaskPass)).call(this, scene, camera, null));
      _this.name = "MaskPass";
      _this.inverse = false;
      _this.clearStencil = true;
      return _this;
    }
    createClass(MaskPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        var context = renderer.context;
        var state = renderer.state;
        var scene = this.scene;
        var camera = this.camera;
        var writeValue = this.inverse ? 0 : 1;
        var clearValue = 1 - writeValue;
        state.buffers.color.setMask(false);
        state.buffers.depth.setMask(false);
        state.buffers.color.setLocked(true);
        state.buffers.depth.setLocked(true);
        state.buffers.stencil.setTest(true);
        state.buffers.stencil.setOp(context.REPLACE, context.REPLACE, context.REPLACE);
        state.buffers.stencil.setFunc(context.ALWAYS, writeValue, 0xffffffff);
        state.buffers.stencil.setClear(clearValue);
        if (this.clearStencil) {
          renderer.setRenderTarget(readBuffer);
          renderer.clearStencil();
          renderer.setRenderTarget(writeBuffer);
          renderer.clearStencil();
        }
        renderer.render(scene, camera, readBuffer);
        renderer.render(scene, camera, writeBuffer);
        state.buffers.color.setLocked(false);
        state.buffers.depth.setLocked(false);
        state.buffers.stencil.setFunc(context.EQUAL, 1, 0xffffffff);
        state.buffers.stencil.setOp(context.KEEP, context.KEEP, context.KEEP);
      }
    }]);
    return MaskPass;
  }(Pass);
  var PixelationPass = function(_Pass) {
    inherits(PixelationPass, _Pass);
    function PixelationPass() {
      var granularity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30.0;
      classCallCheck(this, PixelationPass);
      var _this = possibleConstructorReturn(this, (PixelationPass.__proto__ || Object.getPrototypeOf(PixelationPass)).call(this));
      _this.name = "PixelationPass";
      _this.needsSwap = true;
      _this.pixelationMaterial = new PixelationMaterial();
      _this.granularity = granularity;
      _this.quad.material = _this.pixelationMaterial;
      return _this;
    }
    createClass(PixelationPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        this.pixelationMaterial.uniforms.tDiffuse.value = readBuffer.texture;
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        this.pixelationMaterial.setResolution(width, height);
      }
    }, {
      key: "granularity",
      get: function get$$1() {
        return this.pixelationMaterial.granularity;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30;
        value = Math.floor(value);
        if (value % 2 > 0) {
          value += 1;
        }
        this.pixelationMaterial.granularity = value;
      }
    }]);
    return PixelationPass;
  }(Pass);
  var SavePass = function(_Pass) {
    inherits(SavePass, _Pass);
    function SavePass(renderTarget) {
      var resize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      classCallCheck(this, SavePass);
      var _this = possibleConstructorReturn(this, (SavePass.__proto__ || Object.getPrototypeOf(SavePass)).call(this));
      _this.name = "SavePass";
      _this.material = new CopyMaterial();
      _this.quad.material = _this.material;
      _this.renderTarget = renderTarget !== undefined ? renderTarget : new three.WebGLRenderTarget(1, 1, {
        minFilter: three.LinearFilter,
        magFilter: three.LinearFilter,
        stencilBuffer: false,
        depthBuffer: false
      });
      _this.renderTarget.texture.name = "Save.Target";
      _this.renderTarget.texture.generateMipmaps = false;
      _this.resize = resize;
      return _this;
    }
    createClass(SavePass, [{
      key: "render",
      value: function render(renderer, readBuffer) {
        this.material.uniforms.tDiffuse.value = readBuffer.texture;
        renderer.render(this.scene, this.camera, this.renderTarget);
      }
    }, {
      key: "initialise",
      value: function initialise(renderer, alpha) {
        if (!alpha) {
          this.renderTarget.texture.format = three.RGBFormat;
        }
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        if (this.resize) {
          width = Math.max(1, width);
          height = Math.max(1, height);
          this.renderTarget.setSize(width, height);
        }
      }
    }]);
    return SavePass;
  }(Pass);
  var ShaderPass = function(_Pass) {
    inherits(ShaderPass, _Pass);
    function ShaderPass(material) {
      var textureID = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "tDiffuse";
      classCallCheck(this, ShaderPass);
      var _this = possibleConstructorReturn(this, (ShaderPass.__proto__ || Object.getPrototypeOf(ShaderPass)).call(this));
      _this.name = "ShaderPass";
      _this.needsSwap = true;
      _this.material = material;
      _this.quad.material = _this.material;
      _this.textureID = textureID;
      return _this;
    }
    createClass(ShaderPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        if (this.material.uniforms[this.textureID] !== undefined) {
          this.material.uniforms[this.textureID].value = readBuffer.texture;
        }
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }]);
    return ShaderPass;
  }(Pass);
  var HALF_PI = Math.PI * 0.5;
  var v = new three.Vector3();
  var ab = new three.Vector3();
  var ShockWavePass = function(_Pass) {
    inherits(ShockWavePass, _Pass);
    function ShockWavePass(camera) {
      var epicenter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new three.Vector3();
      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      classCallCheck(this, ShockWavePass);
      var _this = possibleConstructorReturn(this, (ShockWavePass.__proto__ || Object.getPrototypeOf(ShockWavePass)).call(this));
      _this.name = "ShockWavePass";
      _this.needsSwap = true;
      _this.mainCamera = camera;
      _this.epicenter = epicenter;
      _this.screenPosition = new three.Vector3();
      _this.speed = options.speed !== undefined ? options.speed : 2.0;
      _this.time = 0.0;
      _this.active = false;
      _this.shockWaveMaterial = new ShockWaveMaterial(options);
      _this.shockWaveMaterial.uniforms.center.value = _this.screenPosition;
      _this.copyMaterial = new CopyMaterial();
      return _this;
    }
    createClass(ShockWavePass, [{
      key: "explode",
      value: function explode() {
        this.time = 0.0;
        this.active = true;
      }
    }, {
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer, delta) {
        var epicenter = this.epicenter;
        var mainCamera = this.mainCamera;
        var screenPosition = this.screenPosition;
        var shockWaveMaterial = this.shockWaveMaterial;
        var uniforms = shockWaveMaterial.uniforms;
        var center = uniforms.center;
        var radius = uniforms.radius;
        var maxRadius = uniforms.maxRadius;
        var waveSize = uniforms.waveSize;
        this.copyMaterial.uniforms.tDiffuse.value = readBuffer.texture;
        this.quad.material = this.copyMaterial;
        if (this.active) {
          mainCamera.getWorldDirection(v);
          ab.copy(mainCamera.position).sub(epicenter);
          if (v.angleTo(ab) > HALF_PI) {
            uniforms.cameraDistance.value = mainCamera.position.distanceTo(epicenter);
            screenPosition.copy(epicenter).project(mainCamera);
            center.value.x = (screenPosition.x + 1.0) * 0.5;
            center.value.y = (screenPosition.y + 1.0) * 0.5;
            uniforms.tDiffuse.value = readBuffer.texture;
            this.quad.material = shockWaveMaterial;
          }
          this.time += delta * this.speed;
          radius.value = this.time - waveSize.value;
          if (radius.value >= (maxRadius.value + waveSize.value) * 2) {
            this.active = false;
          }
        }
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        this.shockWaveMaterial.uniforms.aspect.value = width / height;
      }
    }]);
    return ShockWavePass;
  }(Pass);
  var searchImageDataUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAhCAAAAABIXyLAAAAAOElEQVRIx2NgGAWjYBSMglEwEICREYRgFBZBqDCSLA2MGPUIVQETE9iNUAqLR5gIeoQKRgwXjwAAGn4AtaFeYLEAAAAASUVORK5CYII";
  var areaImageDataUrl = "data:image/png;base64, ";
  var SMAAPass = function(_Pass) {
    inherits(SMAAPass, _Pass);
    function SMAAPass(searchImage, areaImage) {
      classCallCheck(this, SMAAPass);
      var _this = possibleConstructorReturn(this, (SMAAPass.__proto__ || Object.getPrototypeOf(SMAAPass)).call(this));
      _this.name = "SMAAPass";
      _this.needsSwap = true;
      _this.renderTargetColorEdges = new three.WebGLRenderTarget(1, 1, {
        minFilter: three.LinearFilter,
        format: three.RGBFormat,
        stencilBuffer: false,
        depthBuffer: false
      });
      _this.renderTargetColorEdges.texture.name = "SMAA.ColorEdges";
      _this.renderTargetColorEdges.texture.generateMipmaps = false;
      _this.renderTargetWeights = _this.renderTargetColorEdges.clone();
      _this.renderTargetWeights.texture.name = "SMAA.Weights";
      _this.renderTargetWeights.texture.format = three.RGBAFormat;
      _this.colorEdgesMaterial = new SMAAColorEdgesMaterial();
      _this.weightsMaterial = new SMAAWeightsMaterial();
      _this.weightsMaterial.uniforms.tDiffuse.value = _this.renderTargetColorEdges.texture;
      _this.searchTexture = new three.Texture(searchImage);
      _this.searchTexture.name = "SMAA.Search";
      _this.searchTexture.magFilter = three.NearestFilter;
      _this.searchTexture.minFilter = three.NearestFilter;
      _this.searchTexture.format = three.RGBAFormat;
      _this.searchTexture.generateMipmaps = false;
      _this.searchTexture.needsUpdate = true;
      _this.searchTexture.flipY = false;
      _this.weightsMaterial.uniforms.tSearch.value = _this.searchTexture;
      _this.areaTexture = new three.Texture(areaImage);
      _this.areaTexture.name = "SMAA.Area";
      _this.areaTexture.minFilter = three.LinearFilter;
      _this.areaTexture.format = three.RGBAFormat;
      _this.areaTexture.generateMipmaps = false;
      _this.areaTexture.needsUpdate = true;
      _this.areaTexture.flipY = false;
      _this.weightsMaterial.uniforms.tArea.value = _this.areaTexture;
      _this.blendMaterial = new SMAABlendMaterial();
      _this.blendMaterial.uniforms.tWeights.value = _this.renderTargetWeights.texture;
      _this.quad.material = _this.blendMaterial;
      return _this;
    }
    createClass(SMAAPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer) {
        this.quad.material = this.colorEdgesMaterial;
        this.colorEdgesMaterial.uniforms.tDiffuse.value = readBuffer.texture;
        renderer.render(this.scene, this.camera, this.renderTargetColorEdges, true);
        this.quad.material = this.weightsMaterial;
        renderer.render(this.scene, this.camera, this.renderTargetWeights, false);
        this.quad.material = this.blendMaterial;
        this.blendMaterial.uniforms.tDiffuse.value = readBuffer.texture;
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        this.renderTargetColorEdges.setSize(width, height);
        this.renderTargetWeights.setSize(width, height);
        this.colorEdgesMaterial.uniforms.texelSize.value.copy(this.weightsMaterial.uniforms.texelSize.value.copy(this.blendMaterial.uniforms.texelSize.value.set(1.0 / width, 1.0 / height)));
      }
    }], [{
      key: "searchImageDataUrl",
      get: function get$$1() {
        return searchImageDataUrl;
      }
    }, {
      key: "areaImageDataUrl",
      get: function get$$1() {
        return areaImageDataUrl;
      }
    }]);
    return SMAAPass;
  }(Pass);
  var TexturePass = function(_Pass) {
    inherits(TexturePass, _Pass);
    function TexturePass(texture) {
      var opacity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1.0;
      classCallCheck(this, TexturePass);
      var _this = possibleConstructorReturn(this, (TexturePass.__proto__ || Object.getPrototypeOf(TexturePass)).call(this));
      _this.name = "TexturePass";
      _this.copyMaterial = new CopyMaterial();
      _this.copyMaterial.blending = three.AdditiveBlending;
      _this.copyMaterial.transparent = true;
      _this.texture = texture;
      _this.opacity = opacity;
      _this.quad.material = _this.copyMaterial;
      return _this;
    }
    createClass(TexturePass, [{
      key: "render",
      value: function render(renderer, readBuffer) {
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : readBuffer);
      }
    }, {
      key: "texture",
      get: function get$$1() {
        return this.copyMaterial.uniforms.tDiffuse.value;
      },
      set: function set$$1(value) {
        this.copyMaterial.uniforms.tDiffuse.value = value;
      }
    }, {
      key: "opacity",
      get: function get$$1() {
        return this.copyMaterial.uniforms.opacity.value;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1.0;
        this.copyMaterial.uniforms.opacity.value = value;
      }
    }]);
    return TexturePass;
  }(Pass);
  function ceil2(n) {
    return Math.pow(2, Math.max(0, Math.ceil(Math.log2(n))));
  }
  var ToneMappingPass = function(_Pass) {
    inherits(ToneMappingPass, _Pass);
    function ToneMappingPass() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      classCallCheck(this, ToneMappingPass);
      var _this = possibleConstructorReturn(this, (ToneMappingPass.__proto__ || Object.getPrototypeOf(ToneMappingPass)).call(this));
      _this.name = "ToneMappingPass";
      _this.needsSwap = true;
      _this.renderTargetLuminosity = new three.WebGLRenderTarget(1, 1, {
        minFilter: three.LinearMipMapLinearFilter,
        magFilter: three.LinearFilter,
        format: three.RGBFormat,
        stencilBuffer: false,
        depthBuffer: false
      });
      _this.renderTargetLuminosity.texture.name = "ToneMapping.Luminosity";
      _this.renderTargetAdapted = _this.renderTargetLuminosity.clone();
      _this.renderTargetAdapted.texture.name = "ToneMapping.AdaptedLuminosity";
      _this.renderTargetAdapted.texture.generateMipmaps = false;
      _this.renderTargetAdapted.texture.minFilter = three.LinearFilter;
      _this.renderTargetPrevious = _this.renderTargetAdapted.clone();
      _this.renderTargetPrevious.texture.name = "ToneMapping.PreviousLuminosity";
      _this.copyMaterial = new CopyMaterial();
      _this.luminosityMaterial = new LuminosityMaterial();
      _this.luminosityMaterial.uniforms.distinction.value = options.distinction !== undefined ? options.distinction : 1.0;
      _this.adaptiveLuminosityMaterial = new AdaptiveLuminosityMaterial();
      _this.resolution = options.resolution;
      _this.toneMappingMaterial = new ToneMappingMaterial();
      _this.adaptive = options.adaptive;
      return _this;
    }
    createClass(ToneMappingPass, [{
      key: "render",
      value: function render(renderer, readBuffer, writeBuffer, delta) {
        var quad = this.quad;
        var scene = this.scene;
        var camera = this.camera;
        var adaptiveLuminosityMaterial = this.adaptiveLuminosityMaterial;
        var luminosityMaterial = this.luminosityMaterial;
        var toneMappingMaterial = this.toneMappingMaterial;
        var copyMaterial = this.copyMaterial;
        var renderTargetPrevious = this.renderTargetPrevious;
        var renderTargetLuminosity = this.renderTargetLuminosity;
        var renderTargetAdapted = this.renderTargetAdapted;
        if (this.adaptive) {
          quad.material = luminosityMaterial;
          luminosityMaterial.uniforms.tDiffuse.value = readBuffer.texture;
          renderer.render(scene, camera, renderTargetLuminosity);
          quad.material = adaptiveLuminosityMaterial;
          adaptiveLuminosityMaterial.uniforms.delta.value = delta;
          adaptiveLuminosityMaterial.uniforms.tPreviousLum.value = renderTargetPrevious.texture;
          adaptiveLuminosityMaterial.uniforms.tCurrentLum.value = renderTargetLuminosity.texture;
          renderer.render(scene, camera, renderTargetAdapted);
          quad.material = copyMaterial;
          copyMaterial.uniforms.tDiffuse.value = renderTargetAdapted.texture;
          renderer.render(scene, camera, renderTargetPrevious);
        }
        quad.material = toneMappingMaterial;
        toneMappingMaterial.uniforms.tDiffuse.value = readBuffer.texture;
        renderer.render(this.scene, this.camera, this.renderToScreen ? null : writeBuffer);
      }
    }, {
      key: "initialise",
      value: function initialise(renderer) {
        this.quad.material = new three.MeshBasicMaterial({color: 0x7fffff});
        renderer.render(this.scene, this.camera, this.renderTargetPrevious);
        this.quad.material.dispose();
      }
    }, {
      key: "resolution",
      get: function get$$1() {
        return this.renderTargetLuminosity.width;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 256;
        value = ceil2(value);
        this.renderTargetLuminosity.setSize(value, value);
        this.renderTargetPrevious.setSize(value, value);
        this.renderTargetAdapted.setSize(value, value);
        this.adaptiveLuminosityMaterial.defines.MIP_LEVEL_1X1 = (Math.round(Math.log(value)) / Math.log(2)).toFixed(1);
        this.adaptiveLuminosityMaterial.needsUpdate = true;
      }
    }, {
      key: "adaptive",
      get: function get$$1() {
        return this.toneMappingMaterial.defines.ADAPTED_LUMINANCE !== undefined;
      },
      set: function set$$1() {
        var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
        if (value) {
          this.toneMappingMaterial.defines.ADAPTED_LUMINANCE = "1";
          this.toneMappingMaterial.uniforms.luminanceMap.value = this.renderTargetAdapted.texture;
        } else {
          delete this.toneMappingMaterial.defines.ADAPTED_LUMINANCE;
          this.toneMappingMaterial.uniforms.luminanceMap.value = null;
        }
        this.toneMappingMaterial.needsUpdate = true;
      }
    }]);
    return ToneMappingPass;
  }(Pass);
  var EffectComposer = function() {
    function EffectComposer() {
      var renderer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      classCallCheck(this, EffectComposer);
      this.renderer = renderer;
      this.readBuffer = null;
      this.writeBuffer = null;
      if (this.renderer !== null) {
        this.renderer.autoClear = false;
        this.readBuffer = this.createBuffer(options.depthBuffer !== undefined ? options.depthBuffer : true, options.stencilBuffer !== undefined ? options.stencilBuffer : false, options.depthTexture !== undefined ? options.depthTexture : false);
        this.writeBuffer = this.readBuffer.clone();
      }
      this.copyPass = new ShaderPass(new CopyMaterial());
      this.passes = [];
    }
    createClass(EffectComposer, [{
      key: "replaceRenderer",
      value: function replaceRenderer(renderer) {
        var oldRenderer = this.renderer;
        var parent = void 0,
            oldSize = void 0,
            newSize = void 0;
        if (oldRenderer !== null && oldRenderer !== renderer) {
          this.renderer = renderer;
          this.renderer.autoClear = false;
          parent = oldRenderer.domElement.parentNode;
          oldSize = oldRenderer.getSize();
          newSize = renderer.getSize();
          if (parent !== null) {
            parent.removeChild(oldRenderer.domElement);
            parent.appendChild(renderer.domElement);
          }
          if (oldSize.width !== newSize.width || oldSize.height !== newSize.height) {
            this.setSize();
          }
        }
        return oldRenderer;
      }
    }, {
      key: "createBuffer",
      value: function createBuffer(depthBuffer, stencilBuffer, depthTexture) {
        var drawingBufferSize = this.renderer.getDrawingBufferSize();
        var alpha = this.renderer.context.getContextAttributes().alpha;
        var renderTarget = new three.WebGLRenderTarget(drawingBufferSize.width, drawingBufferSize.height, {
          minFilter: three.LinearFilter,
          magFilter: three.LinearFilter,
          format: alpha ? three.RGBAFormat : three.RGBFormat,
          depthBuffer: depthBuffer,
          stencilBuffer: stencilBuffer,
          depthTexture: depthTexture ? new three.DepthTexture() : null
        });
        if (depthTexture && stencilBuffer) {
          renderTarget.depthTexture.format = three.DepthStencilFormat;
          renderTarget.depthTexture.type = three.UnsignedInt248Type;
        }
        renderTarget.texture.name = "EffectComposer.Buffer";
        renderTarget.texture.generateMipmaps = false;
        return renderTarget;
      }
    }, {
      key: "addPass",
      value: function addPass(pass, index) {
        var renderer = this.renderer;
        var drawingBufferSize = renderer.getDrawingBufferSize();
        pass.setSize(drawingBufferSize.width, drawingBufferSize.height);
        pass.initialise(renderer, renderer.context.getContextAttributes().alpha);
        if (index !== undefined) {
          this.passes.splice(index, 0, pass);
        } else {
          this.passes.push(pass);
        }
      }
    }, {
      key: "removePass",
      value: function removePass(pass) {
        this.passes.splice(this.passes.indexOf(pass), 1);
      }
    }, {
      key: "render",
      value: function render(delta) {
        var passes = this.passes;
        var renderer = this.renderer;
        var copyPass = this.copyPass;
        var readBuffer = this.readBuffer;
        var writeBuffer = this.writeBuffer;
        var maskActive = false;
        var pass = void 0,
            context = void 0,
            buffer = void 0;
        var i = void 0,
            l = void 0;
        for (i = 0, l = passes.length; i < l; ++i) {
          pass = passes[i];
          if (pass.enabled) {
            pass.render(renderer, readBuffer, writeBuffer, delta, maskActive);
            if (pass.needsSwap) {
              if (maskActive) {
                context = renderer.context;
                context.stencilFunc(context.NOTEQUAL, 1, 0xffffffff);
                copyPass.render(renderer, readBuffer, writeBuffer);
                context.stencilFunc(context.EQUAL, 1, 0xffffffff);
              }
              buffer = readBuffer;
              readBuffer = writeBuffer;
              writeBuffer = buffer;
            }
            if (pass instanceof MaskPass) {
              maskActive = true;
            } else if (pass instanceof ClearMaskPass) {
              maskActive = false;
            }
          }
        }
      }
    }, {
      key: "setSize",
      value: function setSize(width, height) {
        var passes = this.passes;
        var renderer = this.renderer;
        var size = void 0,
            drawingBufferSize = void 0;
        var i = void 0,
            l = void 0;
        if (width === undefined || height === undefined) {
          size = renderer.getSize();
          width = size.width;
          height = size.height;
        }
        renderer.setSize(width, height);
        drawingBufferSize = renderer.getDrawingBufferSize();
        this.readBuffer.setSize(drawingBufferSize.width, drawingBufferSize.height);
        this.writeBuffer.setSize(drawingBufferSize.width, drawingBufferSize.height);
        for (i = 0, l = passes.length; i < l; ++i) {
          passes[i].setSize(drawingBufferSize.width, drawingBufferSize.height);
        }
      }
    }, {
      key: "reset",
      value: function reset(renderTarget) {
        var depthBuffer = this.readBuffer.depthBuffer;
        var stencilBuffer = this.readBuffer.stencilBuffer;
        var depthTexture = this.readBuffer.depthTexture !== null;
        this.dispose(renderTarget === undefined ? this.createBuffer(depthBuffer, stencilBuffer, depthTexture) : renderTarget);
      }
    }, {
      key: "dispose",
      value: function dispose(renderTarget) {
        var passes = this.passes;
        if (this.readBuffer !== null && this.writeBuffer !== null) {
          this.readBuffer.dispose();
          this.writeBuffer.dispose();
          this.readBuffer = null;
          this.writeBuffer = null;
        }
        while (passes.length > 0) {
          passes.pop().dispose();
        }
        if (renderTarget !== undefined) {
          this.readBuffer = renderTarget;
          this.writeBuffer = this.readBuffer.clone();
        } else {
          this.copyPass.dispose();
        }
      }
    }, {
      key: "depthTexture",
      get: function get$$1() {
        return this.readBuffer.depthTexture;
      },
      set: function set$$1(x) {
        this.readBuffer.depthTexture = x;
        this.writeBuffer.depthTexture = x;
      }
    }]);
    return EffectComposer;
  }();
  function createCanvas(width, height, data, channels) {
    var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
    var context = canvas.getContext("2d");
    var imageData = context.createImageData(width, height);
    var target = imageData.data;
    var x = void 0,
        y = void 0;
    var i = void 0,
        j = void 0;
    for (y = 0; y < height; ++y) {
      for (x = 0; x < width; ++x) {
        i = (y * width + x) * 4;
        j = (y * width + x) * channels;
        target[i] = channels > 0 ? data[j] : 0;
        target[i + 1] = channels > 1 ? data[j + 1] : 0;
        target[i + 2] = channels > 2 ? data[j + 2] : 0;
        target[i + 3] = channels > 3 ? data[j + 3] : 255;
      }
    }
    canvas.width = width;
    canvas.height = height;
    context.putImageData(imageData, 0, 0);
    return canvas;
  }
  var RawImageData = function() {
    function RawImageData() {
      var width = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
      var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
      var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var channels = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
      classCallCheck(this, RawImageData);
      this.width = width;
      this.height = height;
      this.data = data;
      this.channels = channels;
    }
    createClass(RawImageData, [{
      key: "toCanvas",
      value: function toCanvas() {
        return typeof document === "undefined" ? null : createCanvas(this.width, this.height, this.data, this.channels);
      }
    }]);
    return RawImageData;
  }();
  var b0 = new three.Box2();
  var b1 = new three.Box2();
  var ORTHOGONAL_SIZE = 16;
  var DIAGONAL_SIZE = 20;
  var DIAGONAL_SAMPLES = 30;
  var SMOOTH_MAX_DISTANCE = 32;
  var orthogonalSubsamplingOffsets = new Float32Array([0.0, -0.25, 0.25, -0.125, 0.125, -0.375, 0.375]);
  var diagonalSubsamplingOffsets = [new Float32Array([0.0, 0.0]), new Float32Array([0.25, -0.25]), new Float32Array([-0.25, 0.25]), new Float32Array([0.125, -0.125]), new Float32Array([-0.125, 0.125])];
  var orthogonalEdges = [new Uint8Array([0, 0]), new Uint8Array([3, 0]), new Uint8Array([0, 3]), new Uint8Array([3, 3]), new Uint8Array([1, 0]), new Uint8Array([4, 0]), new Uint8Array([1, 3]), new Uint8Array([4, 3]), new Uint8Array([0, 1]), new Uint8Array([3, 1]), new Uint8Array([0, 4]), new Uint8Array([3, 4]), new Uint8Array([1, 1]), new Uint8Array([4, 1]), new Uint8Array([1, 4]), new Uint8Array([4, 4])];
  var diagonalEdges = [new Uint8Array([0, 0]), new Uint8Array([1, 0]), new Uint8Array([0, 2]), new Uint8Array([1, 2]), new Uint8Array([2, 0]), new Uint8Array([3, 0]), new Uint8Array([2, 2]), new Uint8Array([3, 2]), new Uint8Array([0, 1]), new Uint8Array([1, 1]), new Uint8Array([0, 3]), new Uint8Array([1, 3]), new Uint8Array([2, 1]), new Uint8Array([3, 1]), new Uint8Array([2, 3]), new Uint8Array([3, 3])];
  function lerp(a, b, p) {
    return a + (b - a) * p;
  }
  function saturate(a) {
    return Math.min(Math.max(a, 0.0), 1.0);
  }
  function smoothArea(d, b) {
    var a1 = b.min;
    var a2 = b.max;
    var b1X = Math.sqrt(a1.x * 2.0) * 0.5;
    var b1Y = Math.sqrt(a1.y * 2.0) * 0.5;
    var b2X = Math.sqrt(a2.x * 2.0) * 0.5;
    var b2Y = Math.sqrt(a2.y * 2.0) * 0.5;
    var p = saturate(d / SMOOTH_MAX_DISTANCE);
    a1.set(lerp(b1X, a1.x, p), lerp(b1Y, a1.y, p));
    a2.set(lerp(b2X, a2.x, p), lerp(b2Y, a2.y, p));
    return b;
  }
  function calculateOrthogonalArea(p1, p2, x, result) {
    var dX = p2.x - p1.x;
    var dY = p2.y - p1.y;
    var x1 = x;
    var x2 = x + 1.0;
    var y1 = p1.y + dY * (x1 - p1.x) / dX;
    var y2 = p1.y + dY * (x2 - p1.x) / dX;
    var a = void 0,
        a1 = void 0,
        a2 = void 0,
        t = void 0;
    if (x1 >= p1.x && x1 < p2.x || x2 > p1.x && x2 <= p2.x) {
      if (Math.sign(y1) === Math.sign(y2) || Math.abs(y1) < 1e-4 || Math.abs(y2) < 1e-4) {
        a = (y1 + y2) / 2.0;
        if (a < 0.0) {
          result.set(Math.abs(a), 0.0);
        } else {
          result.set(0.0, Math.abs(a));
        }
      } else {
        t = -p1.y * dX / dY + p1.x;
        a1 = t > p1.x ? y1 * (t - Math.trunc(t)) / 2.0 : 0.0;
        a2 = t < p2.x ? y2 * (1.0 - (t - Math.trunc(t))) / 2.0 : 0.0;
        a = Math.abs(a1) > Math.abs(a2) ? a1 : -a2;
        if (a < 0.0) {
          result.set(Math.abs(a1), Math.abs(a2));
        } else {
          result.set(Math.abs(a2), Math.abs(a1));
        }
      }
    } else {
      result.set(0, 0);
    }
    return result;
  }
  function calculateOrthogonalAreaForPattern(pattern, left, right, offset, result) {
    var p1 = b0.min;
    var p2 = b0.max;
    var a1 = b1.min;
    var a2 = b1.max;
    var a = b1;
    var o1 = 0.5 + offset;
    var o2 = 0.5 + offset - 1.0;
    var d = left + right + 1;
    switch (pattern) {
      case 0:
        {
          result.set(0, 0);
          break;
        }
      case 1:
        {
          if (left <= right) {
            calculateOrthogonalArea(p1.set(0.0, o2), p2.set(d / 2.0, 0.0), left, result);
          } else {
            result.set(0, 0);
          }
          break;
        }
      case 2:
        {
          if (left >= right) {
            calculateOrthogonalArea(p1.set(d / 2.0, 0.0), p2.set(d, o2), left, result);
          } else {
            result.set(0, 0);
          }
          break;
        }
      case 3:
        {
          calculateOrthogonalArea(p1.set(0.0, o2), p2.set(d / 2.0, 0.0), left, a1);
          calculateOrthogonalArea(p1.set(d / 2.0, 0.0), p2.set(d, o2), left, a2);
          smoothArea(d, a);
          result.addVectors(a1, a2);
          break;
        }
      case 4:
        {
          if (left <= right) {
            calculateOrthogonalArea(p1.set(0.0, o1), p2.set(d / 2.0, 0.0), left, result);
          } else {
            result.set(0, 0);
          }
          break;
        }
      case 5:
        {
          result.set(0, 0);
          break;
        }
      case 6:
        {
          if (Math.abs(offset) > 0.0) {
            calculateOrthogonalArea(p1.set(0.0, o1), p2.set(d, o2), left, a1);
            calculateOrthogonalArea(p1.set(0.0, o1), p2.set(d / 2.0, 0.0), left, a2);
            a2.add(calculateOrthogonalArea(p1.set(d / 2.0, 0.0), p2.set(d, o2), left, result));
            result.addVectors(a1, a2).divideScalar(2.0);
          } else {
            calculateOrthogonalArea(p1.set(0.0, o1), p2.set(d, o2), left, result);
          }
          break;
        }
      case 7:
        {
          calculateOrthogonalArea(p1.set(0.0, o1), p2.set(d, o2), left, result);
          break;
        }
      case 8:
        {
          if (left >= right) {
            calculateOrthogonalArea(p1.set(d / 2.0, 0.0), p2.set(d, o1), left, result);
          } else {
            result.set(0, 0);
          }
          break;
        }
      case 9:
        {
          if (Math.abs(offset) > 0.0) {
            calculateOrthogonalArea(p1.set(0.0, o2), p2.set(d, o1), left, a1);
            calculateOrthogonalArea(p1.set(0.0, o2), p2.set(d / 2.0, 0.0), left, a2);
            a2.add(calculateOrthogonalArea(p1.set(d / 2.0, 0.0), p2.set(d, o1), left, result));
            result.addVectors(a1, a2).divideScalar(2.0);
          } else {
            calculateOrthogonalArea(p1.set(0.0, o2), p2.set(d, o1), left, result);
          }
          break;
        }
      case 10:
        {
          result.set(0, 0);
          break;
        }
      case 11:
        {
          calculateOrthogonalArea(p1.set(0.0, o2), p2.set(d, o1), left, result);
          break;
        }
      case 12:
        {
          calculateOrthogonalArea(p1.set(0.0, o1), p2.set(d / 2.0, 0.0), left, a1);
          calculateOrthogonalArea(p1.set(d / 2.0, 0.0), p2.set(d, o1), left, a2);
          smoothArea(d, a);
          result.addVectors(a1, a2);
          break;
        }
      case 13:
        {
          calculateOrthogonalArea(p1.set(0.0, o2), p2.set(d, o1), left, result);
          break;
        }
      case 14:
        {
          calculateOrthogonalArea(p1.set(0.0, o1), p2.set(d, o2), left, result);
          break;
        }
      case 15:
        {
          result.set(0, 0);
          break;
        }
    }
    return result;
  }
  function isInsideArea(p1, p2, x, y) {
    var result = p1.equals(p2);
    var xm = void 0,
        ym = void 0;
    var a = void 0,
        b = void 0,
        c = void 0;
    if (!result) {
      xm = (p1.x + p2.x) / 2.0;
      ym = (p1.y + p2.y) / 2.0;
      a = p2.y - p1.y;
      b = p1.x - p2.x;
      c = a * (x - xm) + b * (y - ym);
      result = c > 0.0;
    }
    return result;
  }
  function calculateDiagonalAreaForPixel(p1, p2, pX, pY) {
    var a = void 0;
    var x = void 0,
        y = void 0;
    var offsetX = void 0,
        offsetY = void 0;
    for (a = 0, y = 0; y < DIAGONAL_SAMPLES; ++y) {
      for (x = 0; x < DIAGONAL_SAMPLES; ++x) {
        offsetX = x / (DIAGONAL_SAMPLES - 1.0);
        offsetY = y / (DIAGONAL_SAMPLES - 1.0);
        if (isInsideArea(p1, p2, pX + offsetX, pY + offsetY)) {
          ++a;
        }
      }
    }
    return a / (DIAGONAL_SAMPLES * DIAGONAL_SAMPLES);
  }
  function calculateDiagonalArea(pattern, p1, p2, left, offset, result) {
    var e = diagonalEdges[pattern];
    var e1 = e[0];
    var e2 = e[1];
    if (e1 > 0) {
      p1.x += offset[0];
      p1.y += offset[1];
    }
    if (e2 > 0) {
      p2.x += offset[0];
      p2.y += offset[1];
    }
    return result.set(1.0 - calculateDiagonalAreaForPixel(p1, p2, 1.0 + left, 0.0 + left), calculateDiagonalAreaForPixel(p1, p2, 1.0 + left, 1.0 + left));
  }
  function calculateDiagonalAreaForPattern(pattern, left, right, offset, result) {
    var p1 = b0.min;
    var p2 = b0.max;
    var a1 = b1.min;
    var a2 = b1.max;
    var d = left + right + 1;
    switch (pattern) {
      case 0:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 1.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 1:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(0.0 + d, 0.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 2:
        {
          calculateDiagonalArea(pattern, p1.set(0.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 3:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, result);
          break;
        }
      case 4:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(0.0 + d, 0.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 5:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(0.0 + d, 0.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 6:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 0.0 + d), left, offset, result);
          break;
        }
      case 7:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 0.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 8:
        {
          calculateDiagonalArea(pattern, p1.set(0.0, 0.0), p2.set(1.0 + d, 1.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 1.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 9:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 1.0 + d), left, offset, result);
          break;
        }
      case 10:
        {
          calculateDiagonalArea(pattern, p1.set(0.0, 0.0), p2.set(1.0 + d, 1.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 11:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 1.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 12:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 1.0 + d), left, offset, result);
          break;
        }
      case 13:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 1.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 1.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 14:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 1.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
      case 15:
        {
          calculateDiagonalArea(pattern, p1.set(1.0, 1.0), p2.set(1.0 + d, 1.0 + d), left, offset, a1);
          calculateDiagonalArea(pattern, p1.set(1.0, 0.0), p2.set(1.0 + d, 0.0 + d), left, offset, a2);
          result.addVectors(a1, a2).divideScalar(2.0);
          break;
        }
    }
    return result;
  }
  function generatePatterns(patterns, offset, orthogonal) {
    var result = new three.Vector2();
    var i = void 0,
        l = void 0;
    var x = void 0,
        y = void 0;
    var c = void 0;
    var pattern = void 0;
    var data = void 0,
        size = void 0;
    for (i = 0, l = patterns.length; i < l; ++i) {
      pattern = patterns[i];
      data = pattern.data;
      size = pattern.width;
      for (y = 0; y < size; ++y) {
        for (x = 0; x < size; ++x) {
          if (orthogonal) {
            calculateOrthogonalAreaForPattern(i, x, y, offset, result);
          } else {
            calculateDiagonalAreaForPattern(i, x, y, offset, result);
          }
          c = (y * size + x) * 2;
          data[c] = result.x * 255;
          data[c + 1] = result.y * 255;
        }
      }
    }
  }
  function assemble(base, patterns, edges, size, orthogonal, target) {
    var p = new three.Vector2();
    var dstData = target.data;
    var dstWidth = target.width;
    var i = void 0,
        l = void 0;
    var x = void 0,
        y = void 0;
    var c = void 0,
        d = void 0;
    var edge = void 0;
    var pattern = void 0;
    var srcData = void 0,
        srcWidth = void 0;
    for (i = 0, l = patterns.length; i < l; ++i) {
      edge = edges[i];
      pattern = patterns[i];
      srcData = pattern.data;
      srcWidth = pattern.width;
      for (y = 0; y < size; ++y) {
        for (x = 0; x < size; ++x) {
          p.fromArray(edge).multiplyScalar(size);
          p.add(base);
          p.x += x;
          p.y += y;
          c = (p.y * dstWidth + p.x) * 2;
          d = orthogonal ? (y * y * srcWidth + x * x) * 2 : (y * srcWidth + x) * 2;
          dstData[c] = srcData[d];
          dstData[c + 1] = srcData[d + 1];
        }
      }
    }
  }
  var SMAAAreaImageData = function() {
    function SMAAAreaImageData() {
      classCallCheck(this, SMAAAreaImageData);
    }
    createClass(SMAAAreaImageData, null, [{
      key: "generate",
      value: function generate() {
        var width = 2 * 5 * ORTHOGONAL_SIZE;
        var height = orthogonalSubsamplingOffsets.length * 5 * ORTHOGONAL_SIZE;
        var data = new Uint8ClampedArray(width * height * 2);
        var result = new RawImageData(width, height, data, 2);
        var orthogonalPatternSize = Math.pow(ORTHOGONAL_SIZE - 1, 2) + 1;
        var diagonalPatternSize = DIAGONAL_SIZE;
        var orthogonalPatterns = [];
        var diagonalPatterns = [];
        var base = new three.Vector2();
        var i = void 0,
            l = void 0;
        for (i = 0; i < 16; ++i) {
          orthogonalPatterns.push(new RawImageData(orthogonalPatternSize, orthogonalPatternSize, new Uint8ClampedArray(orthogonalPatternSize * orthogonalPatternSize * 2), 2));
          diagonalPatterns.push(new RawImageData(diagonalPatternSize, diagonalPatternSize, new Uint8ClampedArray(diagonalPatternSize * diagonalPatternSize * 2), 2));
        }
        for (i = 0, l = orthogonalSubsamplingOffsets.length; i < l; ++i) {
          generatePatterns(orthogonalPatterns, orthogonalSubsamplingOffsets[i], true);
          base.set(0, 5 * ORTHOGONAL_SIZE * i);
          assemble(base, orthogonalPatterns, orthogonalEdges, ORTHOGONAL_SIZE, true, result);
        }
        for (i = 0, l = diagonalSubsamplingOffsets.length; i < l; ++i) {
          generatePatterns(diagonalPatterns, diagonalSubsamplingOffsets[i], false);
          base.set(5 * ORTHOGONAL_SIZE, 4 * DIAGONAL_SIZE * i);
          assemble(base, diagonalPatterns, diagonalEdges, DIAGONAL_SIZE, false, result);
        }
        return result;
      }
    }]);
    return SMAAAreaImageData;
  }();
  var edges = new Map([[bilinear([0, 0, 0, 0]), [0, 0, 0, 0]], [bilinear([0, 0, 0, 1]), [0, 0, 0, 1]], [bilinear([0, 0, 1, 0]), [0, 0, 1, 0]], [bilinear([0, 0, 1, 1]), [0, 0, 1, 1]], [bilinear([0, 1, 0, 0]), [0, 1, 0, 0]], [bilinear([0, 1, 0, 1]), [0, 1, 0, 1]], [bilinear([0, 1, 1, 0]), [0, 1, 1, 0]], [bilinear([0, 1, 1, 1]), [0, 1, 1, 1]], [bilinear([1, 0, 0, 0]), [1, 0, 0, 0]], [bilinear([1, 0, 0, 1]), [1, 0, 0, 1]], [bilinear([1, 0, 1, 0]), [1, 0, 1, 0]], [bilinear([1, 0, 1, 1]), [1, 0, 1, 1]], [bilinear([1, 1, 0, 0]), [1, 1, 0, 0]], [bilinear([1, 1, 0, 1]), [1, 1, 0, 1]], [bilinear([1, 1, 1, 0]), [1, 1, 1, 0]], [bilinear([1, 1, 1, 1]), [1, 1, 1, 1]]]);
  function lerp$1(a, b, p) {
    return a + (b - a) * p;
  }
  function bilinear(e) {
    var a = lerp$1(e[0], e[1], 1.0 - 0.25);
    var b = lerp$1(e[2], e[3], 1.0 - 0.25);
    return lerp$1(a, b, 1.0 - 0.125);
  }
  function deltaLeft(left, top) {
    var d = 0;
    if (top[3] === 1) {
      d += 1;
    }
    if (d === 1 && top[2] === 1 && left[1] !== 1 && left[3] !== 1) {
      d += 1;
    }
    return d;
  }
  function deltaRight(left, top) {
    var d = 0;
    if (top[3] === 1 && left[1] !== 1 && left[3] !== 1) {
      d += 1;
    }
    if (d === 1 && top[2] === 1 && left[0] !== 1 && left[2] !== 1) {
      d += 1;
    }
    return d;
  }
  var SMAASearchImageData = function() {
    function SMAASearchImageData() {
      classCallCheck(this, SMAASearchImageData);
    }
    createClass(SMAASearchImageData, null, [{
      key: "generate",
      value: function generate() {
        var width = 66;
        var height = 33;
        var croppedWidth = 64;
        var croppedHeight = 16;
        var data = new Uint8ClampedArray(width * height);
        var croppedData = new Uint8ClampedArray(croppedWidth * croppedHeight);
        var x = void 0,
            y = void 0;
        var s = void 0,
            t = void 0,
            i = void 0;
        var e1 = void 0,
            e2 = void 0;
        for (y = 0; y < height; ++y) {
          for (x = 0; x < width; ++x) {
            s = 0.03125 * x;
            t = 0.03125 * y;
            if (edges.has(s) && edges.has(t)) {
              e1 = edges.get(s);
              e2 = edges.get(t);
              data[y * width + x] = 127 * deltaLeft(e1, e2);
              data[y * width + x + width / 2] = 127 * deltaRight(e1, e2);
            }
          }
        }
        for (i = 0, y = height - croppedHeight; y < height; ++y) {
          for (x = 0; x < croppedWidth; ++x, ++i) {
            croppedData[i] = data[y * width + x];
          }
        }
        return new RawImageData(croppedWidth, croppedHeight, croppedData, 1);
      }
    }]);
    return SMAASearchImageData;
  }();
  exports.EffectComposer = EffectComposer;
  exports.BloomPass = BloomPass;
  exports.BlurPass = BlurPass;
  exports.BokehPass = BokehPass;
  exports.Bokeh2Pass = Bokeh2Pass;
  exports.ClearPass = ClearPass;
  exports.ClearMaskPass = ClearMaskPass;
  exports.DotScreenPass = DotScreenPass;
  exports.FilmPass = FilmPass;
  exports.GlitchMode = GlitchMode;
  exports.GlitchPass = GlitchPass;
  exports.GodRaysPass = GodRaysPass;
  exports.MaskPass = MaskPass;
  exports.Pass = Pass;
  exports.PixelationPass = PixelationPass;
  exports.RenderPass = RenderPass;
  exports.SavePass = SavePass;
  exports.ShaderPass = ShaderPass;
  exports.ShockWavePass = ShockWavePass;
  exports.SMAAPass = SMAAPass;
  exports.TexturePass = TexturePass;
  exports.ToneMappingPass = ToneMappingPass;
  exports.AdaptiveLuminosityMaterial = AdaptiveLuminosityMaterial;
  exports.BokehMaterial = BokehMaterial;
  exports.Bokeh2Material = Bokeh2Material;
  exports.CombineMaterial = CombineMaterial;
  exports.ConvolutionMaterial = ConvolutionMaterial;
  exports.CopyMaterial = CopyMaterial;
  exports.DotScreenMaterial = DotScreenMaterial;
  exports.FilmMaterial = FilmMaterial;
  exports.GlitchMaterial = GlitchMaterial;
  exports.GodRaysMaterial = GodRaysMaterial;
  exports.KernelSize = KernelSize;
  exports.LuminosityMaterial = LuminosityMaterial;
  exports.PixelationMaterial = PixelationMaterial;
  exports.ShockWaveMaterial = ShockWaveMaterial;
  exports.SMAABlendMaterial = SMAABlendMaterial;
  exports.SMAAColorEdgesMaterial = SMAAColorEdgesMaterial;
  exports.SMAAWeightsMaterial = SMAAWeightsMaterial;
  exports.ToneMappingMaterial = ToneMappingMaterial;
  exports.RawImageData = RawImageData;
  exports.SMAAAreaImageData = SMAAAreaImageData;
  exports.SMAASearchImageData = SMAASearchImageData;
  Object.defineProperty(exports, '__esModule', {value: true});
})));

})();
(function() {
var define = $__System.amdDefine;
define("4f", ["4e"], function(main) {
  return main;
});

})();
$__System.register('50', ['2', '3', '6', '7', '11', '28', '4a', 'a', 'd', 'c', 'f', '4b', '4c', '4f'], function (_export) {
	var FrameBuffer, THREE, parameters, FilterScene, uniforms, clamp, _Object$keys, assets, renderer, RaymarchingScene, TextScene, MainScene, timeline, FX;

	return {
		setters: [function (_) {
			FrameBuffer = _['default'];
		}, function (_6) {
			THREE = _6;
		}, function (_3) {
			parameters = _3['default'];
		}, function (_4) {
			FilterScene = _4['default'];
		}, function (_2) {
			uniforms = _2['default'];
		}, function (_5) {
			clamp = _5.clamp;
		}, function (_a) {
			_Object$keys = _a['default'];
		}, function (_a2) {
			assets = _a2['default'];
		}, function (_d) {
			renderer = _d['default'];
		}, function (_c) {
			RaymarchingScene = _c['default'];
		}, function (_f) {
			TextScene = _f['default'];
		}, function (_b) {
			MainScene = _b['default'];
		}, function (_c2) {
			timeline = _c2;
		}, function (_f2) {
			FX = _f2;
		}],
		execute: function () {
			'use strict';

			_export('default', function () {
				var frameScene = undefined,
				    frameRaymarch = undefined,
				    frameText = undefined;
				var cameraArray = undefined;
				var filterScene = undefined,
				    mainScene = undefined,
				    rayScene = undefined,
				    textScene = undefined;
				var composer = undefined,
				    pass = undefined,
				    clock = undefined;
				var time = 0;
				var delayFPS = 1.,
				    lodRaymarch = 4.,
				    startToLag = 0.;
				var ready = false;
				var started = false;

				requestAnimationFrame(animate);

				assets.load(function () {

					var start = document.getElementById('start');
					start.innerHTML = 'start';
					start.addEventListener('click', function (e) {
						start.innerHTML = '';

						_Object$keys(parameters.show).forEach(function (key) {
							uniforms[key] = { value: parameters.show[key] };
						});

						var w = window.innerWidth;
						var h = window.innerHeight;
						frameScene = new FrameBuffer(w, h, THREE.RGBAFormat, THREE.FloatType);
						frameRaymarch = new FrameBuffer(w / lodRaymarch, h / lodRaymarch, THREE.RGBAFormat, THREE.FloatType);
						frameText = new FrameBuffer(w, h, THREE.RGBAFormat, THREE.FloatType);
						filterScene = new FilterScene();
						rayScene = new RaymarchingScene();
						textScene = new TextScene();
						mainScene = new MainScene();
						composer = new FX.EffectComposer(renderer);
						composer.addPass(new FX.RenderPass(filterScene.scene, filterScene.camera));
						cameraArray = [textScene.camera, mainScene.camera];
						var bloom = new FX.BloomPass();
						bloom.renderToScreen = true;
						composer.addPass(bloom);
						clock = new THREE.Clock();
						onWindowResize();
						window.addEventListener('resize', onWindowResize, false);

						ready = true;
					});
				});

				function animate(elapsed) {
					requestAnimationFrame(animate);

					if (ready) {
						if (!started && timeline.isReady) {
							console.log('hello');
							started = true;
							timeline.start();
						}
						if (started) {
							time = timeline.getTime();

							checkFrameRate();

							mainScene.update(time);
							rayScene.update(time);
							textScene.update(time);
							uniforms.time.value = time;

							_Object$keys(parameters.show).forEach(function (key) {
								// gui parameters
								// uniforms[key].value = parameters.show[key];
								// blender animation parameters
								uniforms[key].value = assets.animations.getValue(key, time);
							});

							// render to textures
							renderer.render(mainScene.scene, mainScene.camera, frameScene.getTarget(), true);
							renderer.render(rayScene.scene, mainScene.camera, frameRaymarch.getTarget(), true);
							renderer.render(textScene.scene, textScene.camera, frameText.getTarget(), true);

							// update textures
							uniforms.frameScene.value = frameScene.getTexture();
							uniforms.frameRaymarch.value = frameRaymarch.getTexture();
							uniforms.frameText.value = frameText.getTexture();

							// custom post fx
							renderer.render(filterScene.scene, filterScene.camera);

							// post processing
							composer.render(clock.getDelta());
						}
					}
				}

				function onWindowResize() {
					var w = window.innerWidth;
					var h = window.innerHeight;
					for (var i = 0; i < cameraArray.length; ++i) {
						cameraArray[i].aspect = w / h;
						cameraArray[i].updateProjectionMatrix();
					}
					frameScene.resize(w, h);
					frameRaymarch.resize(w / lodRaymarch, h / lodRaymarch);
					frameText.resize(w, h);
					composer.readBuffer.setSize(w, h);
					composer.writeBuffer.setSize(w, h);
					uniforms.resolution.value = [w, h];
					renderer.setSize(w, h);
				}

				function checkFrameRate() {
					var fps = 1. / clock.getDelta();
					if (fps < 30. && lodRaymarch < 8) {
						if (startToLag > time) {
							startToLag = time;
						}
						if (clamp((time - startToLag) / delayFPS, 0., 1.) >= 1.) {
							lodRaymarch *= 2.;
							startToLag += time + 10.;
							frameRaymarch.resize(window.innerWidth / lodRaymarch, window.innerHeight / lodRaymarch);
						}
					} else if (fps > 60. && lodRaymarch > 1) {
						if (startToLag > time) {
							startToLag = time;
						}
						if (clamp((time - startToLag) / delayFPS, 0., 1.) >= 1.) {
							lodRaymarch /= 2.;
							startToLag += time + 10.;
							frameRaymarch.resize(window.innerWidth / lodRaymarch, window.innerHeight / lodRaymarch);
						}
					} else {
						startToLag = time + 10.;
					}
				}
			});
		}
	};
});

$__System.register('1', ['50'], function (_export) {
  'use strict';

  var demo;
  return {
    setters: [function (_) {
      demo = _['default'];
    }],
    execute: function () {

      demo();
    }
  };
});

})
(function(factory) {
  factory();
});